這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
本文轉自GOlove部落格:http://www.cnblogs.com/golove/p/3282667.html 並在此基礎上進行了一些添加修改.
bufio 包中的函數和方法
// bufio 包實現了帶緩衝的 I/O 操作
// 它封裝一個 io.Reader 或 io.Writer 對象
// 使其具有緩衝和一些文本讀寫功能
------------------------------------------------------------
// bufio.go
------------------------------------------------------------
type Reader struct { buf []byte rd io.Reader // reader provided by the client r, w int // buf read and write positions err error lastByte int lastRuneSize int }
// NewReaderSize 將 rd 封裝成一個擁有 size 大小緩衝的 bufio.Reader 對象
// 如果 rd 的基底類型就是 bufio.Reader 類型,而且擁有足夠的緩衝
// 則直接將 rd 轉換為基底類型並返回
func NewReaderSize(rd io.Reader, size int) *Reader
// NewReader 相當於 NewReaderSize(rd, 4096)
func NewReader(rd io.Reader) *Reader
------------------------------------------------------------
// Peek 返回緩衝的一個切片,該切片引用緩衝中前 n 位元組資料
// 該操作不會將資料讀出,只是引用
// 引用的資料在下一次讀取操作之前是有效
// 如果引用的資料長度小於 n,則返回一個錯誤資訊
// 如果 n 大於緩衝的總大小,則返回 ErrBufferFull
// 通過 Peek 的傳回值,可以修改緩衝中的資料
// 但是不能修改底層 io.Reader 中的資料
func main() {s := strings.NewReader("ABCDEFG")br := bufio.NewReader(s)b, _ := br.Peek(5)fmt.Printf("%s\n", b)// ABCDEb[0] = 'a'b, _ = br.Peek(5)fmt.Printf("%s\n", b)// aBCDE}
------------------------------------------------------------
// Read 從 b 中讀出資料到 p 中,返回讀出的位元組數
// 如果 p 的大小 >= 緩衝的總大小,而且緩衝不為空白
// 則只能讀出緩衝中的資料,不會從底層 io.Reader 中提取資料
// 如果 p 的大小 >= 緩衝的總大小,而且緩衝為空白
// 則直接從底層 io.Reader 向 p 中讀出資料,不經過緩衝
// 只有當 b 中無可讀資料時,才返回 (0, io.EOF)
func (b *Reader) Read(p []byte) (n int, err error)
func main() {s := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")br := bufio.NewReader(s)b := make([]byte, 20)n, err := br.Read(b)fmt.Printf("%-20s %-2v %v\n", b[:n], n, err)// ABCDEFGHIJKLMNOPQRST 20 <nil>n, err = br.Read(b)fmt.Printf("%-20s %-2v %v\n", b[:n], n, err)// UVWXYZ1234567890 16 <nil>n, err = br.Read(b)fmt.Printf("%-20s %-2v %v\n", b[:n], n, err)// 0 EOF}
------------------------------------------------------------
// ReadByte 從 b 中讀出一個位元組並返回
// 如果 b 中無可讀資料,則返回一個錯誤
func (b *Reader) ReadByte() (c byte, err error)
// UnreadByte 撤消最後一次讀出的位元組
// 只有最後讀出的位元組可以被撤消
// 無論任何操作,只要有內容被讀出,就可以用 UnreadByte 撤消一個位元組
func (b *Reader) UnreadByte() error
func main() {s := strings.NewReader("ABCDEFG")br := bufio.NewReader(s)c, _ := br.ReadByte()fmt.Printf("%c\n", c)// Ac, _ = br.ReadByte()fmt.Printf("%c\n", c)// Bbr.UnreadByte()c, _ = br.ReadByte()fmt.Printf("%c\n", c)// B}
------------------------------------------------------------
// ReadRune 從 b 中讀出一個 UTF8 編碼的字元並返回
// 同時返回該字元的 UTF8 編碼長度
// 如果 UTF8 序列無法解碼出一個正確的 Unicode 字元
// 則唯讀出 b 中的一個位元組,並返回 U+FFFD 字元,size 返回 1
func (b *Reader) ReadRune() (r rune, size int, err error)
// UnreadRune 撤消最後一次讀出的 Unicode 字元
// 如果最後一次執行的不是 ReadRune 操作,則返回一個錯誤
// 因此,UnreadRune 比 UnreadByte 更嚴格
func (b *Reader) UnreadRune() error
func main() {s := strings.NewReader("你好,世界!")br := bufio.NewReader(s)c, size, _ := br.ReadRune()fmt.Printf("%c %v\n", c, size)// 你 3c, size, _ = br.ReadRune()fmt.Printf("%c %v\n", c, size)// 好 3br.UnreadRune()c, size, _ = br.ReadRune()fmt.Printf("%c %v\n", c, size)// 好 3}
------------------------------------------------------------
// Buffered 返回緩衝中資料的長度
func (b *Reader) Buffered() intfunc main() {s := strings.NewReader("你好,世界!")br := bufio.NewReader(s)fmt.Println(br.Buffered())// 0br.Peek(1)fmt.Println(br.Buffered())// 18}
------------------------------------------------------------
// ReadSlice 在 b 中尋找 delim 並返回 delim 及其之前的所有資料的切片
// 該操作會讀出資料,返回的切片是已讀出資料的引用
// 切片中的資料在下一次讀取操作之前是有效
//
// 如果 ReadSlice 在找到 delim 之前遇到錯誤
// 則讀出緩衝中的所有資料並返回,同時返回遇到的錯誤(通常是 io.EOF)
// 如果在整個緩衝中都找不到 delim,則 err 返回 ErrBufferFull
// 如果 ReadSlice 能找到 delim,則 err 始終返回 nil
//
// 因為返回的切片中的資料有可能被下一次讀寫操作修改
// 因此大多數操作應該使用 ReadBytes 或 ReadString,它們返回的不是資料引用
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
func main() {s := strings.NewReader("ABC DEF GHI JKL")br := bufio.NewReader(s)w, _ := br.ReadSlice(' ')fmt.Printf("%q\n", w)// "ABC "w, _ = br.ReadSlice(' ')fmt.Printf("%q\n", w)// "DEF "w, _ = br.ReadSlice(' ')fmt.Printf("%q\n", w)// "GHI "}
------------------------------------------------------------
// ReadLine 是一個低級的原始的行讀取操作
// 大多數情況下,應該使用 ReadBytes('\n') 或 ReadString('\n')
// 或者使用一個 Scanner
//
// ReadLine 通過調用 ReadSlice 方法實現,返回的也是緩衝的切片
// ReadLine 嘗試返回一個單行資料,不包括行尾標記(\n 或 \r\n)
// 如果在緩衝中找不到行尾標記,則設定 isPrefix 為 true,表示尋找未完成
// 同時讀出緩衝中的資料並作為切片返回
// 只有在當前緩衝中找到行尾標記,才將 isPrefix 設定為 false,表示尋找完成
// 可以多次調用 ReadLine 來讀出一行
// 返回的資料在下一次讀取操作之前是有效
// 如果 ReadLine 無法擷取任何資料,則返回一個錯誤資訊(通常是 io.EOF)
func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)
func main() {s := strings.NewReader("ABC\nDEF\r\nGHI\r\nJKL")br := bufio.NewReader(s)w, isPrefix, _ := br.ReadLine()fmt.Printf("%q %v\n", w, isPrefix)// "ABC" falsew, isPrefix, _ = br.ReadLine()fmt.Printf("%q %v\n", w, isPrefix)// "DEF" falsew, isPrefix, _ = br.ReadLine()fmt.Printf("%q %v\n", w, isPrefix)// "GHI" false}
------------------------------------------------------------
// ReadBytes 在 b 中尋找 delim 並讀出 delim 及其之前的所有資料
// 如果 ReadBytes 在找到 delim 之前遇到錯誤
// 則返回遇到錯誤之前的所有資料,同時返回遇到的錯誤(通常是 io.EOF)
// 只有當 ReadBytes 找不到 delim 時,err 才不為 nil
// 對於簡單的用途,使用 Scanner 可能更方便
func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
func main() {s := strings.NewReader("ABC DEF GHI JKL")br := bufio.NewReader(s)w, _ := br.ReadBytes(' ')fmt.Printf("%q\n", w)// "ABC "w, _ = br.ReadBytes(' ')fmt.Printf("%q\n", w)// "DEF "w, _ = br.ReadBytes(' ')fmt.Printf("%q\n", w)// "GHI "}
------------------------------------------------------------
// ReadString 功能同 ReadBytes,只不過返回的是一個字串
func (b *Reader) ReadString(delim byte) (line string, err error)
func main() {s := strings.NewReader("ABC DEF GHI JKL")br := bufio.NewReader(s)w, _ := br.ReadString(' ')fmt.Printf("%q\n", w)// "ABC "w, _ = br.ReadString(' ')fmt.Printf("%q\n", w)// "DEF "w, _ = br.ReadString(' ')fmt.Printf("%q\n", w)// "GHI "}
------------------------------------------------------------
// WriteTo 實現了 io.WriterTo 介面
func (b *Reader) WriteTo(w io.Writer) (n int64, err error)
func main() {s := strings.NewReader("ABCEFG")br := bufio.NewReader(s)b := bytes.NewBuffer(make([]byte, 0))br.WriteTo(b)fmt.Printf("%s\n", b)// ABCEFG}
------------------------------------------------------------
func (b *Reader) Reset(r io.Reader)
reset丟棄任何的快取資料,叢植所有狀態並且將緩衝讀切換到r
package mainimport ("bufio""fmt""strings")func main() {s := strings.NewReader("ABCEFG")str := strings.NewReader("123455")br := bufio.NewReader(s)b, _ := br.ReadString('\n')fmt.Println(b) //ABCEFGbr.Reset(str)b, _ = br.ReadString('\n')fmt.Println(b) //123455}
------------------------------------------------------------
------------------------------------------------------------
// Writer 實現了帶緩衝的 io.Writer 對象
// 如果在向 Writer 中寫入資料的過程中遇到錯誤
// 則 Writer 不會再接受任何資料
// 而且後續的寫入操作都將返回錯誤資訊
type Writer struct {
err error buf []byte n int wr io.Writer
}
// NewWriterSize 將 wr 封裝成一個擁有 size 大小緩衝的 bufio.Writer 對象
// 如果 wr 的基底類型就是 bufio.Writer 類型,而且擁有足夠的緩衝
// 則直接將 wr 轉換為基底類型並返回
func NewWriterSize(wr io.Writer, size int) *Writer
// NewWriter 相當於 NewWriterSize(wr, 4096)
func NewWriter(wr io.Writer) *Writer
------------------------------------------------------------
// Flush 將緩衝中的資料提交到底層的 io.Writer 中
func (b *Writer) Flush() error
// Available 返回緩衝中的可以空間
func (b *Writer) Available() int
// Buffered 返回緩衝中未提交的資料長度
func (b *Writer) Buffered() int
// Write 將 p 中的資料寫入 b 中,返回寫入的位元組數
// 如果寫入的位元組數小於 p 的長度,則返回一個錯誤資訊
func (b *Writer) Write(p []byte) (nn int, err error)
// WriteString 同 Write,只不過寫入的是字串
func (b *Writer) WriteString(s string) (int, error)
func main() { b := bytes.NewBuffer(make([]byte, 0)) bw := bufio.NewWriter(b) fmt.Println(bw.Available()) // 4096 fmt.Println(bw.Buffered()) // 0 bw.WriteString("ABCDEFGH") fmt.Println(bw.Available()) // 4088 fmt.Println(bw.Buffered()) // 8 fmt.Printf("%q\n", b) // "" bw.Flush() fmt.Println(bw.Available()) // 4096 fmt.Println(bw.Buffered()) // 0 fmt.Printf("%q\n", b) // "ABCEFG"}
------------------------------------------------------------
// WriteByte 向 b 中寫入一個位元組
func (b *Writer) WriteByte(c byte) error
// WriteRune 向 b 中寫入 r 的 UTF8 編碼
// 返回 r 的編碼長度
func (b *Writer) WriteRune(r rune) (size int, err error)
func main() { b := bytes.NewBuffer(make([]byte, 0)) bw := bufio.NewWriter(b) bw.WriteByte('H') bw.WriteByte('e') bw.WriteByte('l') bw.WriteByte('l') bw.WriteByte('o') bw.WriteByte(' ') bw.WriteRune('世') bw.WriteRune('界') bw.WriteRune('!') bw.Flush() fmt.Println(b) // Hello 世界!}
------------------------------------------------------------
// ReadFrom 實現了 io.ReaderFrom 介面
func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
func main() {b := bytes.NewBuffer(make([]byte, 0))s := strings.NewReader("Hello 世界!")bw := bufio.NewWriter(b)bw.ReadFrom(s)//bw.Flush() //ReadFrom無需使用Flush,其自己已經寫入.fmt.Println(b) // Hello 世界!}
------------------------------------------------------------
func (b *Writer) Reset(w io.Writer)
Reset丟棄任何沒有寫入的快取資料,清除任何錯誤並且重新將b指定它的輸出結果指向w
package mainimport ("bufio""bytes""fmt")func main() {b := bytes.NewBuffer(make([]byte, 0))bw := bufio.NewWriter(b)bw.WriteString("123")c := bytes.NewBuffer(make([]byte, 0))bw.Reset(c)bw.WriteString("456")bw.Flush()fmt.Println(b) //輸出為空白fmt.Println(c) //輸出456}
------------------------------------------------------------
// ReadWriter 整合了 bufio.Reader 和 bufio.Writer
// 它實現了 io.ReadWriter 介面
type ReadWriter struct {*Reader*Writer}
// NewReadWriter 封裝 r 和 w 為一個 bufio.ReadWriter 對象
func NewReadWriter(r *Reader, w *Writer) *ReadWriter
package mainimport ("bufio""bytes""fmt""strings")func main() {b := bytes.NewBuffer(make([]byte, 0))bw := bufio.NewWriter(b)s := strings.NewReader("123")br := bufio.NewReader(s)rw := bufio.NewReadWriter(br, bw)p, _ := rw.ReadString('\n')fmt.Println(string(p)) //123rw.WriteString("asdf")rw.Flush()fmt.Println(b) //asdf}
------------------------------------------------------------
// scan.go
------------------------------------------------------------
// Scanner 提供了一個方便的介面來讀取資料,例如讀取一個多行文本
// 連續調用 Scan 方法將掃描資料中的“指定部分”,跳過各個“指定部分”之間的資料
// Scanner 使用了緩衝,所以“指定部分”的長度不能超出緩衝的長度
// Scanner 需要一個 SplitFunc 類型的“切分函數”來確定“指定部分”的格式
// 本包中提供的“切分函數”有“行切分函數”、“位元組切分函數”、“UTF8字元編碼切分函數”
// 和“單詞切分函數”,使用者也可以自訂“切分函數”
// 預設的“切分函數”為“行切分函數”,用於擷取資料中的一行資料(不包括行尾符)
//
// 掃描在遇到下面的情況時會停止:
// 1、資料掃描完畢,遇到 io.EOF
// 2、遇到讀寫錯誤
// 3、“指定部分”的長度超過了緩衝的長度
// 如果要對資料進行更多的控制,比如的錯誤處理或掃描更大的“指定部分”或順序掃描
// 則應該使用 bufio.Reader
type Scanner struct {r io.Reader // The reader provided by the client.split SplitFunc // The function to split the tokens.maxTokenSize int // Maximum size of a token; modified by tests.token []byte // Last token returned by split.buf []byte // Buffer used as argument to split.start int // First non-processed byte in buf.end int // End of data in buf.err error // Sticky error.}
// SplitFunc 用來定義“切分函數”類型
// data 是要掃描的資料
// atEOF 標記底層 io.Reader 中的資料是否已經讀完
// advance 返回 data 中已處理的資料長度
// token 返回找到的“指定部分”
// err 返回錯誤資訊
// 如果在 data 中無法找到一個完整的“指定部分”
// 則 SplitFunc 返回 (0, nil) 來告訴 Scanner
// 向緩衝中填充更多資料,然後再次掃描
//
// 如果返回的 err 是非 nil 值,掃描將被終止,並返回錯誤資訊
//
// 如果 data 為空白,則“切分函數”將不被調用
// 意思是在 SplitFunc 中不必考慮 data 為空白的情況
//
// SplitFunc 的作用很簡單,從 data 中找出你感興趣的資料,然後返回
// 並告訴調用者,data 中有多少資料你已經處理過了
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)
// NewScanner 建立一個 Scanner 來掃描 r
// 預設切分函數為 ScanLines
func NewScanner(r io.Reader) *Scanner
// Err 返回掃描過程中遇到的非 EOF 錯誤
// 供使用者調用,以便擷取錯誤資訊
func (s *Scanner) Err() error
------------------------------------------------------------
// Bytes 將最後一次掃描出的“指定部分”作為一個切片返回(引用傳遞)
// 下一次的 Scan 操作會覆蓋本次返回的結果
func (s *Scanner) Bytes() []byte
// Text 將最後一次掃描出的“指定部分”作為字串返回(值傳遞)
func (s *Scanner) Text() string
------------------------------------------------------------
// Scan 在 Scanner 的資料中掃描“指定部分”
// 找到後,使用者可以通過 Bytes 或 Text 方法來取出“指定部分”
// 如果掃描過程中遇到錯誤,則終止掃描,並返回 false
func (s *Scanner) Scan() bool
func main() {s := strings.NewReader("ABC\nDEF\r\nGHI\nJKL")bs := bufio.NewScanner(s)for bs.Scan() {fmt.Printf("%s %v\n", bs.Bytes(), bs.Text())}// ABC ABC// DEF DEF// GHI GHI// JKL JKL}
------------------------------------------------------------
// Split 用於設定 Scanner 的“切分函數”
// 這個函數必須在調用 Scan 前執行
func (s *Scanner) Split(split SplitFunc)
func main() {s := strings.NewReader("ABC DEF GHI JKL")bs := bufio.NewScanner(s)bs.Split(bufio.ScanWords)for bs.Scan() {fmt.Println(bs.Text())}// ABC// DEF// GHI// JKL}
------------------------------------------------------------
// ScanBytes 是一個“切分函數”
// 用來找出 data 中的單個位元組並返回
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)
func main() {s := strings.NewReader("Hello 世界!")bs := bufio.NewScanner(s)bs.Split(bufio.ScanBytes)for bs.Scan() {fmt.Printf("%s ", bs.Text())}}
------------------------------------------------------------
// ScanRunes 是一個“切分函數”
// 用來找出 data 中的單個 UTF8 字元的編碼並返回
// 如果 UTF8 解碼出錯,則返回的 U+FFFD 會被做為 "\xef\xbf\xbd" 返回
// 這使得使用者無法區分“真正的U+FFFD字元”和“解碼錯誤的傳回值”
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)
func main() {s := strings.NewReader("Hello 世界!")bs := bufio.NewScanner(s)bs.Split(bufio.ScanRunes)for bs.Scan() {fmt.Printf("%s ", bs.Text())} // H e l l o 世 界 !}------------------------------------------------------------
// ScanLines 是一個“切分函數”
// 用來找出 data 中的單行資料並返回(包括空行)
// 行尾標記可能是 \n 或 \r\n(傳回值不包括行尾標記)
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)
------------------------------------------------------------
// ScanWords 是一個“切分函數”
// 用來找出 data 中的單詞
// 單詞以空白字元分隔,空白字元由 unicode.IsSpace 定義
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)