我需要在Go中处理一个大文件,所以我不想一次加载我的csv文件的所有行,而是按组处理它们。为了从我离开的位置重新开始计算行,我实际上使用for cycle来跳过已经读取的行:for idx := 0; idx < startAt; idx++ { //Read rows and do nothing with the returned value if _, readErr := reader.Read(); readErr != nil { if readErr == io.EOF { //File end -> OK isEOF = true break } else { //Read failed return nil, errors.New(DATA_READ_ERROR) } }}这是一个非常简单的解决方案;但是,它显然是低效的。阅读第一行后,阅读以下内容的时间呈指数级增长。为了减少这一时间,我尝试了不同的替代方案,但每种方法都无法正常工作,并使读取器失败(行不是从正确的地址读取的)。例如,我试图返回文件指针的当前位置(使用,然后在新的迭代中,我试图使用移动指针,但它没有按预期工作。file.Seek(0, io.SeekCurrent)file.Seek(oldPosition, io.SeekStart)有一种方法可以避免上面的循环,并在从我离开的地方重新启动时改善阅读时间?
1 回答
慕桂英546537
TA贡献1848条经验 获得超10个赞
这里的问题是内部使用缓冲读取器,因此当您执行时,您将获得基础文件上的位置,但读取了一些数据并且您没有使用它。encoding/csv
file.Seek(0, io.SeekCurrent)
有两种可能的解决方案:
一种是使用较低级别的实现,允许准确控制您所在的位置
另一个是找出有多少缓冲数据。
我将向您展示第二个选项的实现(请注意,这依赖于对包内部工作的一些了解,如果更改,可能会停止工作)encoding/csv
首先,在创建 csv 之前创建一个新的缓冲 io 读取器:
//Position the file pointer to the start point
file.Seek(startAt, io.SeekStart)
bReader := bufio.NewReader(file)
//Create a reader
reader := csv.NewReader(bReader)
这将允许您访问缓冲区。您可以像以前一样使用此读取器,但最终您可以通过以下方式计算文件上的最终位置:
bufSize := bReader.Buffered() filePos, err := file.Seek(0, io.SeekCurrent) return filePos - int64(bufSize)
这将采用文件中的当前位置并删除已创建的缓冲区。
请注意,返回的值是文件中的位置,而不是在此函数调用中读取的字节数。
- 1 回答
- 0 关注
- 63 浏览
添加回答
举报
0/150
提交
取消