Go語言中數(shù)據(jù)I/O對象及操作

參考:
http://c.biancheng.net/view/5569.html

在Go語言中,幾乎所有的數(shù)據(jù)結(jié)構(gòu)都圍繞接口展開,接口是Go語言中所有數(shù)據(jù)結(jié)構(gòu)的核心。

在實際開發(fā)過程中,無論是實現(xiàn) web應(yīng)用程序,還是控制臺輸入輸出,又或者是網(wǎng)絡(luò)操作,都不可避免的會遇到I/O操作。

Go語言標(biāo)準(zhǔn)庫的 bufio 包中,實現(xiàn)了對數(shù)據(jù)I/O接口的緩沖功能。

這些功能封裝于接口

  • io.ReadWriter、

  • io.Reader

  • io.Writer 中,

并對應(yīng)創(chuàng)建

  • ReadWriter、

  • Reader

  • Writer 對象,

在提供緩沖的同時實現(xiàn)了一些文本基本 I/O 操作功能。

1、ReadWriter 對象

ReadWriter 對象可以對數(shù)據(jù) I/O 接口 io.ReadWriter 進(jìn)行輸入輸出緩沖操作,
ReadWriter 結(jié)構(gòu)定義如下:

type ReadWriter struct {
    *Reader
    *Writer
}

默認(rèn)情況下,ReadWriter 對象中存放了一對 Reader 和 Writer 指針,它同時提供了對數(shù)據(jù) I/O 對象的讀寫緩沖功能。

可以使用 NewReadWriter() 函數(shù)創(chuàng)建 ReadWriter 對象,該函數(shù)的功能是根據(jù)指定的 Reader 和 Writer 創(chuàng)建一個 ReadWriter 對象,

ReadWriter 對象將會向底層 io.ReadWriter 接口寫入數(shù)據(jù),或者從 io.ReadWriter 接口讀取數(shù)據(jù)。該函數(shù)原型聲明如下:

func NewReadWriter(r *Reader, w *Writer) *ReadWriter

在函數(shù) NewReadWriter() 中,參數(shù) r 是要讀取的來源 Reader 對象,參數(shù) w 是要寫入的目的 Writer 對象。

2、Reader 對象

Reader 對象可以對數(shù)據(jù) I/O 接口 io.Reader 進(jìn)行輸入緩沖操作,
Reader 結(jié)構(gòu)定義如下:

type Reader struct {
    //contains filtered or unexported fields
)

默認(rèn)情況下 Reader 對象沒有定義初始值,輸入緩沖區(qū)最小值16。

當(dāng)超出限制時,另創(chuàng)建一個二倍的存儲空間。

3、創(chuàng)建 Reader 對象

可以創(chuàng)建 Reader 對象的函數(shù)一共有兩個,分別是

  • NewReader()

  • NewReaderSize(),

下面分別介紹。

1) NewReader() 函數(shù)

NewReader() 函數(shù)的功能是按照緩沖區(qū)默認(rèn)長度創(chuàng)建 Reader 對象,

Reader 對象會從底層 io.Reader 接口讀取盡量多的數(shù)據(jù)進(jìn)行緩存。

該函數(shù)原型如下:

func NewReader(rd io.Reader) *Reader

其中,參數(shù) rd 是 io.Reader 接口,Reader 對象將從該接口讀取數(shù)據(jù)。

2) NewReaderSize() 函數(shù)

NewReaderSize() 函數(shù)的功能是按照指定的緩沖區(qū)長度創(chuàng)建 Reader 對象,

Reader 對象會從底層 io.Reader 接口讀取盡量多的數(shù)據(jù)進(jìn)行緩存。

該函數(shù)原型如下:

func NewReaderSize(rd io.Reader, size int) *Reader

其中,參數(shù) rd 是 io.Reader 接口,參數(shù) size 是指定的緩沖區(qū)字節(jié)長度。

4、操作 Reader 對象

操作 Reader 對象的方法共有11個,分別是

  • Read()、

  • ReadByte()、

  • ReadBytes()、

  • ReadLine()、

  • ReadRune ()、R

  • eadSlice()、

  • ReadString()、

  • UnreadByte()、

  • UnreadRune()、

  • Buffered()、

  • Peek(),

下面分別介紹。

1) Read() 方法

Read() 方法的功能是讀取數(shù)據(jù),并存放到字節(jié)切片 p 中。

Read() 執(zhí)行結(jié)束會返回已讀取的字節(jié)數(shù),因為最多只調(diào)用底層的 io.Reader 一次,所以返回的 n 可能小于 len(p),當(dāng)字節(jié)流結(jié)束時,n 為 0,err 為 io. EOF。

該方法原型如下:

func (b *Reader) Read(p []byte) (n int, err error)

在方法 Read() 中,參數(shù) p 是用于存放讀取數(shù)據(jù)的字節(jié)切片。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("C語言中文網(wǎng)")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    var buf [128]byte
    n, err := r.Read(buf[:])
    fmt.Println(string(buf[:n]), n, err)
}

運行結(jié)果如下:

C語言中文網(wǎng) 16 <nil>

2) ReadByte() 方法

ReadByte() 方法的功能是讀取并返回一個字節(jié),如果沒有字節(jié)可讀,則返回錯誤信息。該方法原型如下:

func (b *Reader) ReadByte() (c byte,err error)

示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("Go語言入門教程")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    c, err := r.ReadByte()
    fmt.Println(string(c), err)
}

運行結(jié)果如下:

G <nil>

3) ReadBytes() 方法

ReadBytes() 方法的功能是讀取數(shù)據(jù)直到遇到第一個分隔符“delim”,并返回讀取的字節(jié)序列(包括“delim”)。如果 ReadBytes 在讀到第一個“delim”之前出錯,它返回已讀取的數(shù)據(jù)和那個錯誤(通常是 io.EOF)。只有當(dāng)返回的數(shù)據(jù)不以“delim”結(jié)尾時,返回的 err 才不為空值。
該方法原型如下:

func (b *Reader) ReadBytes(delim byte) (line []byte, err error)

其中,參數(shù) delim 用于指定分割字節(jié)。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("C語言中文網(wǎng), Go語言入門教程")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    var delim byte = ','
    line, err := r.ReadBytes(delim)
    fmt.Println(string(line), err)
}

運行結(jié)果如下:

C語言中文網(wǎng), <nil>

4) ReadLine() 方法

ReadLine() 是一個低級的用于讀取一行數(shù)據(jù)的方法,大多數(shù)調(diào)用者應(yīng)該使用 ReadBytes('\n') 或者 ReadString('\n')。

ReadLine 返回一行,不包括結(jié)尾的回車字符,如果一行太長(超過緩沖區(qū)長度),參數(shù) isPrefix 會設(shè)置為 true 并且只返回前面的數(shù)據(jù),剩余的數(shù)據(jù)會在以后的調(diào)用中返回。

當(dāng)返回最后一行數(shù)據(jù)時,參數(shù) isPrefix 會置為 false。返回的字節(jié)切片只在下一次調(diào)用 ReadLine 前有效。ReadLine 會返回一個非空的字節(jié)切片或一個錯誤,方法原型如下:

func (b *Reader) ReadLine() (line []byte, isPrefix bool, err error)

示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("Golang is a beautiful language. \r\n I like it!")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    line, prefix, err := r.ReadLine()
    fmt.Println(string(line), prefix, err)
}

運行結(jié)果如下:

Golang is a beautiful language.  false <nil>

5) ReadRune() 方法

ReadRune() 方法的功能是讀取一個 UTF-8 編碼的字符,并返回其 Unicode 編碼和字節(jié)數(shù)。如果編碼錯誤,ReadRune 只讀取一個字節(jié)并返回 unicode.ReplacementChar(U+FFFD) 和長度 1。
該方法原型如下:

func (b *Reader) ReadRune() (r rune, size int, err error)

示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("C語言中文網(wǎng)")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    ch, size, err := r.ReadRune()
    fmt.Println(string(ch), size, err)
}

運行結(jié)果如下:

C 1 <nil>

6) ReadSlice() 方法

ReadSlice() 方法的功能是讀取數(shù)據(jù)直到分隔符“delim”處,并返回讀取數(shù)據(jù)的字節(jié)切片,下次讀取數(shù)據(jù)時返回的切片會失效。如果 ReadSlice 在查找到“delim”之前遇到錯誤,它返回讀取的所有數(shù)據(jù)和那個錯誤(通常是 io.EOF)。

如果緩沖區(qū)滿時也沒有查找到“delim”,則返回 ErrBufferFull 錯誤。ReadSlice 返回的數(shù)據(jù)會在下次 I/O 操作時被覆蓋,大多數(shù)調(diào)用者應(yīng)該使用 ReadBytes 或者 ReadString。只有當(dāng) line 不以“delim”結(jié)尾時,ReadSlice 才會返回非空 err。

該方法原型如下:

func (b *Reader) ReadSlice(delim byte) (line []byte, err error)

其中,參數(shù) delim 用于指定分割字節(jié)。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("C語言中文網(wǎng), Go語言入門教程")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    var delim byte = ','
    line, err := r.ReadSlice(delim)
    fmt.Println(string(line), err)
    line, err = r.ReadSlice(delim)
    fmt.Println(string(line), err)
    line, err = r.ReadSlice(delim)
    fmt.Println(string(line), err)
}

運行結(jié)果如下:

C語言中文網(wǎng), <nil>
Go語言入門教程 EOF
EOF

7) ReadString() 方法

ReadString() 方法的功能是讀取數(shù)據(jù)直到分隔符“delim”第一次出現(xiàn),并返回一個包含“delim”的字符串。

如果 ReadString 在讀取到“delim”前遇到錯誤,它返回已讀字符串和那個錯誤(通常是 io.EOF)。只有當(dāng)返回的字符串不以“delim”結(jié)尾時,ReadString 才返回非空 err。該方法原型如下:

func (b *Reader) ReadString(delim byte) (line string, err error)

其中,參數(shù) delim 用于指定分割字節(jié)。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("C語言中文網(wǎng), Go語言入門教程")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    var delim byte = ','
    line, err := r.ReadString(delim)
    fmt.Println(line, err)
}

運行結(jié)果為:

C語言中文網(wǎng), <nil>

8) UnreadByte() 方法

UnreadByte() 方法的功能是取消已讀取的最后一個字節(jié)(即把字節(jié)重新放回讀取緩沖區(qū)的前部)。只有最近一次讀取的單個字節(jié)才能取消讀取。該方法原型如下:

func (b *Reader) UnreadByte() error

9) UnreadRune() 方法

UnreadRune() 方法的功能是取消讀取最后一次讀取的 Unicode 字符。

如果最后一次讀取操作不是 ReadRune,UnreadRune 會返回一個錯誤(在這方面它比 UnreadByte 更嚴(yán)格,因為 UnreadByte 會取消上次任意讀操作的最后一個字節(jié))。

該方法原型如下:

func (b *Reader) UnreadRune() error

10) Buffered() 方法

Buffered() 方法的功能是返回可從緩沖區(qū)讀出數(shù)據(jù)的字節(jié)數(shù), 示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("Go語言入門教程")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    var buf [14]byte
    n, err := r.Read(buf[:])
    fmt.Println(string(buf[:n]), n, err)
    rn := r.Buffered()
    fmt.Println(rn)
    n, err = r.Read(buf[:])
    fmt.Println(string(buf[:n]), n, err)
    rn = r.Buffered()
    fmt.Println(rn)
}

運行結(jié)果如下:

Go語言入門 14 <nil>
6
教程 6 <nil>
0

11) Peek() 方法

Peek() 方法的功能是讀取指定字節(jié)數(shù)的數(shù)據(jù),這些被讀取的數(shù)據(jù)不會從緩沖區(qū)中清除。

在下次讀取之后,本次返回的字節(jié)切片會失效。如果 Peek 返回的字節(jié)數(shù)不足 n 字節(jié),則會同時返回一個錯誤說明原因,如果 n 比緩沖區(qū)要大,則錯誤為 ErrBufferFull。
該方法原型如下:

func (b *Reader) Peek(n int) ([]byte, error)

在方法 Peek() 中,參數(shù) n 是希望讀取的字節(jié)數(shù)。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    data := []byte("Go語言入門教程")
    rd := bytes.NewReader(data)
    r := bufio.NewReader(rd)
    bl, err := r.Peek(8)
    fmt.Println(string(bl), err)
    bl, err = r.Peek(14)
    fmt.Println(string(bl), err)
    bl, err = r.Peek(20)
    fmt.Println(string(bl), err)
}

運行結(jié)果如下:

Go語言 <nil>
Go語言入門 <nil>
Go語言入門教程 <nil>

5、Writer 對象

Writer 對象可以對數(shù)據(jù) I/O 接口 io.Writer 進(jìn)行輸出緩沖操作,Writer 結(jié)構(gòu)定義如下:

type Writer struct {
    //contains filtered or unexported fields
}

默認(rèn)情況下 Writer 對象沒有定義初始值,如果輸出緩沖過程中發(fā)生錯誤,則數(shù)據(jù)寫入操作立刻被終止,后續(xù)的寫操作都會返回寫入異常錯誤。

5.1、創(chuàng)建 Writer 對象

創(chuàng)建 Writer 對象的函數(shù)共有兩個分別是

  • NewWriter()

  • NewWriterSize(),

下面分別介紹一下。

1) NewWriter() 函數(shù)

NewWriter() 函數(shù)的功能是按照默認(rèn)緩沖區(qū)長度創(chuàng)建 Writer 對象,Writer 對象會將緩存的數(shù)據(jù)批量寫入底層 io.Writer 接口。該函數(shù)原型如下:

func NewWriter(wr io.Writer) *Writer

其中,參數(shù) wr 是 io.Writer 接口,Writer 對象會將數(shù)據(jù)寫入該接口。

2) NewWriterSize() 函數(shù)

NewWriterSize() 函數(shù)的功能是按照指定的緩沖區(qū)長度創(chuàng)建 Writer 對象,Writer 對象會將緩存的數(shù)據(jù)批量寫入底層 io.Writer 接口。該函數(shù)原型如下:

func NewWriterSize(wr io.Writer, size int) *Writer

其中,參數(shù) wr 是 io.Writer 接口,參數(shù) size 是指定的緩沖區(qū)字節(jié)長度。

5.2、操作 Writer 對象

操作 Writer 對象的方法共有 7 個,分別是 Available()、Buffered()、Flush()、Write()、WriteByte()、WriteRune() 和 WriteString() 方法,下面分別介紹。

1) Available() 方法

Available() 方法的功能是返回緩沖區(qū)中未使用的字節(jié)數(shù),該方法原型如下:

func (b *Writer) Available() int

示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    wr := bytes.NewBuffer(nil)
    w := bufio.NewWriter(wr)
    p := []byte("C語言中文網(wǎng)")
    fmt.Println("寫入前未使用的緩沖區(qū)為:", w.Available())
    w.Write(p)
    fmt.Printf("寫入%q后,未使用的緩沖區(qū)為:%d\n", string(p), w.Available())
}

運行結(jié)果如下:

寫入前未使用的緩沖區(qū)為: 4096
寫入"C語言中文網(wǎng)"后,未使用的緩沖區(qū)為:4080

2) Buffered() 方法

Buffered() 方法的功能是返回已寫入當(dāng)前緩沖區(qū)中的字節(jié)數(shù),該方法原型如下:

func (b *Writer) Buffered() int

示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    wr := bytes.NewBuffer(nil)
    w := bufio.NewWriter(wr)
    p := []byte("C語言中文網(wǎng)")
    fmt.Println("寫入前未使用的緩沖區(qū)為:", w.Buffered())
    w.Write(p)
    fmt.Printf("寫入%q后,未使用的緩沖區(qū)為:%d\n", string(p), w.Buffered())
    w.Flush()
    fmt.Println("執(zhí)行 Flush 方法后,寫入的字節(jié)數(shù)為:", w.Buffered())
}

該例測試結(jié)果為:

寫入前未使用的緩沖區(qū)為: 0
寫入"C語言中文網(wǎng)"后,未使用的緩沖區(qū)為:16
執(zhí)行 Flush 方法后,寫入的字節(jié)數(shù)為: 0

3) Flush() 方法

Flush() 方法的功能是把緩沖區(qū)中的數(shù)據(jù)寫入底層的 io.Writer,并返回錯誤信息。如果成功寫入,error 返回 nil,否則 error 返回錯誤原因。該方法原型如下:

func (b *Writer) Flush() error

示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    wr := bytes.NewBuffer(nil)
    w := bufio.NewWriter(wr)
    p := []byte("C語言中文網(wǎng)")
    w.Write(p)
    fmt.Printf("未執(zhí)行 Flush 緩沖區(qū)輸出 %q\n", string(wr.Bytes()))
    w.Flush()
    fmt.Printf("執(zhí)行 Flush 后緩沖區(qū)輸出 %q\n", string(wr.Bytes()))
}

運行結(jié)果如下:

未執(zhí)行 Flush 緩沖區(qū)輸出 ""
執(zhí)行 Flush 后緩沖區(qū)輸出 "C語言中文網(wǎng)"

4) Write() 方法

Write() 方法的功能是把字節(jié)切片 p 寫入緩沖區(qū),返回已寫入的字節(jié)數(shù) nn。如果 nn 小于 len(p),則同時返回一個錯誤原因。該方法原型如下:

func (b *Writer) Write(p []byte) (nn int, err error)

其中,參數(shù) p 是要寫入的字節(jié)切片。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    wr := bytes.NewBuffer(nil)
    w := bufio.NewWriter(wr)
    p := []byte("C語言中文網(wǎng)")
    n, err := w.Write(p)
    w.Flush()
    fmt.Println(string(wr.Bytes()), n, err)
}

運行結(jié)果如下:

C語言中文網(wǎng) 16 <nil>

5) WriteByte() 方法

WriteByte() 方法的功能是寫入一個字節(jié),如果成功寫入,error 返回 nil,否則 error 返回錯誤原因。該方法原型如下:

func (b *Writer) WriteByte(c byte) error

其中,參數(shù) c 是要寫入的字節(jié)數(shù)據(jù),比如 ASCII 字符。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    wr := bytes.NewBuffer(nil)
    w := bufio.NewWriter(wr)
    var c byte = 'G'
    err := w.WriteByte(c)
    w.Flush()
    fmt.Println(string(wr.Bytes()), err)
}

運行結(jié)果如下:

G <nil>

6) WriteRune() 方法

WriteRune() 方法的功能是以 UTF-8 編碼寫入一個 Unicode 字符,返回寫入的字節(jié)數(shù)和錯誤信息。該方法原型如下:

func (b *Writer) WriteRune(r rune) (size int,err error)

其中,參數(shù) r 是要寫入的 Unicode 字符。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    wr := bytes.NewBuffer(nil)
    w := bufio.NewWriter(wr)
    var r rune = 'G'
    size, err := w.WriteRune(r)
    w.Flush()
    fmt.Println(string(wr.Bytes()), size, err)
}

該例測試結(jié)果為:

G 1 <nil>

7) WriteString() 方法

WriteString() 方法的功能是寫入一個字符串,并返回寫入的字節(jié)數(shù)和錯誤信息。如果返回的字節(jié)數(shù)小于 len(s),則同時返回一個錯誤說明原因。該方法原型如下:

func (b *Writer) WriteString(s string) (int, error)

其中,參數(shù) s 是要寫入的字符串。示例代碼如下:

package main
import (
    "bufio"
    "bytes"
    "fmt"
)
func main() {
    wr := bytes.NewBuffer(nil)
    w := bufio.NewWriter(wr)
    s := "C語言中文網(wǎng)"
    n, err := w.WriteString(s)
    w.Flush()
    fmt.Println(string(wr.Bytes()), n, err)
}

運行結(jié)果如下:

C語言中文網(wǎng) 16 <nil>
?著作權(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容