Go語言使用buffer讀取文件的實(shí)現(xiàn)示例
buffer 是緩沖器的意思,Go語言要實(shí)現(xiàn)緩沖讀取需要使用到 bufio 包。bufio 包本身包裝了 io.Reader 和 io.Writer 對(duì)象,同時(shí)創(chuàng)建了另外的 Reader 和 Writer 對(duì)象,因此對(duì)于文本 I/O 來說,bufio 包提供了一定的便利性。
buffer 緩沖器的實(shí)現(xiàn)原理就是,將文件讀取進(jìn)緩沖(內(nèi)存)之中,再次讀取的時(shí)候就可以避免文件系統(tǒng)的 I/O 從而提高速度。同理在進(jìn)行寫操作時(shí),先把文件寫入緩沖(內(nèi)存),然后由緩沖寫入文件系統(tǒng)。
使用 bufio 包寫入文件
bufio 和 io 包中有很多操作都是相似的,唯一不同的地方是 bufio 提供了一些緩沖的操作,如果對(duì)文件 I/O 操作比較頻繁的,使用 bufio 包能夠提高一定的性能。
在 bufio 包中,有一個(gè) Writer 結(jié)構(gòu)體,而其相關(guān)的方法支持一些寫入操作,如下所示。
//Writer 是一個(gè)空的結(jié)構(gòu)體,一般需要使用 NewWriter 或者 NewWriterSize 來初始化一個(gè)結(jié)構(gòu)體對(duì)象 type Writer struct { // contains filtered or unexported fields } //NewWriterSize 和 NewWriter 函數(shù) //返回默認(rèn)緩沖大小的 Writer 對(duì)象(默認(rèn)是4096) func NewWriter(w io.Writer) *Writer //指定緩沖大小創(chuàng)建一個(gè) Writer 對(duì)象 func NewWriterSize(w io.Writer, size int) *Writer //Writer 對(duì)象相關(guān)的寫入數(shù)據(jù)的方法 //把 p 中的內(nèi)容寫入 buffer,返回寫入的字節(jié)數(shù)和錯(cuò)誤信息。如果 nn < len(p),返回錯(cuò)誤信息中會(huì)包含為什么寫入的數(shù)據(jù)比較短 func (b *Writer) Write(p []byte) (nn int, err error) //將 buffer 中的數(shù)據(jù)寫入 io.Writer func (b *Writer) Flush() error //以下三個(gè)方法可以直接寫入到文件中 //寫入單個(gè)字節(jié) func (b *Writer) WriteByte(c byte) error //寫入單個(gè) Unicode 指針返回寫入字節(jié)數(shù)錯(cuò)誤信息 func (b *Writer) WriteRune(r rune) (size int, err error) //寫入字符串并返回寫入字節(jié)數(shù)和錯(cuò)誤信息 func (b *Writer) WriteString(s string) (int, error)
示例代碼如下所示:
package main import ( "bufio" "fmt" "os" ) func main() { name := "demo.txt" content := "http://jb51.net/golang/" fileObj, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644) if err != nil { fmt.Println("文件打開失敗", err) } defer fileObj.Close() writeObj := bufio.NewWriterSize(fileObj, 4096) //使用 Write 方法,需要使用 Writer 對(duì)象的 Flush 方法將 buffer 中的數(shù)據(jù)刷到磁盤 buf := []byte(content) if _, err := writeObj.Write(buf); err == nil { if err := writeObj.Flush(); err != nil { panic(err) } fmt.Println("數(shù)據(jù)寫入成功") } }
運(yùn)行上面的代碼會(huì)在當(dāng)前目錄之下生成 demo.txt 文件,并將“http://jb51.net/golang/”寫入到該文件中。
使用 bufio 包讀取文件
使用 bufio 包讀取文件也非常方便,我們先來看下 bufio 包的相關(guān)的 Reader 函數(shù)方法:
//首先定義了一個(gè)用來緩沖 io.Reader 對(duì)象的結(jié)構(gòu)體,同時(shí)該結(jié)構(gòu)體擁有以下相關(guān)的方法 type Reader struct { } //NewReader 函數(shù)用來返回一個(gè)默認(rèn)大小 buffer 的 Reader 對(duì)象(默認(rèn)大小是 4096) 等同于 NewReaderSize(rd,4096) func NewReader(rd io.Reader) *Reader //該函數(shù)返回一個(gè)指定大小 buffer(size 最小為 16)的 Reader 對(duì)象,如果 io.Reader 參數(shù)已經(jīng)是一個(gè)足夠大的 Reader,它將返回該 Reader func NewReaderSize(rd io.Reader, size int) *Reader //該方法返回從當(dāng)前 buffer 中能被讀到的字節(jié)數(shù) func (b *Reader) Buffered() int //Discard 方法跳過后續(xù)的 n 個(gè)字節(jié)的數(shù)據(jù),返回跳過的字節(jié)數(shù)。如果 0 <= n <= b.Buffered(),該方法將不會(huì)從 io.Reader 中成功讀取數(shù)據(jù) func (b *Reader) Discard(n int) (discarded int, err error) //Peekf 方法返回緩存的一個(gè)切片,該切片只包含緩存中的前 n 個(gè)字節(jié)的數(shù)據(jù) func (b *Reader) Peek(n int) ([]byte, error) //把 Reader 緩存對(duì)象中的數(shù)據(jù)讀入到 []byte 類型的 p 中,并返回讀取的字節(jié)數(shù)。讀取成功,err 將返回空值 func (b *Reader) Read(p []byte) (n int, err error) //返回單個(gè)字節(jié),如果沒有數(shù)據(jù)返回 err func (b *Reader) ReadByte() (byte, error) //該方法在 b 中讀取 delimz 之前的所有數(shù)據(jù),返回的切片是已讀出的數(shù)據(jù)的引用,切片中的數(shù)據(jù)在下一次的讀取操作之前是有效的。如果未找到 delim,將返回查找結(jié)果并返回 nil 空值。因?yàn)榫彺娴臄?shù)據(jù)可能被下一次的讀寫操作修改,因此一般使用 ReadBytes 或者 ReadString,他們返回的都是數(shù)據(jù)拷貝 func (b *Reader) ReadSlice(delim byte) (line []byte, err error) //功能同 ReadSlice,返回?cái)?shù)據(jù)的拷貝 func (b *Reader) ReadBytes(delim byte) ([]byte, error) //功能同 ReadBytes,返回字符串 func (b *Reader) ReadString(delim byte) (string, error) //該方法是一個(gè)低水平的讀取方式,一般建議使用 ReadBytes('\n') 或 ReadString('\n'),或者使用一個(gè) Scanner 來代替。ReadLine 通過調(diào)用 ReadSlice 方法實(shí)現(xiàn),返回的也是緩存的切片,用于讀取一行數(shù)據(jù),不包括行尾標(biāo)記(\n 或 \r\n) func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error) //讀取單個(gè) UTF-8 字符并返回一個(gè) rune 和字節(jié)大小 func (b *Reader) ReadRune() (r rune, size int, err error)
示例代碼如下:
package main import ( "bufio" "fmt" "os" "strconv" ) func main() { fileObj, err := os.Open("demo.txt") if err != nil { fmt.Println("文件打開失?。?, err) return } defer fileObj.Close() //一個(gè)文件對(duì)象本身是實(shí)現(xiàn)了io.Reader的 使用bufio.NewReader去初始化一個(gè)Reader對(duì)象,存在buffer中的,讀取一次就會(huì)被清空 reader := bufio.NewReader(fileObj) buf := make([]byte, 1024) //讀取 Reader 對(duì)象中的內(nèi)容到 []byte 類型的 buf 中 info, err := reader.Read(buf) if err != nil { fmt.Println(err) } fmt.Println("讀取的字節(jié)數(shù):" + strconv.Itoa(info)) //這里的buf是一個(gè)[]byte,因此如果需要只輸出內(nèi)容,仍然需要將文件內(nèi)容的換行符替換掉 fmt.Println("讀取的文件內(nèi)容:", string(buf)) }
運(yùn)行結(jié)果如下:
go run main.go
讀取的字節(jié)數(shù):30
讀取的文件內(nèi)容: http://jb51.net/golang/
到此這篇關(guān)于Go語言使用buffer讀取文件的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Go語言buffer讀取文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go實(shí)現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例
本文主要介紹了go實(shí)現(xiàn)服務(wù)優(yōu)雅關(guān)閉的示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02K8s部署發(fā)布Golang應(yīng)用程序的實(shí)現(xiàn)方法
本文主要介紹了K8s部署發(fā)布Golang應(yīng)用程序的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07關(guān)于go-micro與其它gRPC框架之間的通信問題及解決方法
在之前的文章中分別介紹了使用gRPC官方插件和go-micro插件開發(fā)gRPC應(yīng)用程序的方式,都能正常走通。不過當(dāng)兩者混合使用的時(shí)候,互相訪問就成了問題,下面通過本文給大家講解下go-micro與gRPC框架通信問題,一起看看吧2022-04-04一文帶你了解Go中跟蹤函數(shù)調(diào)用鏈的實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了go如何實(shí)現(xiàn)一個(gè)自動(dòng)注入跟蹤代碼,并輸出有層次感的函數(shù)調(diào)用鏈跟蹤命令行工具,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-11-11go語言限制協(xié)程并發(fā)數(shù)的方案詳情
一個(gè)線程中可以有任意多個(gè)協(xié)程,但某一時(shí)刻只能有一個(gè)協(xié)程在運(yùn)行,多個(gè)協(xié)程分享該線程分配到的計(jì)算機(jī)資源,接下來通過本文給大家介紹go語言限制協(xié)程的并發(fā)數(shù)的方案詳情,感興趣的朋友一起看看吧2022-01-01