咖啡伴侶

          呆在上海
          posts - 163, comments - 156, trackbacks - 0, articles - 2

          bufio 包

          Posted on 2013-09-05 16:01 oathleo 閱讀(1202) 評論(0)  編輯  收藏 所屬分類: Golang
          // bufio 包實現了帶緩存的 I/O 操作
          // 它封裝一個 io.Reader 或 io.Writer 對象
          // 使其具有緩存和一些文本讀寫功能
          ------------------------------------------------------------
          // bufio.go
          ------------------------------------------------------------
          // Reader 實現了帶緩存的 io.Reader 對象
          type Reader struct {
          // 私有字段
          }
          // 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 (b *Reader) Peek(n int) ([]byte, error)
          func main() {
          s := strings.NewReader("ABCDEFG")
          br := bufio.NewReader(s)
          b, _ := br.Peek(5)
          fmt.Printf("%s\n", b)
          // ABCDE
          b[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)
          // A
          c, _ = br.ReadByte()
          fmt.Printf("%c\n", c)
          // B
          br.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)
          // 你 3
          c, size, _ = br.ReadRune()
          fmt.Printf("%c %v\n", c, size)
          // 好 3
          br.UnreadRune()
          c, size, _ = br.ReadRune()
          fmt.Printf("%c %v\n", c, size)
          // 好 3
          }
          ------------------------------------------------------------
          // Buffered 返回緩存中數據的長度
          func (b *Reader) Buffered() int
          func main() {
          s := strings.NewReader("你好,世界!")
          br := bufio.NewReader(s)
          fmt.Println(br.Buffered())
          // 0
          br.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" false
          w, isPrefix, _ = br.ReadLine()
          fmt.Printf("%q %v\n", w, isPrefix)
          // "DEF" false
          w, 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
          }
          ------------------------------------------------------------
          // Writer 實現了帶緩存的 io.Writer 對象
          // 如果在向 Writer 中寫入數據的過程中遇到錯誤
          // 則 Writer 不會再接受任何數據
          // 而且后續的寫入操作都將返回錯誤信息
          type Writer struct {
          // 私有字段
          }
          // 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()
          fmt.Println(b) // Hello 世界!
          }
          ------------------------------------------------------------
          // ReadWriter 集成了 bufio.Reader 和 bufio.Writer
          // 它實現了 io.ReadWriter 接口
          type ReadWriter struct {
          *Reader
          *Writer
          }
          // NewReadWriter 封裝 r 和 w 為一個 bufio.ReadWriter 對象
          func NewReadWriter(r *Reader, w *Writer) *ReadWriter
          ------------------------------------------------------------
          // scan.go
          ------------------------------------------------------------
          // Scanner 提供了一個方便的接口來讀取數據,例如讀取一個多行文本
          // 連續調用 Scan 方法將掃描數據中的“指定部分”,跳過各個“指定部分”之間的數據
          // Scanner 使用了緩存,所以“指定部分”的長度不能超出緩存的長度
          // Scanner 需要一個 SplitFunc 類型的“切分函數”來確定“指定部分”的格式
          // 本包中提供的“切分函數”有“行切分函數”、“字節切分函數”、“UTF8字符編碼切分函數”
          // 和“單詞切分函數”,用戶也可以自定義“切分函數”
          // 默認的“切分函數”為“行切分函數”,用于獲取數據中的一行數據(不包括行尾符)
          //
          // 掃描在遇到下面的情況時會停止:
          // 1、數據掃描完畢,遇到 io.EOF
          // 2、遇到讀寫錯誤
          // 3、“指定部分”的長度超過了緩存的長度
          // 如果要對數據進行更多的控制,比如的錯誤處理或掃描更大的“指定部分”或順序掃描
          // 則應該使用 bufio.Reader
          type Scanner struct {
          // 私有字段
          }
          // 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)
          主站蜘蛛池模板: 安平县| 锡林郭勒盟| 呼玛县| 通州市| 勃利县| 沙湾县| 图片| 尉氏县| 昭通市| 崇信县| 定襄县| 旌德县| 安福县| 闽侯县| 苗栗市| 贵港市| 衡山县| 万荣县| 波密县| 阳江市| 杭锦旗| 秦安县| 山东省| 和田县| 德清县| 武强县| 商城县| 石柱| 龙海市| 陆河县| 灯塔市| 政和县| 桂平市| 浦北县| 毕节市| 蓝山县| 尉氏县| 蛟河市| 墨玉县| 祁东县| 涡阳县|