php小編蘋果將為大家介紹一種精確讀取指定行數(而不是一個字節)的文本的慣用語Go。在處理文本文件時,我們經常需要讀取特定行數的內容,而不是逐個字節讀取。使用Go語言的bufio包,我們可以輕松實現這個目標。接下來,我們將詳細介紹如何使用這個慣用語來實現精確讀取指定行數的文本的功能。讓我們一起來探索吧!
問題內容
我有一個來自報告生成器的 CSV,它添加了一些非 CSV 前導碼,例如:
Time Off Requests My Org Street Address City, State ZIP Col1,Col2,Col3 r1c1,r1c2,r1c3 r2c1,r2c2,r2c3
登錄后復制
在將文件的 io.Reader 傳遞給 csv.NewReader 并嘗試 ReadAll() 之前,我需要丟棄這 6 行,因此我需要確保我不會讀取第 6 行之后的任何一個字節。
我最初想到 bufio.Scanner 并在循環中調用 Scan() 6 次,但后來通過實驗意識到 bufio 中的“buf”意味著我無法控制緩沖讀取的結束位置,并且它可能會讀取超過真正開始的位置CSV。
所以我想出了一個辦法,就是逐字節讀取,直到數到 6 個換行符 (10):
f, _ := os.Open(csvPath) // Read just past report-generated 6-line preamble b := make([]byte, 1) for i := 0; i < 6; { f.Read(b) if b[0] == 10 { i++ } } r := csv.NewReader(f) records, err = r.ReadAll() ...
登錄后復制
這有效。但是,有更慣用的 Go 方式嗎?
解決方法
您不需要避免使用 bufio
,事實上您應該盡可能選擇使用緩沖 IO。您不能做的是通過 bufio.Reader
訪問它之后使用原始閱讀器,即,在使用 bufio.NewReader
后,不要將 os.File
傳遞給 csv.NewReader
,繼續使用 bufio.Reader
可能包含已從文件中讀取的數據。
一旦有了 bufio.Reader
,您就可以使用所有方法來讀取流的各個部分,而無需擔心逐字節讀取。
buf := bufio.NewReader(f) // the preambled is defined as 6 lines for i := 0; i < 6; i++ { line, err := buf.ReadBytes('\n') if err != nil { log.Fatal(err) } fmt.Printf("line: %q\n", line) } r := csv.NewReader(buf) records, err := r.ReadAll() if err != nil { log.Fatal(err) } fmt.Printf("records: %q\n", records)
登錄后復制
完整示例