CSV转换为日期和浮点数

3

我目前正在编写一个小程序,将CSV文件转换为结构体以供进一步处理。CSV行的格式如下:

20140102,09:30,38.88,38.88,38.82,38.85,67004

我有500个文件,每个文件大小约为20-30 MB。我的代码可以正常工作,但我不禁想知道是否有比我现在所做的更好的方法来转换这些文件。首先读取文件并将其转换为csv记录(伪代码)。

    data, err := ioutil.ReadFile(path)
    if err != nil {
        ... 
    }
    r := csv.NewReader(bytes.NewReader(data))
    records, err := r.ReadAll()
    if err != nil {
        ... 
    }

然后循环遍历所有记录并执行

    parsedTime, err := time.Parse("2006010215:04", record[0]+record[1])
    if err != nil {
        return model.ZorroT6{}, time.Time{}, err
    }

    t6.Date = ConvertToOle(parsedTime)
    if open, err := strconv.ParseFloat(record[2], 32); err == nil {
        t6.Open = float32(open)
    }
    if high, err := strconv.ParseFloat(record[3], 32); err == nil {
        t6.High = float32(high)
    }
    if low, err := strconv.ParseFloat(record[4], 32); err == nil {
        t6.Low = float32(low)
    }
    if close, err := strconv.ParseFloat(record[5], 32); err == nil {
        t6.Close = float32(close)
    }
    if vol, err := strconv.ParseInt(record[6], 10,32); err == nil {
        t6.Vol = int32(vol)
    }

例如,我必须经过 []byte -> string -> float64 -> float32 的转换才能获得我的浮点值。我该怎么做来改善这段代码呢?
编辑:只是为了明确,我并不是真的需要提高性能,我只是更好地尝试理解Go以及可以应用于此类问题的性能优化。例如,当我有一个字节切片并且想要一个float32时,创建大量字符串和float64似乎是很多开销。

1
我认为这段代码不需要改进。现在需要多长时间,你希望它需要多长时间?你是否对程序进行了分析,确定瓶颈确实在这里? - leaf bebop
我并不真正需要提高速度,但为了更好地理解Go语言,我想尝试一下。我已经对应用程序进行了分析,目前大部分时间都花在readRecord(由readAll调用)、time.Parse和parseFloat上。 - Daniel
1个回答

1
我只看到一个需要修复的问题:
不要将ioutil.ReadFilebytes.NewReader一起使用。当文件很大时,它会将所有内容读入内存,这是低效的。
相反,使用os.Open(file),它完美地提供了一个io.Reader,可以被csv.NewReader利用。不要忘记关闭文件并处理错误。
如果您仍然想提高性能:
  1. 由于您的csv文件具有固定格式,因此可以使用bufio提供的原始字节,而不是csv
  2. 您可以复制并粘贴strconvtime中的基础代码以避免不需要的通用代码。
但我认为它们不值得麻烦。

谢谢,我会看看是否可以使用os.Open()代替。我实际上快速查看了bufio,但由于我仍然找不到一种将[]byte从bufio转换为float32或time的方法而不经过字符串,因此我没有进一步深入。但我想我可以结合1)和2),并编写函数以接受[]byte而不是字符串。这可能是一个下雨天的好项目;-) 再次感谢,非常感谢您的回复。 - Daniel
1
@Daniel请注意,这可能会影响您未来的维护工作。 - leaf bebop
当然,这不是我为生产系统做的事情。更多地是作为一种学习体验,并了解从提取和修改内部API等更极端措施中可以获得什么样的性能提升。当前代码大约在100秒内解析了约10GB的数据,这已经足够快了。 - Daniel
我只是出于好玩尝试了一下。让parseFloat直接返回float32对性能完全没有任何影响。将其更改为接受[]byte而不是字符串可以将分配减少一半,所以如果您遇到问题,这可能值得进一步探索。但正如您已经说过的那样,这可能并不值得麻烦。 - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接