学习网站: https://gobyexample.com/reading-files

可以直接读取文件里面的所有内容到内存里面:

data, err := os.ReadFile("/tmp/data")
fmt.Println(string(data))

有时候想要自定义一些操作,比如读取文件里面的某些内容,从某个位置开始读取等,这时候,我们可以用 os.Open 打开一个文件,返回一个 os.File 对象。

f, err := os.Open("/tmp/data")

我们可以定义一个缓存(5个字节的[]byte类型),然后从文件中读取内容,读取的内容大小上限为5:

b1 := make([]byte, 5)
n1, err := f.Read(b1)
fmt.Printf("%d bytes read from file: %s\n", n1, string(b1))

调用 f.Read来读取文件,返回两个结果,第一个为实际读取的内容长度,第二个为error。我们定义了一个长度为5的 b1 来存储文件内容,但是文件里面的内容长度可能只有3,因此,n1不一定等于5,它是实际读取的长度。

同样,我们还能用 os.Seek,来查找文件的位置,第一个参数为 offset,意味着偏移量,第二个参数为 whence

  • 0表示从文件的开始位置进行偏移查找
  • 1表示从文件的当前位置开始偏移,如果之前已经设置过偏移,再次设置则从当前位置开始偏移
  • 2表示从文件的末尾开始偏移
o2, err := f.Seek(6, 0)
b2 := make([]byte, 2)
n2, err := f.Read(b2)
fmt.Printf("%d bytes read at %d\n", n2, o2)
fmt.Printf("Value is : %s\n", string(b2[:n2]))

golang 的 io包提供了一些有用的函数,帮助我们高效读取。比如 io.ReadAtLeast,可以更健壮地实现上的读取操作:

o3, err := f.Seek(6, 0)
b3 := make([]byte, 2)
n3, err := io.ReadAtLeast(f, b3, 2)
fmt.Printf("%d bytes @ %d: %s\n", n3, o3, string(b3))

如果想要将文件指针倒回到最初的位置,没有内置的函数,但是使用 f.Seek(0, 0) 可以实现同样的效果:

_, err := f.Seek(0, 0)

golang的 bufio 包提供了 缓冲读取器,它提供和额外的读取方法,对于少量的读取很有用:

r4 := bufio.NewReader(f)
b4, err := r4.Peek(5)
fmt.Printf("5 bytes: %s\n", string(b4))

最后,我们应该在结束的时候关闭文件:

f.Close()

但是一般来说,我们应该在打开文件之后,使用 defer f.Close() 来进行优雅的关闭文件:

f, err := os.Open("/tmp/data")
defer f.Close()

完整代码:


func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	// ReadFile
	data, err := os.ReadFile("/tmp/data")
	check(err)
	fmt.Printf("data: %s\n", string(data))

	// Open file
	f, err := os.Open("/tmp/data")
	check(err)
	b1 := make([]byte, 5)
	n1, err := f.Read(b1)
	check(err)
	fmt.Printf("%d size of data read: %s\n", n1, string(b1))

	// Seek
	o1, err := f.Seek(6, 0)
	check(err)
	b2 := make([]byte, 2)
	n2, err := f.Read(b2)
	check(err)
	fmt.Printf("%d bytes read @ %d: %s\n", n2, o1, string(b2))

	// io.ReadAtLeast
	o3, err := f.Seek(6, 0)
	b3 := make([]byte, 2)
	n3, err := io.ReadAtLeast(f, b3, 2)
	check(err)
	fmt.Printf("io.ReadAtLeast, %d bytes read @ %d: %s\n", n3, o3, string(b3))

	// rewind
	_, err = f.Seek(0, 0)
	check(err)

	// bufio
	r4 := bufio.NewReader(f)
	b4, err := r4.Peek(5)
	check(err)
	fmt.Printf("5 bytes read from bufio: %s\n", string(b4))

	// close file
	f.Close()
}