Golang 中的 bufio 包是帶緩沖 I/O 操作的标準庫,之前的幾篇文章詳細講解了 bufio.Reader、bufio.Writer 和 bufio.Scanner 這個幾個結構體的使用方法、特性和使用場景,本文介紹一下 bufio 包中的函數。
介紹常用函數之前,先簡單介紹下另一個結構體類型和一個函數類型:bufio.ReadWriter 和 bufio.SplitFunc,對應的定義如下:
type ReadWriter struct {
*Reader
*Writer
}
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
ReadWriter 結構體實作了 io.ReadWriter 接口,SplitFunc 是用來指定自定義分割規則的函數類型,通常結合 bufio.Scanner 使用。
建立對象函數
- func NewReader(rd io.Reader) *Reader,建立一個帶緩沖的 Reader 對象。
- func NewWriter(w io.Writer) *Writer,建立一個帶緩沖的 Writer 對象。
- func NewReadWriter(r *Reader, w *Writer) *ReadWriter,建立一個帶緩沖的 ReadWriter 對象。
- func NewReaderSize(rd io.Reader, size int) *Reader,建立一個帶緩沖的 Reader 對象,使用 size 指定緩沖區的最小值。
- func NewWriterSize(w io.Writer, size int) *Writer,建立一個帶緩沖的 Writer 對象,使用 size 指定緩沖區的最小值。
- func NewScanner(r io.Reader) *Scanner,建立一個帶緩沖的 Scanner 對象。
SplitFunc 類型函數
以下幾個函數都是 SplitFunc 類型,通常與 bufio.NewScanner 一起使用。
- func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐行讀取輸入流中的資料。
- func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐個位元組讀取輸入流中的資料。
- func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐個 unicode 編碼讀取輸入流中的資料。
- func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error),用于逐個單詞(空格分割)讀取輸入流中的資料。
使用示例
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
// 确定讀取檔案的路徑
path := "file.txt"
// 打開檔案并處理錯誤
file, err := os.Open(path)
if err != nil {
panic(err)
}
defer file.Close()
// 建立Scanner類型對象
scanner := bufio.NewScanner(file)
// 設定分割函數
scanner.Split(bufio.ScanWords)
// 建立一個map對象,用于存儲單詞出現的次數
counts := make(map[string]int)
// 讀取檔案内容并統計單詞出現次數
for scanner.Scan() {
word := strings.ToLower(scanner.Text())
counts[word]++
}
// 檢查Scanner是否出錯
if err := scanner.Err(); err != nil {
panic(err)
}
// 輸出結果到控制台
for word, count := range counts {
fmt.Printf("%s: %d\n", word, count)
}
// 讓使用者根據輸入的關鍵字進行篩選
fmt.Print("Enter keyword to filter results: ")
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
keyword := strings.TrimSpace(input)
if keyword != "" {
for word, count := range counts {
if strings.Contains(word, keyword) {
fmt.Printf("%s: %d\n", word, count)
}
}
}
}
首先建立了一個 Scanner 類型的對象,指定了 ScanWords 作為分隔函數,然後周遊檔案内容,統計單詞出現的次數并将結果存儲到一個map中,最後讓使用者輸入關鍵字進行篩選,根據關鍵字過濾并輸出結果。
小結
bufio 是一個提供了帶緩沖讀寫操作的包,通過使用 bufio 包提供的類型和方法,可以高效地讀寫資料,特别是當涉及到大量資料的讀寫時,可以大大提高程式的性能。