存储到CSV文件中

本文接上一篇:内存存储

关于CSV文件的说明,见csv文件格式

当数据存储到了内存中,可以在需要的时候持久化保存到磁盘文件中。比如保存为csv格式的文件,下一篇再介绍序列化持久到文件中。

下面是持久化到csv文件的函数代码:

func storeToCsv(filename string, posts map[int]*Post) {
// 创建文件
csvFile, err := os.Create(filename)
if err != nil {
panic(err)
}
defer csvFile.Close() // 获取csv的Writer
writer := csv.NewWriter(csvFile) // 将map中的Post转换成slice,因为csv的Write需要slice参数
// 并写入csv文件
for _, post := range posts {
record := []string{strconv.Itoa(post.Id), post.Content, post.Author}
err1 := writer.Write(record)
if err1 != nil {
panic(err1)
}
} // 确保所有内存数据刷到csv文件
writer.Flush()
}

这个函数的逻辑很简单,无需过多的解释。需要注意的是,os.Create()函数在文件存在时会截断文件,如有需要,可以考虑使用追加写入的相关函数。

当需要将保存在内存中的post保存到csv文件时,只需调用该函数,传递一个文件名以及PostById作为参数即可:

storeToCsv("d:/a.csv", PostById)

保存之后,以下是a.csv文件的内容:

2,Hello 2,userB
3,Hello 3,userC
4,Hello 4,userA
1,Hello 1,userA

数据保存到了csv文件,自然需要从csv文件中读取数据到内存。以下是读取csv文件的函数:

func load(filename string) []*Post {
// 打开文件
file, err := os.Open(filename)
if err != nil {
panic(err)
}
defer file.Close() // 获取csv的reader
reader := csv.NewReader(file) // 设置FieldsPerRecord为-1
reader.FieldsPerRecord = -1 // 读取文件中所有行保存到slice中
records, err := reader.ReadAll()
if err != nil {
panic(err)
} var posts []*Post
// 将每一行数据保存到内存slice中
for _, item := range records {
id, _ := strconv.Atoi(item[0])
post := &Post{Id: id, Content: item[1], Author: item[2]}
posts = append(posts, post)
}
return posts
}

逻辑也很简单,唯一需要注意的是FiledsPerRecord=-1

  • 设置为负数表示读取时每条记录的字段数量可以随意
  • 如果设置为正数N,则表示每条记录必须且只读取N个字段,如果字段少于N,则报错
  • 如果设置为0,则表示按照第一条记录所拥有的字段数量进行读取剩余记录,也就是说每一条记录的字段数量都必须和第一条记录相同

这个load()函数返回一个slice,这个slice中保存了所有读取到的文章指针。

s := load("d:/a.csv")

因为使用var PostById map[int]*Postvar PostsByAuthor map[string][]*Post保存一篇篇的文章,迭代此slice即可将slice中的post保存到这两个map中。

for _, post := range s {
store(post)
}

然后就可以从这两个map中按照Id或者按照Author进行检索:

fmt.Println(PostById[1])
fmt.Println(PostById[2])
for _, post := range PostsByAuthor["userA"] {
fmt.Println(post)
}

下面是完整的保存到csv文件以及读取csv文件的代码:

package main

import (
"encoding/csv"
"fmt"
"os"
"strconv"
) type Post struct {
Id int
Content string
Author string
} var PostById map[int]*Post
var PostsByAuthor map[string][]*Post func store(post *Post) {
PostById[post.Id] = post
PostsByAuthor[post.Author] = append(PostsByAuthor[post.Author], post)
} func storeToCsv(filename string, posts map[int]*Post) {
csvFile, err := os.Create(filename)
if err != nil {
panic(err)
}
defer csvFile.Close() writer := csv.NewWriter(csvFile) for _, post := range posts {
record := []string{strconv.Itoa(post.Id), post.Content, post.Author}
err1 := writer.Write(record)
if err1 != nil {
panic(err1)
}
} writer.Flush()
} func load(filename string) []*Post {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
defer file.Close() reader := csv.NewReader(file)
reader.FieldsPerRecord = -1
records, err := reader.ReadAll()
if err != nil {
panic(err)
} var posts []*Post
for _, item := range records {
id, _ := strconv.Atoi(item[0])
post := &Post{Id: id, Content: item[1], Author: item[2]}
posts = append(posts, post)
}
return posts
} func main() {
PostById = make(map[int]*Post)
PostsByAuthor = make(map[string][]*Post) // 模拟几篇文章
post1 := &Post{Id: 1, Content: "Hello 1", Author: "userA"}
post2 := &Post{Id: 2, Content: "Hello 2", Author: "userB"}
post3 := &Post{Id: 3, Content: "Hello 3", Author: "userC"}
post4 := &Post{Id: 4, Content: "Hello 4", Author: "userA"}
// 存储到内存中
store(post1)
store(post2)
store(post3)
store(post4) // 将内存中的map容器,保存到csv文件中
storeToCsv("d:/a.csv", PostById) // 为了测试,此处将已保存在内存中的数据清空
PostById = map[int]*Post{}
PostsByAuthor = map[string][]*Post{} // 下面是加载csv文件
s := load("d:/a.csv")
for _, post := range s {
store(post)
} // 检索
fmt.Println(PostById[1])
fmt.Println(PostById[2])
for _, post := range PostsByAuthor["userA"] {
fmt.Println(post)
}
for _, post := range PostsByAuthor["userC"] {
fmt.Println(post)
}
}

运行结果:

&{1 Hello 1 userA}
&{2 Hello 2 userB}
&{1 Hello 1 userA}
&{4 Hello 4 userA}
&{3 Hello 3 userC}

Go Web:数据存储(2)——CSV文件的更多相关文章

  1. 直接把数据库中的数据保存在CSV文件中

    今天突然去聊就来写一个小小的demo喽,嘿嘿 public partial class Form1 : Form { public Form1() { InitializeComponent(); } ...

  2. <Android基础> (六) 数据存储 Part 1 文件存储方式

    第六章 数据存储 6.1 持久化技术 持久化技术指将内存中的瞬时数据保存到存储设备中,保证即使在手机或电脑关机的情况下,这些数据仍然不会丢失. 主要有三种方式用于简单地实现数据持久化功能:文件存储.S ...

  3. python3下scrapy爬虫(第九卷:scrapy数据存储进JSON文件)

    将爬取数据存储在JSON文件里并不难,只需修改pipelines文件 直接看代码: 来看下结果: 中文字符恶心的很 之后我会在后卷中做出修改

  4. 数据存储之json文件处理和csv文件处理

    什么是json: JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式.它基于 ECMAScript (w3c制定的js规范)的一个子集,采用 ...

  5. python爬虫#数据存储#JSON/CSV/MYSQL/MongoDB/

    Json数据处理 JSON支持数据格式: 对象(字典).使用花括号. 数组(列表).使用方括号. 整形.浮点型.布尔类型还有null类型. 字符串类型(字符串必须要用双引号,不能用单引号). 多个数据 ...

  6. Web 端 js 导出csv文件(使用a标签)

    前言 导出文件,使用最多的方式还是服务器端来处理.比如jsp 中使用response 的方式. 但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格. 这 ...

  7. Android 数据存储02之文件读写

    Android文件读写 版本 修改内容 日期 修改人 V1.0 原始版本 2013/2/25 skywang Android文件读写的有两种方式.一种,是通过标准的JavaIO库去读写.另一种,是通过 ...

  8. Android开发--数据存储之File文件存储

    转载来自:http://blog.csdn.net/ahuier/article/details/10364757,并进行扩充 引言:Android开发中的数据存储方式 Android提供了5种方式存 ...

  9. vue.js纯前端处理如何将后台返回来的csv数据导出成csv文件

    需要实现一个下载csv文件的功能,但后台没有对这个下载文件进行处理,而是将csv数据传给前台而已,需要前台做一下处理. 这是按钮的代码: <a> <el-button size=&q ...

随机推荐

  1. CentOS 7 nginx 1.8.1安装

    OS版本:CentOS 7.2nginx版本:1.8.1所需包:openssl-1.0.2m.tar.gz zlib-1.2.8.tar.gz pcre-8.36.tar.gz nginx-1.8.1 ...

  2. Solaris:你好奇的十件事

    想想你周围的人,看看他们正在使用的操作系统.绝大部分人的电脑都在用主流操作系统:Windows,MacOS,甚至是Ubuntu.当说到Solaris,Unix和BSD的时候,其他人还以为你说鸟语呢.除 ...

  3. pdf流文件的展示、下载、打印;html转为pdf

    背景:合同(后台返回pdf流文件)展示.下载.打印,基于angular4 场景区分: 1.checkout页面 —— post接口,入参为offering.shippingInfo.invoice等( ...

  4. Astrology PHP 框架

    1.Web 服务器配置 PHP 支持 URL Rewrite.PATH_INFO 2.环境需求 PHP 7.2+ 扩展:gettext 3.目录结构 + src | - autoload.php | ...

  5. ELK从5.6.3升级到6.3.0总结

    ELK从5.6.3升级到6.3.0总结 由于6.3.0默认有es的监控功能,并且我们现在es总是有各种问题,原有的es开源插件head和HQ的监控都不够详细,所以决定升级es集群.我们目前es有5个n ...

  6. 5-Django接口数据处理

    1.get接口数据处理 # get接口数据处理 def dadaHandle_get(request): if request.method == 'GET': results = {} userna ...

  7. 从零起步做到Linux运维经理, 你必须管好的23个细节

    “不想成为将军的士兵,不是好士兵”-拿破仑 如何成为运维经理? 一般来说,运维经理大概有两种出身:一种是从底层最基础的维护做起,通过出色的维护工作,让公司领导对这个人非常认可,同时对Linux运维工作 ...

  8. 推导正交投影(Orthographic Projection)

    定义六个面 left right bottom top near far   然后三个轴分开考虑 x轴 视椎体的x范围在[l,r],我们要变换到[-1,1] 1 减去l变换到[0, r-l] 2 乘以 ...

  9. Windows反复重启的可能的解决办法

    Windows反复重启,原因很多,下面提供两个可能的解决办法: 1. 查看BIOS中关于SATA的设置,一般只有两种PCIE和IDE,调整成另外一个试试: 2. 查看BIOS的启动模式,如果是UEFI ...

  10. EmpireCMS_V7.5的一次审计

    i春秋作家:Qclover 原文来自:EmpireCMS_V7.5的一次审计 EmpireCMS_V7.5的一次审计 1概述    最近在做审计和WAF规则的编写,在CNVD和CNNVD等漏洞平台寻找 ...