任何类型,只要实现了 Reader接口的 Read 方法,那么他就是一个Reader 类型。
Writer 同样如此
还有 ReadCloser 和 ReadWriter
type Reader interface {
Read(p []byte) (n int, err error) // 将 len(p) 个字节读取到 p 数组里。返回读取的字节数。
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 写入并关闭
type WriteCloser interface {
Writer
Closer
}
一些快速创建Reader的方法:
// 从字符串创建一个Reader
r := strings.NewReader("some io.Reader stream to be read\n")
lr := io.LimitReader(r, 4)
// 从一个字节数组创建一个Reader => NewReader returns a new Reader reading from b.
b = []byte("abc")
bytes.NewReader(b)
// os.Stdout 本书就是一个Writer
if _, err := io.Copy(os.Stdout, r); err != nil {
log.Fatal(err)
}
N种方式实现读取文件内容
func main() {
osReadFile()
// ioutil.ReadFile 就等价于 os.ReadFile,二者是完全一致的
// ioutil直接一次性读取
ioutilReadFile()
// 先打开文件,再用 ioutil 一次性读取
ioutilReadAll()
// 一行一行读取
readLines()
// 也是一次读取一行,不过通过 ReadString 返回的是字符串
bufioReadString()
//每次只读取固定字节数
readFixedSizeBytes()
}
func readLines() {
fmt.Println("一次读取一行(从缓冲区): ")
file, err := os.Open(filename)
if err != nil {
panic(err)
}
rb := bufio.NewReader(file) // 多了个缓冲区,磁盘读取次数减少
for {
lineBytes, err := rb.ReadBytes('\n') // 每次读取到换行,也就是每次读取一行
if err != nil && err != io.EOF {
panic(err)
}
if err == io.EOF { // 到文件结束停止
break
}
fmt.Printf("Line: %s", lineBytes) // 字符串里已经有换行符,这里不要加换行符
}
}
func ioutilReadAll() {
fmt.Println("ioutil 一次性全部读取:")
fh, err := os.Open(filename)
if err != nil {
panic(err)
}
// fh 类型为 File, File 实现了Reader 接口
content3, err := ioutil.ReadAll(fh)
if err != nil {
panic(err)
}
println(string(content3))
}
func osReadFile() {
fmt.Println("一次性读取文件内容:对于小文件很方便,但大文件不适用")
content, err := os.ReadFile(filename)
if err != nil {
panic(err)
}
fmt.Printf("%s\n", content)
}
func ioutilReadFile() {
fmt.Println("ioutil.ReadFile 与 os.ReadFile 底层实现是一样的")
content2, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
fmt.Printf("ioutil.ReadFile: %s\n", content2)
}
func readFixedSizeBytes() {
fmt.Println("一次性读取固定字节的数据(1024): ")
file, err := os.Open(filename)
if err != nil {
panic(err)
}
r := bufio.NewReader(file)
// 每次读取 1024 个字节
buf := make([]byte, 1024)
for {
n, err := r.Read(buf)
if err != nil && err != io.EOF {
panic(err)
}
if n == 0 {
break
}
fmt.Println("fixed bytes: ", string(buf[:n]))
}
}
func bufioReadString() {
fmt.Println("也是一次读取一行,不过通过 ReadString 返回的是字符串 ")
file, err := os.Open(filename)
if err != nil {
panic(err)
}
r := bufio.NewReader(file)
for {
line, err := r.ReadString('\n')
line = strings.TrimSpace(line)
if err != nil && err != io.EOF {
panic(err)
}
if err == io.EOF {
break
}
fmt.Println("bufio.line: ", line)
}
}