golang的io包read和write

一般的,计算机程序是:输入 (Input) 经过算法处理产生输出 (Output)。各种语言一般都会提供IO库供开发者使用。

IO操作封装在如下几个包中:

  • io为io原生 (I/O primitives) 提供基本的接口
  • io/ioutiil 封装一些实用的I/O函数
  • fmt 实现格式化I/O,类似C语言中的printf和scanf
  • bufio 实现带缓冲I/O

IO读写原理

所谓IO的读写,本质上是相对与程序而言,读取数据进入程序,输出数据写到外部设备. 所以理解下面五点:

  1. 从哪里读
  2. 怎么读,读的方式有哪些
  3. 数据到程序用什么数据结构存储,用[]byte 还是buffer等
  4. 怎么写,写的方式有哪些
  5. 写到哪里去 (这里的哪里指的是实现Write方法的抽象)

IO接口操作

1. 最抽象的两个接口 Reader 和 Writer

1
2
3
type Reader interface {
    Read(p []byte) (n int, err error)
}
1
2
3
4
5
6
7
8
9
// 怎么读
func ReadFrom(reader io.Reader, num int) ([]byte, error) {
    p := make([]byte, num) // 用字节存储
    n, err := reader.Read(p) // 从reader中将数据读到字节中 ,每次读取的长度不超过num的长度
    if n > 0 {
        return p[:n], nil
    }
    return p, err
}
1
2
3
4
5
6
7
8
// 从标准输入读取
data, err := ReadFrom(os.Stdin, 11)

// 从普通文件读取,其中 file 是 os.File 的实例
data, err := ReadFrom(file, 9)

// 从字符串读取  Reader 可以读取字符串的read方法实现
data, err := ReadFrom(strings.NewReader("from string"), 12)
1
2
3
type Writer interface {
    Write(p []byte) (n int, err error)
}
1
2
3
func Println(a ...interface{}) (n int, err error) {
    return Fprintln(os.Stdout, a...) //将数据写到标准输出stdout中
}

os本质实现

1
2
3
4
5
var (
    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)
  • os.File 同时实现了 io.Reader 和 io.Writer
  • strings.Reader 实现了 io.Reader
  • bufio.Reader/Writer 分别实现了 io.Reader 和 io.Writer
  • bytes.Buffer 同时实现了 io.Reader 和 io.Writer
  • bytes.Reader 实现了 io.Reader
  • compress/gzip.Reader/Writer 分别实现了 io.Reader 和 io.Writer
  • crypto/cipher.StreamReader/StreamWriter 分别实现了 io.Reader 和 io.Writer
  • crypto/tls.Conn 同时实现了 io.Reader 和 io.Writer
  • encoding/csv.Reader/Writer 分别实现了 io.Reader 和 io.Writer
  • mime/multipart.Part 实现了 io.Reader
  • net/conn 分别实现了 io.Reader 和 io.Writer(Conn接口定义了Read/Write)
1
2
实现了 Reader 的类型:LimitedReader、PipeReader、SectionReader
实现了 Writer 的类型:PipeWriter

2. 读写增强接口

ReaderAt 和 WriterAt 接口

1
2
3
4
5
6
7
8
9
// 从偏移位置开始读
type ReaderAt interface {
    ReadAt(p []byte, off int64) (n int, err error)
}

// 从便宜位置开始写
type WriterAt interface {
    WriteAt(p []byte, off int64) (n int, err error)
}

ReaderFrom 和 WriterTo 接口

1
2
3
4
5
6
7
8
// 从reader一个具有read方法的抽象的输入中读
type ReaderFrom interface {
    ReadFrom(r Reader) (n int64, err error)
}
// 向reader一个具有write方法的抽象的输出中写
type WriterTo interface {
    WriteTo(w Writer) (n int64, err error)
}

Seeker 接口

1
2
3
4
5

// Seek 设置偏移量,可以从偏移位置开始操作数据流
type Seeker interface {
    Seek(offset int64, whence int) (ret int64, err error)
}

Closer接口

1
2
3
4
// 关闭数据流
type Closer interface {
    Close() error
}

3. 实现read和write方法的特殊对象

ByteReader 和 ByteWriter 接口

1
2
3
4
5
6
7
8
9
// 字节读接口
type ByteReader interface {
    ReadByte() (c byte, err error)
}

// 字节写接口
type ByteWriter interface {
    WriteByte(c byte) error
}
  • bufio.Reader/Writer 分别实现了io.ByteReader 和 io.ByteWriter
  • bytes.Buffer 同时实现了 io.ByteReader 和 io.ByteWriter
  • bytes.Reader 实现了 io.ByteReader
  • strings.Reader 实现了 io.ByteReader

** ByteScanner、RuneReader 和 RuneScanner接口**

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type ByteScanner interface {
    ByteReader
    UnreadByte() error
}

type RuneReader interface {
	ReadRune() (r rune, size int, err error)
}

type RuneScanner interface {
	RuneReader
	UnreadRune() error
}

ReadCloser、ReadSeeker、ReadWriteCloser、ReadWriteSeeker、ReadWriter、WriteCloser 和 WriteSeeker 接口

1
2
3
4
type ReadWriter interface {
    Reader
    Writer
}

SectionReader 类型

1
2
3
4
5
6
type SectionReader struct {
    r     ReaderAt    // 该类型最终的 Read/ReadAt 最终都是通过 r 的 ReadAt 实现
    base  int64        // NewSectionReader 会将 base 设置为 off
    off   int64        // 从 r 中的 off 偏移处开始读取数据
    limit int64        // limit - off = SectionReader 流的长度
}

LimitedReader 类型

1
2
3
4
type LimitedReader struct {
    R Reader // underlying reader,最终的读取操作通过 R.Read 完成
    N int64  // max bytes remaining
}

PipeReader 和 PipeWriter 类型

1
2
3
4
5
6
type PipeReader struct {
    p *pipe
}
type PipeWriter struct {
    p *pipe
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
func main() {
    pipeReader, pipeWriter := io.Pipe()
    go PipeWrite(pipeWriter)
    go PipeRead(pipeReader)
    time.Sleep(30 * time.Second)
}

func PipeWrite(writer *io.PipeWriter){
    data := []byte("Go语言中文网")
    for i := 0; i < 3; i++{
        n, err := writer.Write(data)
        if err != nil{
            fmt.Println(err)
            return
        }
        fmt.Printf("写入字节 %d\n",n)
    }
    writer.CloseWithError(errors.New("写入段已关闭"))
}

func PipeRead(reader *io.PipeReader){
    buf := make([]byte, 128)
    for{
        fmt.Println("接口端开始阻塞5秒钟...")
        time.Sleep(5 * time.Second)
        fmt.Println("接收端开始接受")
        n, err := reader.Read(buf)
        if err != nil{
            fmt.Println(err)
            return
        }
        fmt.Printf("收到字节: %d\n buf内容: %s\n",n,buf)
    }
}

4. 工具函数

Copy 和 CopyN 函数

1
func Copy(dst Writer, src Reader) (written int64, err error)

Copy 将 src 复制到 dst,直到在 src 上到达 EOF 或发生错误。

1
func CopyN(dst Writer, src Reader, n int64) (written int64, err error)

ReadAtLeast 和 ReadFull 函数

1
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
1
func ReadFull(r Reader, buf []byte) (n int, err error)

WriteString 函数

1
func WriteString(w Writer, s string) (n int, err error)

MultiReader 和 MultiWriter 函数

1
2
func MultiReader(readers ...Reader) Reader
func MultiWriter(writers ...Writer) Writer

TeeReader函数

1
func TeeReader(r Reader, w Writer) Reader