新聞中心
在Go語言中,幾乎所有的 數(shù)據(jù)結(jié)構(gòu)都圍繞接口展開,接口是Go語言中所有數(shù)據(jù)結(jié)構(gòu)的核心。在實(shí)際開發(fā)過程中,無論是實(shí)現(xiàn) web 應(yīng)用程序,還是控制臺(tái)輸入輸出,又或者是網(wǎng)絡(luò)操作,都不可避免的會(huì)遇到 I/O 操作。

Go語言標(biāo)準(zhǔn)庫的 bufio 包中,實(shí)現(xiàn)了對(duì)數(shù)據(jù) I/O 接口的緩沖功能。這些功能封裝于接口 io.ReadWriter、io.Reader 和 io.Writer 中,并對(duì)應(yīng)創(chuàng)建了 ReadWriter、Reader 或 Writer 對(duì)象,在提供緩沖的同時(shí)實(shí)現(xiàn)了一些文本基本 I/O 操作功能。
ReadWriter 對(duì)象
ReadWriter 對(duì)象可以對(duì)數(shù)據(jù) I/O 接口 io.ReadWriter 進(jìn)行輸入輸出緩沖操作,ReadWriter 結(jié)構(gòu)定義如下:
type ReadWriter struct {
*Reader
*Writer
}
默認(rèn)情況下,ReadWriter 對(duì)象中存放了一對(duì) Reader 和 Writer 指針,它同時(shí)提供了對(duì)數(shù)據(jù) I/O 對(duì)象的讀寫緩沖功能。
可以使用 NewReadWriter() 函數(shù)創(chuàng)建 ReadWriter 對(duì)象,該函數(shù)的功能是根據(jù)指定的 Reader 和 Writer 創(chuàng)建一個(gè) ReadWriter 對(duì)象,ReadWriter 對(duì)象將會(huì)向底層 io.ReadWriter 接口寫入數(shù)據(jù),或者從 io.ReadWriter 接口讀取數(shù)據(jù)。該函數(shù)原型聲明如下:
func NewReadWriter(r *Reader, w *Writer) *ReadWriter
在函數(shù) NewReadWriter() 中,參數(shù) r 是要讀取的來源 Reader 對(duì)象,參數(shù) w 是要寫入的目的 Writer 對(duì)象。
Reader 對(duì)象
Reader 對(duì)象可以對(duì)數(shù)據(jù) I/O 接口 io.Reader 進(jìn)行輸入緩沖操作,Reader 結(jié)構(gòu)定義如下:
type Reader struct {
//contains filtered or unexported fields
)
默認(rèn)情況下 Reader 對(duì)象沒有定義初始值,輸入緩沖區(qū)最小值為 16。當(dāng)超出限制時(shí),另創(chuàng)建一個(gè)二倍的存儲(chǔ)空間。
創(chuàng)建 Reader 對(duì)象
可以創(chuàng)建 Reader 對(duì)象的函數(shù)一共有兩個(gè),分別是 NewReader() 和 NewReaderSize(),下面分別介紹。
1) NewReader() 函數(shù)
NewReader() 函數(shù)的功能是按照緩沖區(qū)默認(rèn)長(zhǎng)度創(chuàng)建 Reader 對(duì)象,Reader 對(duì)象會(huì)從底層 io.Reader 接口讀取盡量多的數(shù)據(jù)進(jìn)行緩存。該函數(shù)原型如下:
func NewReader(rd io.Reader) *Reader
其中,參數(shù) rd 是 io.Reader 接口,Reader 對(duì)象將從該接口讀取數(shù)據(jù)。
2) NewReaderSize() 函數(shù)
NewReaderSize() 函數(shù)的功能是按照指定的緩沖區(qū)長(zhǎng)度創(chuàng)建 Reader 對(duì)象,Reader 對(duì)象會(huì)從底層 io.Reader 接口讀取盡量多的數(shù)據(jù)進(jìn)行緩存。該函數(shù)原型如下:
func NewReaderSize(rd io.Reader, size int) *Reader
其中,參數(shù) rd 是 io.Reader 接口,參數(shù) size 是指定的緩沖區(qū)字節(jié)長(zhǎng)度。
操作 Reader 對(duì)象
操作 Reader 對(duì)象的方法共有 11 個(gè),分別是 Read()、ReadByte()、ReadBytes()、ReadLine()、ReadRune ()、ReadSlice()、ReadString()、UnreadByte()、UnreadRune()、Buffered()、Peek(),下面分別介紹。
1) Read() 方法
Read() 方法的功能是讀取數(shù)據(jù),并存放到字節(jié)切片 p 中。Read() 執(zhí)行結(jié)束會(huì)返回已讀取的字節(jié)數(shù),因?yàn)樽疃嘀徽{(diào)用底層的 io.Reader 一次,所以返回的 n 可能小于 len(p),當(dāng)字節(jié)流結(jié)束時(shí),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)
} 運(yùn)行結(jié)果如下:
C語言中文網(wǎng) 16
2) ReadByte() 方法
ReadByte() 方法的功能是讀取并返回一個(gè)字節(jié),如果沒有字節(jié)可讀,則返回錯(cuò)誤信息。該方法原型如下:
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)
} 運(yùn)行結(jié)果如下:
G
3) ReadBytes() 方法
ReadBytes() 方法的功能是讀取數(shù)據(jù)直到遇到第一個(gè)分隔符“delim”,并返回讀取的字節(jié)序列(包括“delim”)。如果 ReadBytes 在讀到第一個(gè)“delim”之前出錯(cuò),它返回已讀取的數(shù)據(jù)和那個(gè)錯(cuò)誤(通常是 io.EOF)。只有當(dāng)返回的數(shù)據(jù)不以“delim”結(jié)尾時(shí),返回的 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)
} 運(yùn)行結(jié)果如下:
C語言中文網(wǎng),
4) ReadLine() 方法
ReadLine() 是一個(gè)低級(jí)的用于讀取一行數(shù)據(jù)的方法,大多數(shù)調(diào)用者應(yīng)該使用 ReadBytes('\n') 或者 ReadString('\n')。ReadLine 返回一行,不包括結(jié)尾的回車字符,如果一行太長(zhǎng)(超過緩沖區(qū)長(zhǎng)度),參數(shù) isPrefix 會(huì)設(shè)置為 true 并且只返回前面的數(shù)據(jù),剩余的數(shù)據(jù)會(huì)在以后的調(diào)用中返回。
當(dāng)返回最后一行數(shù)據(jù)時(shí),參數(shù) isPrefix 會(huì)置為 false。返回的字節(jié)切片只在下一次調(diào)用 ReadLine 前有效。ReadLine 會(huì)返回一個(gè)非空的字節(jié)切片或一個(gè)錯(cuò)誤,方法原型如下:
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)
} 運(yùn)行結(jié)果如下:
Golang is a beautiful language. false
5) ReadRune() 方法
ReadRune() 方法的功能是讀取一個(gè) UTF-8 編碼的字符,并返回其 Unicode 編碼和字節(jié)數(shù)。如果編碼錯(cuò)誤,ReadRune 只讀取一個(gè)字節(jié)并返回 unicode.ReplacementChar(U+FFFD) 和長(zhǎng)度 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)
} 運(yùn)行結(jié)果如下:
C 1
6) ReadSlice() 方法
ReadSlice() 方法的功能是讀取數(shù)據(jù)直到分隔符“delim”處,并返回讀取數(shù)據(jù)的字節(jié)切片,下次讀取數(shù)據(jù)時(shí)返回的切片會(huì)失效。如果 ReadSlice 在查找到“delim”之前遇到錯(cuò)誤,它返回讀取的所有數(shù)據(jù)和那個(gè)錯(cuò)誤(通常是 io.EOF)。
如果緩沖區(qū)滿時(shí)也沒有查找到“delim”,則返回 ErrBufferFull 錯(cuò)誤。ReadSlice 返回的數(shù)據(jù)會(huì)在下次 I/O 操作時(shí)被覆蓋,大多數(shù)調(diào)用者應(yīng)該使用 ReadBytes 或者 ReadString。只有當(dāng) line 不以“delim”結(jié)尾時(shí),ReadSlice 才會(huì)返回非空 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)
} 運(yùn)行結(jié)果如下:
C語言中文網(wǎng),
Go語言入門教程 EOF
EOF
7) ReadString() 方法
ReadString() 方法的功能是讀取數(shù)據(jù)直到分隔符“delim”第一次出現(xiàn),并返回一個(gè)包含“delim”的字符串。如果 ReadString 在讀取到“delim”前遇到錯(cuò)誤,它返回已讀字符串和那個(gè)錯(cuò)誤(通常是 io.EOF)。只有當(dāng)返回的字符串不以“delim”結(jié)尾時(shí),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)
} 運(yùn)行結(jié)果為:
C語言中文網(wǎng),
8) UnreadByte() 方法
UnreadByte() 方法的功能是取消已讀取的最后一個(gè)字節(jié)(即把字節(jié)重新放回讀取緩沖區(qū)的前部)。只有最近一次讀取的單個(gè)字節(jié)才能取消讀取。該方法原型如下:
func (b *Reader) UnreadByte() error
9) UnreadRune() 方法
UnreadRune() 方法的功能是取消讀取最后一次讀取的 Unicode 字符。如果最后一次讀取操作不是 ReadRune,UnreadRune 會(huì)返回一個(gè)錯(cuò)誤(在這方面它比 UnreadByte 更嚴(yán)格,因?yàn)?UnreadByte 會(huì)取消上次任意讀操作的最后一個(gè)字節(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)
} 運(yùn)行結(jié)果如下:
Go語言入門 14
6
教程 6
0
11) Peek() 方法
Peek() 方法的功能是讀取指定字節(jié)數(shù)的數(shù)據(jù),這些被讀取的數(shù)據(jù)不會(huì)從緩沖區(qū)中清除。在下次讀取之后,本次返回的字節(jié)切片會(huì)失效。如果 Peek 返回的字節(jié)數(shù)不足 n 字節(jié),則會(huì)同時(shí)返回一個(gè)錯(cuò)誤說明原因,如果 n 比緩沖區(qū)要大,則錯(cuò)誤為 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)
} 運(yùn)行結(jié)果如下:
Go語言
Go語言入門
Go語言入門教程
Writer 對(duì)象
Writer 對(duì)象可以對(duì)數(shù)據(jù) I/O 接口 io.Writer 進(jìn)行輸出緩沖操作,Writer 結(jié)構(gòu)定義如下:
type Writer struct {
//contains filtered or unexported fields
}
默認(rèn)情況下 Writer 對(duì)象沒有定義初始值,如果輸出緩沖過程中發(fā)生錯(cuò)誤,則數(shù)據(jù)寫入操作立刻被終止,后續(xù)的寫操作都會(huì)返回寫入異常錯(cuò)誤。
創(chuàng)建 Writer 對(duì)象
創(chuàng)建 Writer 對(duì)象的函數(shù)共有兩個(gè)分別是 NewWriter() 和 NewWriterSize(),下面分別介紹一下。
1) NewWriter() 函數(shù)
NewWriter() 函數(shù)的功能是按照默認(rèn)緩沖區(qū)長(zhǎng)度創(chuàng)建 Writer 對(duì)象,Writer 對(duì)象會(huì)將緩存的數(shù)據(jù)批量寫入底層 io.Writer 接口。該函數(shù)原型如下:
func NewWriter(wr io.Writer) *Writer
其中,參數(shù) wr 是 io.Writer 接口,Writer 對(duì)象會(huì)將數(shù)據(jù)寫入該接口。
2) NewWriterSize() 函數(shù)
NewWriterSize() 函數(shù)的功能是按照指定的緩沖區(qū)長(zhǎng)度創(chuàng)建 Writer 對(duì)象,Writer 對(duì)象會(huì)將緩存的數(shù)據(jù)批量寫入底層 io.Writer 接口。該函數(shù)原型如下:
func NewWriterSize(wr io.Writer, size int) *Writer
其中,參數(shù) wr 是 io.Writer 接口,參數(shù) size 是指定的緩沖區(qū)字節(jié)長(zhǎng)度。
操作 Writer 對(duì)象
操作 Writer 對(duì)象的方法共有 7 個(gè),分別是 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())
} 運(yùn)行結(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())
} 該例測(cè)試結(jié)果為:
寫入前未使用的緩沖區(qū)為: 0
寫入"C語言中文網(wǎng)"后,未使用的緩沖區(qū)為:16
執(zhí)行 Flush 方法后,寫入的字節(jié)數(shù)為: 0
3) Flush() 方法
Flush() 方法的功能是把緩沖區(qū)中的數(shù)據(jù)寫入底層的 io.Writer,并返回錯(cuò)誤信息。如果成功寫入,error 返回 nil,否則 error 返回錯(cuò)誤原因。該方法原型如下:
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()))
} 運(yùn)行結(jié)果如下:
未執(zhí)行 Flush 緩沖區(qū)輸出 ""
執(zhí)行 Flush 后緩沖區(qū)輸出 "C語言中文網(wǎng)"
4) Write() 方法
Write() 方法的功能是把字節(jié)切片 p 寫入緩沖區(qū),返回已寫入的字節(jié)數(shù) nn。如果 nn 小于 len(p),則同時(shí)返回一個(gè)錯(cuò)誤原因。該方法原型如下:
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)
} 運(yùn)行結(jié)果如下:
C語言中文網(wǎng) 16
5) WriteByte() 方法
WriteByte() 方法的功能是寫入一個(gè)字節(jié),如果成功寫入,error 返回 nil,否則 error 返回錯(cuò)誤原因。該方法原型如下:
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)
} 運(yùn)行結(jié)果如下:
G
6) WriteRune() 方法
WriteRune() 方法的功能是以 UTF-8 編碼寫入一個(gè) Unicode 字符,返回寫入的字節(jié)數(shù)和錯(cuò)誤信息。該方法原型如下:
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)
} 該例測(cè)試結(jié)果為:
G 1
7) WriteString() 方法
WriteString() 方法的功能是寫入一個(gè)字符串,并返回寫入的字節(jié)數(shù)和錯(cuò)誤信息。如果返回的字節(jié)數(shù)小于 len(s),則同時(shí)返回一個(gè)錯(cuò)誤說明原因。該方法原型如下:
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)
} 運(yùn)行結(jié)果如下:
C語言中文網(wǎng) 16
網(wǎng)頁標(biāo)題:創(chuàng)新互聯(lián)GO教程:Go語言數(shù)據(jù)I/O對(duì)象及操作
當(dāng)前鏈接:http://www.dlmjj.cn/article/cogpdes.html


咨詢
建站咨詢
