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的读写,本质上是相对与程序而言,读取数据进入程序,输出数据写到外部设备.
所以理解下面五点:
- 从哪里读
- 怎么读,读的方式有哪些
- 数据到程序用什么数据结构存储,用[]byte 还是buffer等
- 怎么写,写的方式有哪些
- 写到哪里去 (这里的哪里指的是实现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
|