package main
import (
"bufio"
"fmt"
"strings"
"bytes"
"io"
)
// bufio 包實現(xiàn)了帶緩存的 I/O 操作
/**
* 首先看reader和writer基本的結(jié)構(gòu)
* // Reader implements buffering for an io.Reader object.
* 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
* }
*
*
* // Writer implements buffering for an io.Writer object.
* // If an error occurs writing to a Writer, no more data will be
* // accepted and all subsequent writes will return the error.
* // After all data has been written, the client should call the
* // Flush method to guarantee all data has been forwarded to
* // the underlying io.Writer.
* type Writer struct {
* err error
* buf []byte
* n int
* wr io.Writer
* }
*
*
*
* // ReadWriter 集成了 bufio.Reader 和 bufio.Writer, 實現(xiàn)了 io.ReadWriter 接口
* type ReadWriter struct {
* *Reader
* *Writer
* }
*/
func main() {
// 1: 使用bufio.NewReader構(gòu)造一個reader
inputReadBuf := strings.NewReader("1234567890")
reader := bufio.NewReader(inputReadBuf)
// 2: 使用bufio.NewWriter構(gòu)造一個writer
buf := bytes.NewBuffer(make([]byte, 0))
writer := bufio.NewWriter(buf)
// 3: 函數(shù)Peek函數(shù): 返回緩存的一個Slice(引用,不是拷貝),引用緩存中前n字節(jié)數(shù)據(jù)
// > 如果引用的數(shù)據(jù)長度小于 n,則返回一個錯誤信息
// > 如果 n 大于緩存的總大小,則返回 ErrBufferFull
// 通過Peek的返回值,可以修改緩存中的數(shù)據(jù), 但不能修改底層io.Reader中的數(shù)據(jù)
b, err := reader.Peek(5)
if err != nil {
fmt.Printf("Read data error")
return
}
// 修改第一個字符
b[0] = 'A'
// 重新讀取
b, _ = reader.Peek(5)
writer.Write(b)
writer.Flush()
fmt.Println("buf(Changed): ", buf, "\ninputReadBuf(Not Changed): ", inputReadBuf)
// 4: Read函數(shù), 每次讀取一定量的數(shù)據(jù), 這個由buf大小覺得, 所以我們可以循環(huán)讀取數(shù)據(jù), 直到Read返回0說明讀取數(shù)據(jù)結(jié)束
for {
b1 := make([]byte, 3)
n1, _ := reader.Read(b1)
if n1 <= 0 {
break
}
fmt.Println(n1, string(b1))
}
// 5: ReadByte和UnreadByte函數(shù)
// ReadByte 從 b 中讀出一個字節(jié)并返回, 如果 b 中無可讀數(shù)據(jù),則返回一個錯誤
// UnreadByte 撤消最后一次讀出的字節(jié), 只有最后讀出的字節(jié)可以被撤消, 無論任何操作,只要有內(nèi)容被讀出,就可以用 UnreadByte 撤消一個字節(jié)
inputReadBuf2 := strings.NewReader("1234567890")
reader2 := bufio.NewReader(inputReadBuf2)
// 讀一個字節(jié)
b2, _ := reader2.ReadByte()
fmt.Println(string(b2))
// Unread一個字節(jié)
reader2.UnreadByte()
b2, _ = reader2.ReadByte()
fmt.Println(string(b2))
// 6: ReadRune和UnreadRune函數(shù), 類似上面兩個函數(shù)
// ReadRune讀出一個 UTF8 編碼的字符并返回編碼長度, 如果UTF8序列無法解碼出一個正確的Unicode字符, 則只讀出b中的一個字節(jié),size 返回 1
inputReadBuf3 := strings.NewReader("中文1234567890")
reader3 := bufio.NewReader(inputReadBuf3)
b3, size, _ := reader3.ReadRune()
fmt.Println(string(b3), size)
reader3.UnreadRune()
b3, size, _ = reader3.ReadRune()
fmt.Println(string(b3), size)
// 執(zhí)行UnreadRune時候, 如果之前一步不是ReadRune, 那么會報錯, 看下面
b33, _ := reader3.ReadByte()
fmt.Println(string(b33))
err3 := reader3.UnreadRune()
if err3 != nil {
fmt.Println("ERR")
}
// 7: 讀取緩沖區(qū)中數(shù)據(jù)字節(jié)數(shù)(只有執(zhí)行讀才會使用到緩沖區(qū), 否則是沒有的)
inputReadBuf4 := strings.NewReader("中文1234567890")
reader4 := bufio.NewReader(inputReadBuf4)
// 下面返回0, 因為還沒有開始讀取, 緩沖區(qū)沒有數(shù)據(jù)
fmt.Println(reader4.Buffered())
// 下面返回strings的整體長度16(一個人中文是3長度)
reader4.Peek(1)
fmt.Println(reader4.Buffered())
// 下面返回15, 因為readByte已經(jīng)讀取一個字節(jié)數(shù)據(jù), 所以緩沖區(qū)還有15字節(jié)
reader4.ReadByte()
fmt.Println(reader4.Buffered())
// 下面的特別有意思: 上面已經(jīng)讀取了一個字節(jié), 想當于是將"中"讀取了1/3, 那么如果現(xiàn)在使用readRune讀取, 那么
// 由于無法解析, 那么僅僅讀取一個byte, 所以下面的結(jié)果很顯然
// 第一次: 無法解析, 那么返回一個byte, 所以輸出的是14
reader4.ReadRune()
fmt.Println(reader4.Buffered())
// 第二次讀取, 還剩下"中"最后一個字節(jié), 所以也會err, 所以輸出13
reader4.ReadRune()
fmt.Println(reader4.Buffered())
// 現(xiàn)在"中"讀完了, 那么開始完整讀取"文", 這個OK的, 可以解析的, 所以可以讀取三字節(jié), 那么剩下10字節(jié)
reader4.ReadRune()
fmt.Println(reader4.Buffered())
// 8: ReadSlice查找 delim 并返回 delim 及其之前的所有數(shù)據(jù)的切片, 該操作會讀出數(shù)據(jù),返回的切片是已讀出數(shù)據(jù)的"引用"
// 如果 ReadSlice 在找到 delim 之前遇到錯誤, 則讀出緩存中的所有數(shù)據(jù)并返回,同時返回遇到error(通常是 io.EOF)
// 如果 在整個緩存中都找不到 delim,則返回 ErrBufferFull
// 如果 ReadSlice 能找到 delim,則返回 nil
// 注意: 因為返回的Slice數(shù)據(jù)有可能被下一次讀寫操作修改, 因此大多數(shù)操作應(yīng)該使用 ReadBytes 或 ReadString,它們返回數(shù)據(jù)copy
// 不推薦!
inputReadBuf5 := strings.NewReader("中文123 4567 890")
reader5 := bufio.NewReader(inputReadBuf5)
for ; ; {
b5 , err := reader5.ReadSlice(' ')
fmt.Println(string(b5))
// 讀到最后
if err == io.EOF {
break
}
}
// 9: ReadLine 是一個低級的原始的行讀取操作, 一般應(yīng)該使用 ReadBytes('\n') 或 ReadString('\n')
// ReadLine 通過調(diào)用 ReadSlice 方法實現(xiàn),返回的也是"引用", 回一行數(shù)據(jù),不包括行尾標記(\n 或 \r\n)
// 如果 在緩存中找不到行尾標記,設(shè)置 isPrefix 為 true,表示查找未完成
// 如果 在當前緩存中找到行尾標記,將 isPrefix 設(shè)置為 false,表示查找完成
// 如果 ReadLine 無法獲取任何數(shù)據(jù),則返回一個錯誤信息(通常是 io.EOF)
// 不推薦!
inputReadBuf6 := strings.NewReader("中文123\n4567\n890")
reader6 := bufio.NewReader(inputReadBuf6)
for ; ; {
l, p, err := reader6.ReadLine()
fmt.Println(string(l), p, err)
if err == io.EOF {
break
}
}
// 10: ReadBytes查找 delim 并讀出 delim 及其之前的所有數(shù)據(jù)
// 如果 ReadBytes 在找到 delim 之前遇到錯誤, 則返回遇到錯誤之前的所有數(shù)據(jù),同時返回遇到的錯誤(通常是 io.EOF)
// 如果 ReadBytes 找不到 delim 時,err != nil
// 返回的是數(shù)據(jù)的copy, 不是引用
inputReadBuf7 := strings.NewReader("中文123;4567;890")
reader7 := bufio.NewReader(inputReadBuf7)
for ; ; {
line, err := reader7.ReadBytes(';')
fmt.Println(string(line))
if err != nil {
break
}
}
// 11: ReadString返回的是字符串, 不是bytes
inputReadBuf8 := strings.NewReader("中文123;4567;890")
reader8 := bufio.NewReader(inputReadBuf8)
for ; ; {
line, err := reader8.ReadString(';')
fmt.Println(line)
if err != nil {
break
}
}
//12: Flush函數(shù)用于提交數(shù)據(jù), 立即更新
// Available函數(shù)返回緩存中的可以空間
// b10是保存數(shù)據(jù)的數(shù)組, 不是writer的緩沖區(qū), 別搞錯了
b10 := bytes.NewBuffer(make([]byte, 30))
// 下面會分配4096字節(jié)空間緩沖區(qū)
writer10 := bufio.NewWriter(b10)
writer10.WriteString("1234567890")
// 此時沒有flush, 那么輸出的是"", 但是緩沖區(qū)使用了10個字節(jié), 那么剩下4086, Buffered()返回的是緩沖區(qū)還沒有提交的數(shù)據(jù), 此處顯然是10
fmt.Println(writer10.Available(), writer10.Buffered(), b10)
// 下面flush后, 將緩沖區(qū)的數(shù)據(jù)全部寫入b10中, 緩沖區(qū)被清空, 所以緩沖區(qū)變成4096, Buffered()返回的是0, 說明數(shù)據(jù)被寫入
writer10.Flush()
fmt.Println(writer10.Available(), writer10.Buffered(), b10)
// 13: WriteString(...), Write(...), WriteByte(...), WriteRune(...)函數(shù)
// 都是寫數(shù)據(jù)函數(shù)
b11 := bytes.NewBuffer(make([]byte, 1024))
writer11 := bufio.NewWriter(b11)
writer11.WriteString("ABC")
writer11.WriteByte(byte('M'))
// Rune的意思是: 代表一個字符, 那么需要一次一個字符寫入
writer11.WriteRune(rune('好'))
writer11.WriteRune(rune('么'))
writer11.Write([]byte("1234567890"))
writer11.Flush()
fmt.Println(b11)
// 14: WriteTo函數(shù)
inputReadBuf9 := strings.NewReader("中文1234567890")
reader9 := bufio.NewReader(inputReadBuf9)
b9 := bytes.NewBuffer(make([]byte, 0))
reader9.WriteTo(b9)
fmt.Println(b9)
// 15: ReadFrom函數(shù)
inputReadBuf15 := strings.NewReader("率哪來的順豐內(nèi)部了第三方吧")
b15 := bytes.NewBuffer(make([]byte, 0))
writer15 := bufio.NewWriter(b15)
writer15.ReadFrom(inputReadBuf15)
fmt.Println(b15)
}```
golang bufio包
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
相關(guān)閱讀更多精彩內(nèi)容
- 結(jié)論:閉包函數(shù)可以直接引用外層代碼定義的變量,但是,注意,閉包函數(shù)里面引用的是變量的地址,當goroutine被調(diào)...
- 結(jié)論:閉包能夠訪問外層代碼中的變量;foe循環(huán)與gotoutine同時執(zhí)行;所有的goroutine操作的變量都是...
- 現(xiàn)如今即便是個人開發(fā)的一般程序,可能其包含的函數(shù)都超過了一萬個,這些函數(shù)代碼一般都由他人編寫并打包為“包”或者“模...
- 總結(jié)下Go的package設(shè)計哲學(xué) 明確目的在準備設(shè)計一個包之前,我們需要明確它的目的。包的命名就必須明確體現(xiàn)其目...