一苟鸯、介紹go標(biāo)準(zhǔn)庫中的bufio
最近用golang寫了一個處理文件的腳本,由于其中涉及到了文件讀寫抡柿,開始使用golang中的 io 包,后來發(fā)現(xiàn)golang 中提供了一個bufio的包爵赵,使用這個包可以大幅提高文件讀寫的效率吝秕,于是在網(wǎng)上搜索同樣的文件讀寫為什么bufio 要比io 的讀寫更快速呢?根據(jù)網(wǎng)上的資料和閱讀源碼空幻,以下來詳細(xì)解釋下bufio的高效如何實現(xiàn)的烁峭。
bufio 包介紹
bufio包實現(xiàn)了有緩沖的I/O。它包裝一個io.Reader或io.Writer接口對象秕铛,創(chuàng)建另一個也實現(xiàn)了該接口约郁,且同時還提供了緩沖和一些文本I/O的幫助函數(shù)的對象。
以上為官方包的介紹但两,在其中我們能了解到的信息如下:
bufio 是通過緩沖來提高效率
簡單的說就是鬓梅,把文件讀取進(jìn)緩沖(內(nèi)存)之后再讀取的時候就可以避免文件系統(tǒng)的io 從而提高速度。同理谨湘,在進(jìn)行寫操作時己肮,先把文件寫入緩沖(內(nèi)存),然后由緩沖寫入文件系統(tǒng)悲关。看完以上解釋有人可能會表示困惑了娄柳,直接把 內(nèi)容->文件 和 內(nèi)容->緩沖->文件相比寓辱, 緩沖區(qū)好像沒有起到作用嘛。其實緩沖區(qū)的設(shè)計是為了存儲多次的寫入赤拒,最后一口氣把緩沖區(qū)內(nèi)容寫入文件秫筏。下面會詳細(xì)解釋
bufio 封裝了io.Reader或io.Writer接口對象,并創(chuàng)建另一個也實現(xiàn)了該接口的對象
io.Reader或io.Writer 接口實現(xiàn)read() 和 write() 方法挎挖,對于實現(xiàn)這個接口的對象都是可以使用這兩個方法的
注明:介紹內(nèi)容來自博主LiangWenT
这敬,原文鏈接:https://blog.csdn.net/LiangWenT/article/details/78995468,在查找資料時蕉朵,發(fā)現(xiàn)這篇博客的內(nèi)容很好理解
bufio包實現(xiàn)了緩存IO崔涂。它包裝了io.Reader和io.Write對象,創(chuàng)建了另外的Reader和Writer對象始衅,它們也實現(xiàn)了io.Reader和io.Write接口冷蚂,具有緩存。注意:緩存是放在主存中汛闸,既然是保存在主存里蝙茶,斷電會丟失數(shù)據(jù),那么要及時保存數(shù)據(jù)诸老。
二隆夯、常用內(nèi)容
1、Reader類型
type Reader struct {
buf []byte // 緩存
rd io.Reader // 底層的io.Reader
r, w int
err error // 讀過程中遇到的錯誤
lastByte int // 最后一次讀到的字節(jié)
lastRuneSize int // 最后一次讀到的Rune的大小
}
NewReaderSize
func NewReaderSize(rd io.Reader, size int) *Reader
作用:NewReaderSize將rd封裝成一個帶緩存的bufio.Reader對象。緩存大小由size指定(如果小于16則會被設(shè)為16)蹄衷。如果rd的基類型就是有足夠緩存的bufio.Reader類型忧额,則直接將rd轉(zhuǎn)換為基類型返回。
NewReader
func NewReader(rd io.Reader) *Reader
funcReader相當(dāng)于NewReaderSize(rd, 4096)
Peek
func (b *Reader) Peek(n int) ([]byte, error)
Peek返回緩存的一個切片宦芦,該切片引用緩存中前n個字節(jié)的數(shù)據(jù)宙址,該操作不會將數(shù)據(jù)讀出,只是引用调卑,引用的數(shù)據(jù)在下一次讀取操作之前有效的抡砂。如果切片長度小于n,則返回一個錯誤信息說明原因恬涧。如果n大于緩存的總大小注益,則返回ErrBufferFull。
Read
func (b *Reader) Read(p []byte) (n int, err error)
Read從b中數(shù)據(jù)到p中溯捆,返回讀出的字節(jié)數(shù)和遇到的錯誤丑搔。如果緩存不為空,則只能讀出緩沖中的數(shù)據(jù)提揍,不會從底層io.Reader中提取數(shù)據(jù)啤月,如果緩存為空,則:
1劳跃、len(p) >= 緩存大小谎仲,則跳過緩存,直接從底層io.Reader中讀出到p中
2刨仑、len(p)< 緩存大小郑诺,則先將數(shù)據(jù)從底層io.Reader中讀取到緩存中竖共,再從緩存讀取到p中曾沈。
Buffered
func (b *Reader) Buffered() int
Buffered返回緩存中未讀取的數(shù)據(jù)的長度。
Discard
func (b *Reader) Discard(n int) (discarded int, err error)
Discard跳過后續(xù)的n個字節(jié)的數(shù)據(jù)量淌,返回跳過的字節(jié)數(shù)轻抱。
Writer類型和方法
write結(jié)構(gòu)
type Write struct {
err error // 寫過程中遇到的錯誤
buf []byte // 緩存
n int // 當(dāng)前緩存中的字節(jié)數(shù)
wr io.Writer // 底層的io.Writer對象
}
NewWriteSize
func NewWriteSize(wr io.Write, size int) *Write
NewWriterSize將wr封裝成一個帶緩存的bufio.Writer對象飞涂,緩存大小由size指定(如果小于4096則會被設(shè)置未4096)。
NewWrite
func NewWriter(wr io.Writer) *Writer
NewWriter相等于NewWriterSize(wr, 4096)
WriteString
func (b *Write) WriteString(s string) (int, error)
WriteString功能同Write祈搜,只不過寫入的是字符串
WriteRune
func (b *Writer) WriteRune(r rune) (size int, err error)
WriteRune向b寫入r的UTF-8編碼封拧,返回r的編碼長度。
Flush
func (b *Writer) Flush() error
Available
func (b *Writer) Available() int
Available 返回緩存中未使用的空間的長度
Buffered
func (b *Writer) Buffered() int
Buffered返回緩存中未提交的數(shù)據(jù)長度
Reset
func (b *Write) Reset(w io.Writer)
Reset將b的底層Write重新指定為w夭问,同時丟棄緩存中的所有數(shù)據(jù)泽西,復(fù)位所有標(biāo)記和錯誤信息。相當(dāng)于創(chuàng)建了一個新的bufio.Writer缰趋。
GO中還提供了Scanner類型捧杉,處理一些比較簡單的場景陕见。如處理按行讀取輸入序列或空格分隔的詞等。
內(nèi)容來自:https://blog.csdn.net/wangshubo1989/article/details/70177928
參考鏈接:
1)https://blog.csdn.net/LiangWenT/article/details/78995468
2)https://blog.csdn.net/wangshubo1989/article/details/70177928