//4.打开文件: //file3 ,err := os.Open(fileName1) //只读的 //if err != nil{ // fmt.Println("err:",err) // return //} //fmt.Println(file3) /* 第一个参数:文件名称 第二个参数:文件的打开方式 const ( // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified. O_RDONLY int = syscall.O_RDONLY // open the file read-only. O_WRONLY int = syscall.O_WRONLY // open the file write-only. O_RDWR int = syscall.O_RDWR // open the file read-write. // The remaining values may be or'ed in to control behavior. O_APPEND int = syscall.O_APPEND // append data to the file when writing. O_CREATE int = syscall.O_CREAT // create a new file if none exists. O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist. O_SYNC int = syscall.O_SYNC // open for synchronous I/O. O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened. ) 第三个参数:文件的权限:文件不存在创建文件,需要指定权限 */ //file4,err := os.OpenFile(fileName1,os.O_RDONLY|os.O_WRONLY,os.ModePerm) //if err != nil{ // fmt.Println("err:",err) // return //} //fmt.Println(file4)
WriterTo 将对象的数据流写入到 w 中 直到对象的数据流全部写入完毕或遇到写入错误为止 返回值 n 是写入的字节数 返回值 err 就是 w 的返回值 err
定义ReaderAt接口,ReaderAt 接口封装了基本的 ReadAt 方法
1 2 3
type ReaderAt interface { ReadAt(p []byte, off int64) (n int, err error) }
1 2 3 4 5 6 7 8 9 10 11 12 13
ReadAt 从对象数据流的 off 处读出数据到 p 中 忽略数据的读写指针,从数据的起始位置偏移 off 处开始读取 如果对象的数据流只有部分可用,不足以填满 p 则 ReadAt 将等待所有数据可用之后,继续向 p 中写入 直到将 p 填满后再返回 在这点上 ReadAt 要比 Read 更严格 返回读取的字节数 n 和读取时遇到的错误 如果 n < len(p),则需要返回一个 err 值来说明 为什么没有将 p 填满(比如 EOF) 如果 n = len(p),而且对象的数据没有全部读完,则 err 将返回 nil 如果 n = len(p),而且对象的数据刚好全部读完,则 err 将返回 EOF 或者 nil(不确定)
定义WriterAt接口,WriterAt 接口封装了基本的 WriteAt 方法
1 2 3
type WriterAt interface { WriteAt(p []byte, off int64) (n int, err error) }
1 2 3 4 5
WriteAt 将 p 中的数据写入到对象数据流的 off 处 忽略数据的读写指针,从数据的起始位置偏移 off 处开始写入 返回写入的字节数和写入时遇到的错误 如果 n < len(p),则必须返回一个 err 值来说明 为什么没有将 p 完全写入
funccopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error) { // If the reader has a WriteTo method, use it to do the copy. // Avoids an allocation and a copy. if wt, ok := src.(WriterTo); ok { return wt.WriteTo(dst) } // Similarly, if the writer has a ReadFrom method, use it to do the copy. if rt, ok := dst.(ReaderFrom); ok { return rt.ReadFrom(src) } if buf == nil { size := 32 * 1024 if l, ok := src.(*LimitedReader); ok && int64(size) > l.N { if l.N < 1 { size = 1 } else { size = int(l.N) } } buf = make([]byte, size) } for { nr, er := src.Read(buf) if nr > 0 { nw, ew := dst.Write(buf[0:nr]) if nw > 0 { written += int64(nw) } if ew != nil { err = ew break } if nr != nw { err = ErrShortWrite break } } if er != nil { if er != EOF { err = er } break } } return written, err }
const ( SeekStart = 0// seek relative to the origin of the file SeekCurrent = 1// seek relative to the current offset SeekEnd = 2// seek relative to the end )
funcmain() { /* seek(offset,whence),设置指针光标的位置 第一个参数:偏移量 第二个参数:如何设置 0:seekStart表示相对于文件开始, 1:seekCurrent表示相对于当前偏移量, 2:seek end表示相对于结束。 const ( SeekStart = 0 // seek relative to the origin of the file SeekCurrent = 1 // seek relative to the current offset SeekEnd = 2 // seek relative to the end ) 随机读取文件: 可以设置指针光标的位置 */
// Reader implements buffering for an io.Reader object. type Reader struct { buf []byte rd io.Reader // reader provided by the client r, w int// buf read and write positions err error lastByte int// last byte read for UnreadByte; -1 means invalid lastRuneSize int// size of last rune read for UnreadRune; -1 means invalid }
// Read reads data into p. // It returns the number of bytes read into p. // The bytes are taken from at most one Read on the underlying Reader, // hence n may be less than len(p). // To read exactly len(p) bytes, use io.ReadFull(b, p). // At EOF, the count will be zero and err will be io.EOF. func(b *Reader) Read(p []byte) (n int, err error) { n = len(p) if n == 0 { return0, b.readErr() } if b.r == b.w { if b.err != nil { return0, b.readErr() } iflen(p) >= len(b.buf) { // Large read, empty buffer. // Read directly into p to avoid copy. n, b.err = b.rd.Read(p) if n < 0 { panic(errNegativeRead) } if n > 0 { b.lastByte = int(p[n-1]) b.lastRuneSize = -1 } return n, b.readErr() } // One read. // Do not use b.fill, which will loop. b.r = 0 b.w = 0 n, b.err = b.rd.Read(b.buf) if n < 0 { panic(errNegativeRead) } if n == 0 { return0, b.readErr() } b.w += n }
// copy as much as we can n = copy(p, b.buf[b.r:b.w]) b.r += n b.lastByte = int(b.buf[b.r-1]) b.lastRuneSize = -1 return n, nil }
说明:
reader内部通过维护一个r, w 即读入和写入的位置索引来判断是否缓存区内容被全部读出。
Writer对象
bufio.Writer 是bufio中对io.Writer 的封装
1 2 3 4 5 6 7 8 9 10 11 12
// Writer implements buffering for an io.Writer object. // If an error occurs writing to a Writer, no more data will be // accepted and all subsequent writes, and Flush, will return the error. // After all data has been written, the client should call the // Flush method to guarantee all data has been forwarded to // the underlying io.Writer. type Writer struct { err error buf []byte n int wr io.Writer }
// Write writes the contents of p into the buffer. // It returns the number of bytes written. // If nn < len(p), it also returns an error explaining // why the write is short. func(b *Writer) Write(p []byte) (nn int, err error) { forlen(p) > b.Available() && b.err == nil { var n int if b.Buffered() == 0 { // Large write, empty buffer. // Write directly from p to avoid copy. n, b.err = b.wr.Write(p) } else { n = copy(b.buf[b.n:], p) b.n += n b.Flush() } nn += n p = p[n:] } if b.err != nil { return nn, b.err } n := copy(b.buf[b.n:], p) b.n += n nn += n return nn, nil }