读文件

一次性读取整个文件

一次性读取整个文件是一种比较简单的文件读取方式。我们可以通过ioutil包中的ReadFile来读取整个文件。

我们在Golang工作目录下创建一个工程目录filehandling。然后在该工程目录下再创建一个文本文件test.txt。在该文件中输入如下文本:

Hello World. Welcome to file handling in Go.

然后创建Golang程序文件filehandling.go,并输入如下代码:

package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    data, err := ioutil.ReadFile("test.txt")
    if err != nil {
        fmt.Println("File reading error", err)
        return
    }
    fmt.Println("Contents of file:", string(data))
}

此时的文件目录为:

前面程序中我们通过ioutil.ReadFile("test.txt")来读取了整个文件的内容,该函数返回的数据格式为字节切片。因此这里的data数据类型为字节切片,我们通过string(data)将字节切片转成了字符串然后再打印。该程序执行结果如下:

注意,这里我们使用的是相对目录test.txt,因此需要先切换到test.txt所在的目录,然后再执行程序,可通过如下两种方式来执行。

如果不切换到test.txt文件所在目录,那么执行会报错:

之所以会报错是因为Golang是一种编译型语言,Golang程序在执行前会先编译成二进制程序,而我们在程序中已经写死了文件目录test.txt,即二进制程序在什么目录下执行,就在哪个目录下寻找test.txt,因此如果我们不在filehandling目录下执行,则会找不到test.txt文件,就会报错。我们有三种方式能解决这个问题:

  1. 使用绝对路径

  2. 文件路径通过命令行参数动态传入

  3. 将文本文件编译到二进制程序内

这里就不细讲了,感兴趣的同学可以google下。

按字节读取

前面我们看了怎么读取整个文件,但是对于过大的文件,一次性读取到内存则不太现实。更加合理的方式是一小块一小块的读取。我们可以借助buffo包来实现。

下面我们按每3个字节一块来读取前面的test.txt文件。

这里我们从命令行中解析出了文件目录。我们defer了一个函数用来在文件读取结束后关闭文件。通过make([]byte, 3)创建了长度为3的字节切片,然后通过r.Read(b)不断的讲文件内容读入到b中。Read方法读取最多len(b)个字节,并返回真实读取到的字节数,读取到文件结尾后会返回一个EOF错误。

可通过如下方式执行该程序:

执行结果如下:

按行读取

下面我们看下如何按行读取文件。仍然是借助bufio实现。现在将test.txt中的文本换成如下内容。

按行读取的流程如下:

  1. 打开文件

  2. 创建一个scanner

  3. 按行读取

这里通过os.Open(*fptr)打开了文件,然后通过bufio.NewScanner(f)创建了一个scanner,然后通过s.Scan()s.Text()按行读取了文件内容。s.Err()用来判断读取文件过程中是否发生了错误。该程序执行结果如下:

Last updated

Was this helpful?