我需要在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/csvfile.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 關注
- 101 瀏覽
添加回答
舉報
0/150
提交
取消
