csv - 在 Go 中高效读写 CSV

标签 csv go

下面的 Go 代码读取 10,000 条记录的 CSV(时间戳 times 和 float values),对数据运行一些操作,然后将原始值写入另一个 CSV 以及用于 score 的附加列。然而,它非常慢(即几个小时,但其中大部分是 calculateStuff()),我很好奇 CSV 读/写中是否存在任何我可以处理的低效率问题。

package main

import (
  "encoding/csv"
  "log"
  "os"
  "strconv"
)

func ReadCSV(filepath string) ([][]string, error) {
  csvfile, err := os.Open(filepath)

  if err != nil {
    return nil, err
  }
  defer csvfile.Close()

  reader := csv.NewReader(csvfile)
  fields, err := reader.ReadAll()

  return fields, nil
}

func main() {
  // load data csv
  records, err := ReadCSV("./path/to/datafile.csv")
  if err != nil {
    log.Fatal(err)
  }

  // write results to a new csv
  outfile, err := os.Create("./where/to/write/resultsfile.csv"))
  if err != nil {
    log.Fatal("Unable to open output")
  }
  defer outfile.Close()
  writer := csv.NewWriter(outfile)

  for i, record := range records {
    time := record[0]
    value := record[1]

    // skip header row
    if i == 0 {
      writer.Write([]string{time, value, "score"})
      continue
    }

    // get float values
    floatValue, err := strconv.ParseFloat(value, 64)
    if err != nil {
      log.Fatal("Record: %v, Error: %v", floatValue, err)
    }

    // calculate scores; THIS EXTERNAL METHOD CANNOT BE CHANGED
    score := calculateStuff(floatValue)

    valueString := strconv.FormatFloat(floatValue, 'f', 8, 64)
    scoreString := strconv.FormatFloat(prob, 'f', 8, 64)
    //fmt.Printf("Result: %v\n", []string{time, valueString, scoreString})

    writer.Write([]string{time, valueString, scoreString})
  }

  writer.Flush()
}

我正在寻求帮助,以尽可能快地完成此 CSV 读/写模板代码。对于这个问题的范围,我们不必担心 calculateStuff 方法。

最佳答案

您首先将文件加载到内存中,然后再对其进行处理,这对于大文件来说可能会很慢。

您需要循环调用.Read 并一次处理一行。

func processCSV(rc io.Reader) (ch chan []string) {
    ch = make(chan []string, 10)
    go func() {
        r := csv.NewReader(rc)
        if _, err := r.Read(); err != nil { //read header
            log.Fatal(err)
        }
        defer close(ch)
        for {
            rec, err := r.Read()
            if err != nil {
                if err == io.EOF {
                    break
                }
                log.Fatal(err)

            }
            ch <- rec
        }
    }()
    return
}

playground

//请注意,它大致基于 DaveC 的评论。

关于csv - 在 Go 中高效读写 CSV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32027590/

相关文章:

php - 如何将 CSV 解析为以第一个值作为键的数组?

node.js - Node : Hit endpoint that returns a CSV file and send the contents to client

mysql - golang mysql exec 占位符 "?"未展开

android - 在 Android 上使用网络

go - 为什么 Goroutine 在 Busy Loop 之后还能被调度?

R - 如何导入带有 block 的巨大 .csv?

java - 在java中使用SuperCsv读取tsv文件时出现异常

Java:如何在 Unicode Normal Form C 中创建一个字符串

unit-testing - 如何使用golang实现单元测试程序?

google-app-engine - 为什么我的存储实体使用默认值?