第三十一章 文件操作与I/O

作者:李骁

31.1 文件系统

对于文件和目录的操作,Go主要在os包中提供了的相应方法:

func Mkdir(name string, perm FileMode) error 
func Chdir(dir string) error
func TempDir() string
func Rename(oldpath, newpath string) error
func Chmod(name string, mode FileMode) error
func Open(name string) (*File, error) {
    return OpenFile(name, O_RDONLY, 0)
}
func Create(name string) (*File, error) {
    return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
func OpenFile(name string, flag int, perm FileMode) (*File, error) {
    testlog.Open(name)
    return openFileNolog(name, flag, perm)
}

从上面函数定义中我们可以发现一个情况:那就是os包中不同函数打开(创建)文件的操作,最终还是通过函数OpenFile()来实现,而OpenFile()由编译器根据系统的情况来选择不同的底层功能来实现,对这个实现细节有兴趣可以根据标准包来仔细了解,这里就不展开讲了。

预定义的Flag值:

在ioutil包中,也可以对文件操作,主要有下面三个函数:

这三个函数涉及到了文件I/O ,而对文件的操作我们除了打开(创建),关闭外,更主要的是对内容的读写操作上,也即是文件I/O处理上。在Go语言中,对于I/O的操作在Go 语言很多标准库中存在,很难完整地讲清楚。下面我就尝试结合io, ioutil, bufio这三个标准库,讲一讲这几个标准库在文件I/O操作中的具体使用方法。

31.2 I/O读写

Go 语言中,为了方便开发者使用,将 I/O 操作封装在了大概如下几个包中:

  • io 为 I/O 原语(I/O primitives)提供基本的接口

  • io/ioutil 封装一些实用的 I/O 函数

  • fmt 实现格式化 I/O,类似 C 语言中的 printf 和 scanf ,后面会详细讲解

  • bufio 实现带缓冲I/O

在 io 包中最重要的是两个接口:Reader 和 Writer 接口。

这两个接口是我们了解整个I/O的关键,我们只要记住:实现了这两个接口,就有了 I/O 的功能

有关缓冲:

  • 内核中的缓冲:无论进程是否提供缓冲,内核都是提供缓冲的,系统对磁盘的读写都会提供一个缓冲(内核高速缓冲),将数据写入到块缓冲进行排队,当块缓冲达到一定的量时,才把数据写入磁盘。

  • 进程中的缓冲:是指对输入输出流进行了改进,提供了一个流缓冲,当调用一个函数向磁盘写数据时,先把数据写入缓冲区,当达到某个条件,如流缓冲满了,或刷新流缓冲,这时候才会把数据一次送往内核提供的块缓冲中,再经块缓冲写入磁盘。

Go 语言提供了很多读写文件的方式,一般来说常用的有三种。 一:os.File 实现了Reader 和 Writer 接口,所以在文件对象上,我们可以直接读写文件。

在使用File.Read读文件时,可考虑使用buffer:

二:ioutil库,没有直接实现Reader 和 Writer 接口,但是通过内部调用,也可读写文件内容:

三:使用bufio库,这个库实现了I/O的缓冲操作,通过内嵌io.Reader、io.Writer接口,新建了Reader ,Writer 结构体。同时也实现了Reader 和 Writer 接口。

这三种读方式的效率怎么样呢,我们可以看看:

经过多次测试,基本上保持 file.Read > ioutil >bufio 这样的成绩, bufio读同一文件耗费时间最少,效果稳稳地保持在最佳。

31.3 ioutil包

下面代码使用ioutil包实现2种读文件,1种写文件的方法,其中 ioutil.ReadAll 可以读取所有io.Reader流。所以在网络连接中,也经常使用ioutil.ReadAll来读取流,后面章节我们会讲到这块内容。

31.4 bufio包

bufio 包通过 bufio.NewReader 和bufio.NewWriter 来创建I/O方法集,利用缓冲来处理流,后面章节我们也会讲到这块内容。

bufio包中,主要方法如下:

下面一段代码是,里面有用到peek,Discard 等方法,可以修改方法参数值,仔细体会:

有关I/O 的处理,这里主要讲了针对文件的处理。后面在网络I/O读写处理中,我们将会接触到更多的方式和方法。

目录

第三十章 OS包

第三十二章 fmt包与日志log包

本书《Go语言四十二章经》内容在github上同步地址:https://github.com/ffhelicopter/Go42

虽然本书中例子都经过实际运行,但难免出现错误和不足之处,烦请您指出;如有建议也欢迎交流。 联系邮箱:[email protected]

Last updated

Was this helpful?