go语言——输入流Reader
与输出流Writer
1. 输入流Reader
Reader
即输入流,那么什么又是流? 流(stream)是应用程序和外部资源进行数据交互的纽带;- 流又分为输入流和输出流;这里的输入和输出都是相对于应用程序而言的,把外部资源输入到应用程序称之为输入流,反之为输出流;
- 输入流即Input Stream,输出流即Output Stream,二者合称为I/O流;
- go语言中标准库的io包下
Reader
接口表示输入流,只要实现这个接口就属于输入流,Reader
从字面意思来看是读者,也就是负责将外部资源(类比成纸上的知识)输入到应用程序(类比成把纸上的知识输入到脑中); - Reader接口源码:
type Reader interface {
Read(p []byte) (n int, err error)
}
- Read方法要读取的是字节类型的切片,所以需要将数据转化为字节切片,可以使用
make()
方法;切片长度可以从字符串流或者文件对象的属性中获取到;
package main
import (
"fmt"
"os"
"strings"
)
func main() {
createStrStream()
fmt.Println("=============================================")
readFromFile()
}
func createStrStream() {
// 使用strings包下的NewReader创建字符串流
r := strings.NewReader("Hello World! 你好,世界!")//创建一个从s读取数据的Reader。本函数类似bytes.NewBufferString,但是更有效率且为只读。
b := make([]byte, r.Size()) // 创建字节切片,存放流中数据,根据流数据大小创建切片大小;
n, err := r.Read(b)//Read返回r的数据长度
if err != nil {
fmt.Println("流数据读取失败!", err)
return
}
fmt.Println("读取的数据长度是: ", n) // 读取的数据长度是: 27
fmt.Println("数据内容: ", string(b)) // 以字符串形式显示切片中的数据 // 数据内容: Hello World! 你好,世界!
}
// 从文件中读取数据,新建一个测试文件,goReader.txt
func readFromFile() {
f, _ := os.Open("goReader.txt")
fileInfo, _ := f.Stat()//Stat返回描述文件f的FileInfo类型值。如果出错,错误底层类型是*PathError
b := make([]byte, fileInfo.Size())
n, err := f.Read(b)//Read返回b的数据长度
if err != nil {
fmt.Println("数据读取失败, ", err)
return
}
fmt.Println("数据长度是: ", n) // 数据长度是: 133
fmt.Println("数据内容是: \n", string(b))
/*
数据内容是:
1.这里是测试go语言的Reader的文本
2.这里是测试go语言的Reader的文本
3.这里是测试go语言的Reader的文本
*/
}
控制台输出:
读取的数据长度是: 27
数据内容: Hello World! 你好,世界!
=============================================
数据长度是: 133
数据内容是:
1.这里是测试go语言的Reader的文本
2.这里是测试go语言的Reader的文本
3.这里是测试go语言的Reader的文本
2. 输出流Writer
- 输出流(Output Stream)就是将应用程序中的数据写出到外部资源;
- go语言中
io
包下的Writer
接口表示输出流,只要实现这个接口就属于输出流,reader
从字面意思来看是写者,也就是负责将应用程序(类比成脑中的想法)输出到外部资源(类比成把脑中的想法输出在纸上); Writer
的源码:
type Writer interface {
Write(p []byte) (n int, err error)
}
- 注意构建字节切片的时候如果需要读取文件,不要使用
os.Open()
,因为这种方式获取的文件是只读的,无法写入;需要使用os.OpenFile()
; os.OpenFile(name string, flag int, perm FileMode)
的参数:name
:文件名,flag
:操作方式,perm
:文件权限;- 其中
perm
参数:共4位,第一位总为0,第二位表示是否可读,第3位表示是否可写;第4位表示是否可执行; 例如:0000 不可读写 不可执行; 0001 不可读写 可执行; 0010 可写不可读,不可执行; 0100 可读不可写,不可执行;由于是二进制表示,所以可以将其转化为10进制的数值,比如0100可以转化为4, 0111为7,0110为6;也可以记作: 4读2写1执行; 最多不大于7,在表示权限的时候可以使用8进制,来区分用户/用户组/其他用户的分别权限;比如0764表示文件所属用户可读可写可执行,用户组其他用户仅可读可写,其他非用户组用户仅可读; - 写入文件中的特殊字符,
\r\n
换行,\t
制表符。
以下代码涉及到的函数/方法(均属os
包下):
函数名 | 功能 |
---|---|
func OpenFile(name string, flag int, perm FileMode) (file *File, err error) |
读取文件,读取的文件可以写入。 |
func Create(name string) (file *File, err error) |
创建一个名为name 的文件。 |
func (f *File) Write(b []byte) (n int, err error) |
Write 向文件中写入len(b) 字节数据。 |
func (f *File) WriteString(s string) (ret int, err error) |
WriteString 类似Write ,但接受一个字符串参数。 |
package main
import (
"fmt"
"os"
)
func main() {
goWriter()
}
func goWriter() {
f, err := os.OpenFile("goWriter.txt", os.O_APPEND, 0764)
defer f.Close() // 记得打开流之后要关闭流
if err != nil {
fmt.Println("文件不存在,正在创建文件")
f, _ = os.Create("goWriter.txt")
}
fmt.Println("文件打开成功")
f.Write([]byte("要写入的内容1\r\n要写入的内容2\r\n\t要写入的内容3\r\n"))
f.WriteString("这一行是使用`f.WriteString()`写入的\r\n")
}
在原本没有goWriter.txt
文件的情况下,根目录下生成了此文件,并在此文件输出了内容,实现了将应用程序中的数据写出到外部资源这一目的。
控制台输出:
文件不存在,正在创建文件
文件打开成功
goWriter.txt
文件内容: