经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Go语言 » 查看文章
Go Web:数据存储(2)——CSV文件
来源:cnblogs  作者:骏马金龙  时间:2018/12/3 20:05:30  对本文有异议

存储到CSV文件中

本文接上一篇:内存存储

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

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

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

  1. func storeToCsv(filename string, posts map[int]*Post) {
  2. // 创建文件
  3. csvFile, err := os.Create(filename)
  4. if err != nil {
  5. panic(err)
  6. }
  7. defer csvFile.Close()
  8. // 获取csv的Writer
  9. writer := csv.NewWriter(csvFile)
  10. // 将map中的Post转换成slice,因为csv的Write需要slice参数
  11. // 并写入csv文件
  12. for _, post := range posts {
  13. record := []string{strconv.Itoa(post.Id), post.Content, post.Author}
  14. err1 := writer.Write(record)
  15. if err1 != nil {
  16. panic(err1)
  17. }
  18. }
  19. // 确保所有内存数据刷到csv文件
  20. writer.Flush()
  21. }

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

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

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

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

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

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

  1. func load(filename string) []*Post {
  2. // 打开文件
  3. file, err := os.Open(filename)
  4. if err != nil {
  5. panic(err)
  6. }
  7. defer file.Close()
  8. // 获取csv的reader
  9. reader := csv.NewReader(file)
  10. // 设置FieldsPerRecord为-1
  11. reader.FieldsPerRecord = -1
  12. // 读取文件中所有行保存到slice中
  13. records, err := reader.ReadAll()
  14. if err != nil {
  15. panic(err)
  16. }
  17. var posts []*Post
  18. // 将每一行数据保存到内存slice中
  19. for _, item := range records {
  20. id, _ := strconv.Atoi(item[0])
  21. post := &Post{Id: id, Content: item[1], Author: item[2]}
  22. posts = append(posts, post)
  23. }
  24. return posts
  25. }

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

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

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

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

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

  1. for _, post := range s {
  2. store(post)
  3. }

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

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

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

  1. package main
  2. import (
  3. "encoding/csv"
  4. "fmt"
  5. "os"
  6. "strconv"
  7. )
  8. type Post struct {
  9. Id int
  10. Content string
  11. Author string
  12. }
  13. var PostById map[int]*Post
  14. var PostsByAuthor map[string][]*Post
  15. func store(post *Post) {
  16. PostById[post.Id] = post
  17. PostsByAuthor[post.Author] = append(PostsByAuthor[post.Author], post)
  18. }
  19. func storeToCsv(filename string, posts map[int]*Post) {
  20. csvFile, err := os.Create(filename)
  21. if err != nil {
  22. panic(err)
  23. }
  24. defer csvFile.Close()
  25. writer := csv.NewWriter(csvFile)
  26. for _, post := range posts {
  27. record := []string{strconv.Itoa(post.Id), post.Content, post.Author}
  28. err1 := writer.Write(record)
  29. if err1 != nil {
  30. panic(err1)
  31. }
  32. }
  33. writer.Flush()
  34. }
  35. func load(filename string) []*Post {
  36. file, err := os.Open(filename)
  37. if err != nil {
  38. panic(err)
  39. }
  40. defer file.Close()
  41. reader := csv.NewReader(file)
  42. reader.FieldsPerRecord = -1
  43. records, err := reader.ReadAll()
  44. if err != nil {
  45. panic(err)
  46. }
  47. var posts []*Post
  48. for _, item := range records {
  49. id, _ := strconv.Atoi(item[0])
  50. post := &Post{Id: id, Content: item[1], Author: item[2]}
  51. posts = append(posts, post)
  52. }
  53. return posts
  54. }
  55. func main() {
  56. PostById = make(map[int]*Post)
  57. PostsByAuthor = make(map[string][]*Post)
  58. // 模拟几篇文章
  59. post1 := &Post{Id: 1, Content: "Hello 1", Author: "userA"}
  60. post2 := &Post{Id: 2, Content: "Hello 2", Author: "userB"}
  61. post3 := &Post{Id: 3, Content: "Hello 3", Author: "userC"}
  62. post4 := &Post{Id: 4, Content: "Hello 4", Author: "userA"}
  63. // 存储到内存中
  64. store(post1)
  65. store(post2)
  66. store(post3)
  67. store(post4)
  68. // 将内存中的map容器,保存到csv文件中
  69. storeToCsv("d:/a.csv", PostById)
  70. // 为了测试,此处将已保存在内存中的数据清空
  71. PostById = map[int]*Post{}
  72. PostsByAuthor = map[string][]*Post{}
  73. // 下面是加载csv文件
  74. s := load("d:/a.csv")
  75. for _, post := range s {
  76. store(post)
  77. }
  78. // 检索
  79. fmt.Println(PostById[1])
  80. fmt.Println(PostById[2])
  81. for _, post := range PostsByAuthor["userA"] {
  82. fmt.Println(post)
  83. }
  84. for _, post := range PostsByAuthor["userC"] {
  85. fmt.Println(post)
  86. }
  87. }

运行结果:

  1. &{1 Hello 1 userA}
  2. &{2 Hello 2 userB}
  3. &{1 Hello 1 userA}
  4. &{4 Hello 4 userA}
  5. &{3 Hello 3 userC}
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号