Reader和Writer
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
实现reader和writer的模块:
围绕io.Reader/Writer,有几个常用的实现:
net.Conn, os.Stdin, os.File: 网络、标准输入输出、文件的流读取
strings.Reader: 把字符串抽象成Reader
bytes.Reader: 把[]byte抽象成Reader
bytes.Buffer: 把[]byte抽象成Reader和Writer
bufio.Reader/Writer: 抽象成带缓冲的流读取(比如按行读写)
bufio
bufio就是在系统io中间多了一个缓冲区,
以buferio为例,来看具体的实现:
1 读-将一个string.newreader读到*bufio
2 写-先定义一个bytes.newbuffer,再构造成bufio.newwriter,再调用write/writestring方法写入byte/string
package main
import (
"bytes"
"fmt"
// "os"
"strings"
"bufio"
)
//type Reader struct { ... }
// NewReaderSize 将 rd 封装成一个带缓存的 bufio.Reader 对象,
// 缓存大小由 size 指定(如果小于 16 则会被设置为 16)。
// 如果 rd 的基类型就是有足够缓存的 bufio.Reader 类型,则直接将
// rd 转换为基类型返回。
//func NewReaderSize(rd io.Reader, size int) *Reader
// NewReader 相当于 NewReaderSize(rd, 4096)
//func NewReader(rd io.Reader) *Reader
// bufio.Reader 实现了如下接口:
// io.Reader
// io.WriterTo
// io.ByteScanner
// io.RuneScanner
func testRead(){
s := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
br := bufio.NewReader(s)
buf:=make([]byte,1024)//sliece
n, err := br.Read(buf)
// buf:= [512]byte{}//array
// n, err := br.Read(buf[:])//将array切片
fmt.Printf("%s %v %v\n", buf[:n], n, err) // ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 36 <nil>
}
func testReadstring(){
s := strings.NewReader("亲爱的提奥,梵高")
br := bufio.NewReader(s)
// ReadString 在 br 中查找 delim 并返回 delim 及其之前的所有数据。
// func (b *Reader) ReadString(delim byte) (line []byte, err error)
n, err := br.ReadString(',')
fmt.Printf("%s %v\n", n, err) // 亲爱的提奥, <nil>
// 如果未找到 delim 且遇到错误(通常是 io.EOF),则返回缓存中的所
n, err = br.ReadString(',')
fmt.Printf("%s %v\n", n, err) // 梵高 EOF
fmt.Println(n)
fmt.Println(string(n))
}
func TestReadBytes() {
// ReadBytes 功能同 ReadSlice,只不过返回的是缓存的拷贝。
// func (b *Reader) ReadBytes(delim byte) (line []byte, err error)
s := strings.NewReader("ABC,你好啊,HIJ")
br := bufio.NewReader(s)
line, err := br.ReadBytes(',')
if err != nil {
panic(err)
}
fmt.Printf("%s %v\n", line, err) //
line, err = br.ReadBytes(',')
if err != nil {
panic(err)
}
fmt.Printf("%s %v\n", line, err) //
fmt.Println(line)
fmt.Println(string(line))
}
// ReadLine 是一个低水平的行读取原语,大多数情况下,应该使用
// ReadBytes('\n') 或 ReadString('\n'),或者使用一个 Scanner。
//
// ReadLine 通过调用 ReadSlice 方法实现,返回的也是缓存的切片。用于
// 读取一行数据,不包括行尾标记(\n 或 \r\n)。
//
// 只要能读出数据,err 就为 nil。如果没有数据可读,则 isPrefix 返回
// false,err 返回 io.EOF。
//
// 如果找到行尾标记,则返回查找结果,isPrefix 返回 false。
// 如果未找到行尾标记,则:
// 1、缓存不满,则将缓存填满后再次查找。
// 2、缓存是满的,则返回整个缓存,isPrefix 返回 true。
//
// 整个数据尾部“有一个换行标记”和“没有换行标记”的读取结果是一样。
//
// 如果 ReadLine 读取到换行标记,则调用 UnreadByte 撤销的是换行标记,
// 而不是返回的数据。
func testReadline(){
s := strings.NewReader("ABC,你好啊,HIJ,李银河")
br := bufio.NewReader(s)
var finish bool
line,finish ,err := br.ReadLine()
if err != nil {
panic(err)
}
fmt.Println(line,finish)
fmt.Println(string(line))
}
//type Writer struct { ... }
// NewWriterSize 将 wr 封装成一个带缓存的 bufio.Writer 对象,
// 缓存大小由 size 指定(如果小于 4096 则会被设置为 4096)。
// 如果 wr 的基类型就是有足够缓存的 bufio.Writer 类型,则直接将
// wr 转换为基类型返回。
//func NewWriterSize(wr io.Writer, size int) *Writer
// NewWriter 相当于 NewWriterSize(wr, 4096)
//func NewWriter(wr io.Writer) *Writer
//func NewWriter(wr io.Writer) *Writer
// bufio.Writer 实现了如下接口:
// io.Writer
// io.ReaderFrom
// io.ByteWriter
// WriteString 功能同 Write,只不过写入的是字符串
// func (b *Writer) WriteString(s string) (int, error)
// WriteRune 向 b 写入 r 的 UTF-8 编码,返回 r 的编码长度。
// func (b *Writer) WriteRune(r rune) (size int, err error)
// Flush 将缓存中的数据提交到底层的 io.Writer 中
// func (b *Writer) Flush() error
// Available 返回缓存中未使用的空间的长度
// func (b *Writer) Available() int
// Buffered 返回缓存中未提交的数据的长度
// func (b *Writer) Buffered() int
// Reset 将 b 的底层 Writer 重新指定为 w,同时丢弃缓存中的所有数据,复位
// 所有标记和错误信息。相当于创建了一个新的 bufio.Writer。
// func (b *Writer) Reset(w io.Writer)
func TestWriteTo() {
// WriteTo方法实现了io.WriterTo接口。
// func (b *Reader) WriteTo(w io.Writer) (n int64, err error)
s := strings.NewReader("李银河")
br := bufio.NewReader(s)
b := bytes.NewBuffer(make([]byte, 0))
br.WriteTo(b)
fmt.Println(b)
fmt.Printf("%T\n",b)
fmt.Println(b.String())
}
func TestNewWriter() {
// NewWriter创建一个具有默认大小缓冲、写入w的*Writer。
// 相当于 NewWriterSize(wr, 4096)
// func NewWriter(w io.Writer) *Writer
// Buffered()返回缓冲中已使用的字节数。
// func (b *Writer) Buffered() int
// Available()返回缓冲中还有多少字节未使用。
// func (b *Writer) Available() int
// Reset丢弃缓冲中的数据,清除任何错误,将b重设为将其输出写入w。
// func (b *Writer) Reset(w io.Writer)
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
fmt.Println(bw.Available(), bw.Buffered()) // 4096 0
bw.WriteString("card")
fmt.Println(bw.Available(), bw.Buffered()) // 4092 4
bw.Reset(b)
fmt.Println(bw.Available(), bw.Buffered()) // 4096 0
fmt.Println(bw)
}
func TestWriteString() {
// WriteString 同 Write,只不过写入的是字符串
// func (b *Writer) WriteString(s string) (int, error)
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
bw.WriteString("hello world")
bw.Flush()//y一定要flush到底层//y一定要flush到底层//y一定要flush到底层
fmt.Printf("%s\n", b)
}
func TestWritebytes() {
// WriteString 同 Write,只不过写入的是字符串
// func (b *Writer) WriteString(s string) (int, error)
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
bw.WriteByte('h')
bw.Flush()//y一定要flush到底层//y一定要flush到底层//y一定要flush到底层
fmt.Printf("%s\n", b)
}
func TestWriterune() {
// WriteString 同 Write,只不过写入的是字符串
// func (b *Writer) WriteString(s string) (int, error)
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
bw.WriteRune('h')
bw.Flush()//y一定要flush到底层//y一定要flush到底层//y一定要flush到底层
fmt.Printf("%s\n", b)
}
func TestReadFrom() {
// ReadFrom实现了io.ReaderFrom接口。
//将r读到b
// func (b *Writer) ReadFrom(r io.Reader) (n int64, err error)
// ReadFrom无需使用Flush
// b := bytes.NewBuffer(make([]byte, 0))
b :=bytes.NewBufferString("你好啊")
s := strings.NewReader(",李银河")
bw := bufio.NewWriter(b)
bw.ReadFrom(s)
fmt.Println(b)
}
func TestReadWriter() {
// ReadWriter类型保管了指向Reader和Writer类型的指针
// 实现了io.ReadWriter接口。
// NewReadWriter 生成bufio.ReadWriter对象
// func NewReadWriter(r *Reader, w *Writer) *ReadWriter
b := bytes.NewBuffer(make([]byte, 0))
bw := bufio.NewWriter(b)
s := strings.NewReader("hello world")
br := bufio.NewReader(s)
rw := bufio.NewReadWriter(br, bw)
word, err := rw.ReadString(' ')
if err != nil {
panic(err)
}
fmt.Printf("%s\n", word) // hello
_, err = rw.WriteString(",I'm coming")
if err != nil {
panic(err)
}
rw.Flush()
fmt.Println(b)
}
func TestNewScanner() {
// Scanner 提供了一个方便的接口来读取数据,例如遍历多行文本中的行。Scan 方法会通过
// 一个“匹配函数”读取数据中符合要求的部分,跳过不符合要求的部分。“匹配函数”由调
// 用者指定。本包中提供的匹配函数有“行匹配函数”、“字节匹配函数”、“字符匹配函数”
// 和“单词匹配函数”,用户也可以自定义“匹配函数”。默认的“匹配函数”为“行匹配函
// 数”,用于获取数据中的一行内容(不包括行尾标记)
//
// Scanner 使用了缓存,所以匹配部分的长度不能超出缓存的容量。默认缓存容量为 4096 -
// bufio.MaxScanTokenSize,用户可以通过 Buffer 方法指定自定义缓存及其最大容量。
//
// Scan 在遇到下面的情况时会终止扫描并返回 false(扫描一旦终止,将无法再继续):
// 1、遇到 io.EOF
// 2、遇到读写错误
// 3、“匹配部分”的长度超过了缓存的长度
//
// 如果需要对错误进行更多的控制,
// 或“匹配部分”超出缓存容量,或需要连续扫描,
// 则应该使用 bufio.Reader
// func NewScanner(r io.Reader) *Scanner
// Bytes方法返回最近一次Scan调用生成的token。
// 底层数组指向的数据可能会被下一次Scan的调用重写。
// func (s *Scanner) Bytes() []byte
// Buffer()方法设置扫描时使用的初始缓冲区和最大值
// 默认情况下,Scan使用内部缓冲区并设置MaxScanTokenSize的最大令牌大小
s := strings.NewReader("周起\n卡牌\n程序员\n")
bs := bufio.NewScanner(s)
bs.Buffer(make([]byte,0),bufio.MaxScanTokenSize)
for bs.Scan() {
// 周起
// 卡牌
// 程序员
fmt.Printf("%s\n", bs.Bytes())
}
}
func TestScan() {
// Scan方法获取当前位置的token(该token可以通过Bytes或Text方法获得),
// 并让Scanner的扫描位置移动到下一个token。
// 当扫描因为抵达输入流结尾或者遇到错误而停止时,
// 本方法会返回false。在Scan方法返回false后,
// Err方法将返回扫描时遇到的任何错误;
// 除非是io.EOF,此时Err会返回nil。
// func (s *Scanner) Scan() bool
s := strings.NewReader("周起 卡牌 程序员")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanWords)
for bs.Scan() {
fmt.Printf("%s %s\n", bs.Text(), bs.Bytes())
}
}
func TestScanBytes() {
// Bytes方法返回最近一次Scan调用生成的token。
// 底层数组指向的数据可能会被下一次Scan的调用重写。
s := strings.NewReader("abcd")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanBytes)
for bs.Scan(){
// a
// b
// c
// d
fmt.Printf("%s\n", bs.Bytes())
}
}
func TestScanRunes() {
// ScanRunes是用于Scanner类型的分割函数(符合SplitFunc),
// 本函数会将每个utf-8编码的unicode码值作为一个token返回。
s := strings.NewReader("周起卡牌程序员")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanRunes)
for bs.Scan() {
// 周
// 起
// 卡
// 牌
// 程
// 序
// 员
fmt.Printf("%s\n", bs.Text())
}
}
func TestScanWords() {
// ScanRunes是用于Scanner类型的分割函数(符合SplitFunc),
// 本函数会将空白(参见unicode.IsSpace)
// 分隔的片段(去掉前后空白后)作为一个token返回。
// 本函数永远不会返回空字符串。
s := strings.NewReader("我 是 卡 牌")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanWords)
for bs.Scan(){
// 我
// 是
// 卡
// 牌
fmt.Printf("%s\n", bs.Text())
}
}
func TestScanLines() {
// 将每一行文本去掉末尾的换行标记作为一个token返回
// 此函数的bs.Scan()的默认值
s := strings.NewReader("卡牌\n周起\n程序员\n")
bs := bufio.NewScanner(s)
bs.Split(bufio.ScanLines)
for bs.Scan(){
// 卡牌
// 周起
// 程序员
fmt.Printf("%s\n", bs.Text())
}
}
func main(){
testRead()
testReadstring()
TestReadBytes()
testReadline()
TestWriteTo()
TestWriteString()
TestWritebytes()
TestWriterune()
TestReadFrom()
TestScan()
TestNewScanner()
TestScanBytes()
TestScanWords()
TestScanRunes()
TestScanLines()
}
代码参考:https://blog.csdn.net/weixin_46742102/article/details/107937096
buffer
先看buffer结构体
// type Buffer struct {
// buf []byte // byte切片 contents are the bytes buf[off : len(buf)]
// off int // 偏移量,read中记录已读入的位置,write中记录写入的位置
// lastRead readOp // 记录最后读入的位置
// }
new方法:
// func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
// func NewBufferString(s string) *Buffer {
// return &Buffer{buf: []byte(s)}
// }
buffer:
1 读 从b读到p,先将b new成buffer,定义一个[]]byte类型的p
2 写 将一个[]byte写到*bufferr
//func (b *Buffer) Read(p []byte) (n int, err error)
//从b读到p,先将b new成buffer,定义一个[]]byte类型的p
package main
import (
"bytes"
"fmt"
"os"
"strings"
)
func main() {
Newbuffer()
Readrune()
// Readfrombuffer()
// Readstrings()
Readbyte()
ReadNext()
// Writetobuffer()
}
// type Buffer struct {
// buf []byte // byte切片 contents are the bytes buf[off : len(buf)]
// off int // 偏移量,read中记录已读入的位置,write中记录写入的位置
// lastRead readOp // 记录最后读入的位置
// }
// func NewBuffer(buf []byte) *Buffer { return &Buffer{buf: buf} }
// func NewBufferString(s string) *Buffer {
// return &Buffer{buf: []byte(s)}
// }
func Newbuffer() {
//bytes.buffer
buf1 := bytes.NewBufferString("hello")
buf2 := bytes.NewBuffer([]byte("hello"))
buf3 := bytes.NewBuffer([]byte{'h', 'e', 'l', 'l', 'o'})
// 以上三者等效,输出//hello
buf4 := bytes.NewBufferString("")
buf5 := bytes.NewBuffer([]byte{})
// 以上两者等效,输出//""
fmt.Println(buf1,buf1.String(), buf2, buf3, buf4, buf5, 1)
fmt.Printf("%T\n",buf2)
}
//func (b *Buffer) Read(p []byte) (n int, err error)
//从b读到p,先将b new成buffer,定义一个[]]byte类型的p
func Readfrombuffer(){
s1 := []byte("hello")
buff := bytes.NewBuffer(s1)
s2 := []byte(" world")
buff.Write(s2)
fmt.Println(buff.String()) //hello world
s3 := make([]byte,3)
buff.Read(s3) //把buff的内容读入到s3,s3的容量为3,读了3个过来
fmt.Println(buff.String()) //lo world
fmt.Println(string(s3)) //hel
buff.Read(s3) //继续读入3个,原来的被覆盖
fmt.Println(buff.String()) //world
fmt.Println(string(s3)) //"lo "
}
func Readbyte(){
buf := bytes.NewBufferString("hello")
fmt.Println(buf.String())
for i :=0;i<buf.Len();i++ {
b,_ := buf.ReadByte() //取出第一个byte,赋值给b
fmt.Println(buf.String()) //ello
fmt.Printf("取出了%s\n",string(b)) //h
}
}
func Readrune(){//int32,相当于java的char
buf6 := bytes.NewBufferString("你好啊李银河hello")
fmt.Println(buf6.String())//你好啊李银河hello
fmt.Println(buf6.Len()) //23 3*6+5
for i :=0;i<buf6.Len();i++ {
b,n,_ := buf6.ReadRune() //取出第一个rune
fmt.Println(string(b)) //你
fmt.Println(n) //3,"你“作为utf8存储占3个byte
}
fmt.Println(buf6.String())
}
func Readbytes() {
var d byte = ',' //分隔符
buf := bytes.NewBufferString("你好,charlie,pretty ,boy")
fmt.Println(buf.String()) //你好esmieth
for {
b,_ := buf.ReadBytes(d) //读到分隔符,并返回给b
if strings.Compare(string(b),"")==0{//读到""后返回结束循坏
return
}
fmt.Println(string(b)) //你好e
}
}
func ReadNext() {
buf := bytes.NewBufferString("你好,charlie,pretty ,boy")
fmt.Println(buf.String()) //你好esmieth
for{
b:= buf.Next(3) //读取3字节返回给b
if strings.Compare(string(b),"")==0{//读到""后返回结束循坏,一定要设置返回条件
return
}
fmt.Println(string(b)) //你好e
}
}
func Readstrings(){
var d byte = ','
buf := bytes.NewBufferString("你好,smieth,and,lucy")
fmt.Println(buf.String()) //你好esmieth
for {
b,_:= buf.ReadString(d)
if strings.Compare(string(b),"")==0{//读到""后返回结束循坏
return
} //读取到分隔符,并返回给b
fmt.Println(string(b))
//你好e
}
}
// 读取文件
func Readfromfile(){
file, _ := os.Open("text.txt")
buf := bytes.NewBufferString("")
for {
n,_:=buf.ReadFrom(file)
if n==0{
return
}
fmt.Println(buf.String())
}
}
func Writetobuffer() {
//write string to buffer
s0 := " charlie"
buf0 := bytes.NewBufferString("hello")
fmt.Println(buf0.String()) //hello
buf0.WriteString(s0) //将string写入到buf的尾部
fmt.Println(buf0.String()) //hello charlie
//write []byte to buffer
s := []byte("world")
buf := bytes.NewBufferString("hello")
fmt.Println(buf.String()) //hello
buf.Write(s) //将s这个slice添加到buf的尾部
fmt.Println(buf.String()) //hello world
//write byte to buffer
var s1 byte = 'w'//byte:字符
buf1 := bytes.NewBufferString("hello ")
fmt.Println(s1) //把buf的内容转换为string,hello
buf1.WriteByte(s1) //将s写到buf的尾部
fmt.Println(buf1) //hello?
}
func Writefrombuffer(){
file,_ := os.Create("text.txt")
// for i:=0;i<50;i++{
buf2 := bytes.NewBufferString("hello world,my name is charlie Wong\n")
buf2.WriteTo(file)//func (b *Buffer) WriteTo(w io.Writer) (n int64, err error)
// }
}