參考:
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>