php小編蘋果將為大家介紹一種精確讀取指定行數(shù)(而不是一個字節(jié))的文本的慣用語Go。在處理文本文件時,我們經(jīng)常需要讀取特定行數(shù)的內(nèi)容,而不是逐個字節(jié)讀取。使用Go語言的bufio包,我們可以輕松實現(xiàn)這個目標(biāo)。接下來,我們將詳細(xì)介紹如何使用這個慣用語來實現(xiàn)精確讀取指定行數(shù)的文本的功能。讓我們一起來探索吧!
問題內(nèi)容
我有一個來自報告生成器的 CSV,它添加了一些非 CSV 前導(dǎo)碼,例如:
Time Off Requests My Org Street Address City, State ZIP Col1,Col2,Col3 r1c1,r1c2,r1c3 r2c1,r2c2,r2c3
登錄后復(fù)制
在將文件的 io.Reader 傳遞給 csv.NewReader 并嘗試 ReadAll() 之前,我需要丟棄這 6 行,因此我需要確保我不會讀取第 6 行之后的任何一個字節(jié)。
我最初想到 bufio.Scanner 并在循環(huán)中調(diào)用 Scan() 6 次,但后來通過實驗意識到 bufio 中的“buf”意味著我無法控制緩沖讀取的結(jié)束位置,并且它可能會讀取超過真正開始的位置CSV。
所以我想出了一個辦法,就是逐字節(jié)讀取,直到數(shù)到 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() ...
登錄后復(fù)制
這有效。但是,有更慣用的 Go 方式嗎?
解決方法
您不需要避免使用 bufio
,事實上您應(yīng)該盡可能選擇使用緩沖 IO。您不能做的是通過 bufio.Reader
訪問它之后使用原始閱讀器,即,在使用 bufio.NewReader
后,不要將 os.File
傳遞給 csv.NewReader
,繼續(xù)使用 bufio.Reader
可能包含已從文件中讀取的數(shù)據(jù)。
一旦有了 bufio.Reader
,您就可以使用所有方法來讀取流的各個部分,而無需擔(dān)心逐字節(jié)讀取。
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)
登錄后復(fù)制
完整示例