一架梯子,一头程序猿,仰望星空!

golang 文件读写


本章介绍go语言中如何进行文件读写。

在go语言中文件读写相关的包有:

  • io/ioutil - 提供常用的io函数,例如:便捷的文件读写。
  • os - 系统相关的函数,我这里主要用到跟文件相关的函数,例如,打开文件。
  • path/filepath - 用处理文件路径

1.读文件

通过io/ioutil包的ReadFile函数,可以一次读取一个文件的内容。

函数定义:

func ReadFile(filename string) ([]byte, error)

ReadFile 从filename指定的文件中读取数据并返回文件的内容。成功的调用返回的err为nil而非EOF。因为本函数定义为读取整个文件,它不会将读取返回的EOF视为应报告的错误。

例子:

package main

import (
	"fmt"
	"io/ioutil"
)

func main() {
	content, err := ioutil.ReadFile("./readme.txt")
	if err != nil {
		// 读取文件失败
		panic(err)
	}
	
	fmt.Println(string(content))
}

2.写文件

通过io/ioutil包的WriteFile函数,可以将内容保存到文件中。

函数定义:

func WriteFile(filename string, data []byte, perm os.FileMode) error

函数向filename指定的文件中写入数据。如果文件不存在将按给出的权限创建文件,否则在写入数据之前清空文件。

例子:

package main

import (
	"io/ioutil"
)

func main() {
	content := "这里是文件的内容。"
	// 因为WriteFile函数接受的文件内容是字节数组,所以需要将content转换成字节数组
	// 0666是指文件的权限是具有读写权限,具体可以参考linux文件权限相关内容。
	err := ioutil.WriteFile("./demo.txt", []byte(content), 0666)
	
	if err != nil {
		panic(err)
	}
}

3.检测文件是否存在

package main

import (
	"fmt"
	"os"
)

func main() {
	_, err := os.Stat("./demo.txt")
	if err != nil {
		if os.IsNotExist(err) {
			fmt.Println("文件不存在")
			return
		}

		if os.IsPermission(err) {
			fmt.Println("没有权限对文件进行操作。")
			return
		}
		
		fmt.Println("其他错误。")
		return
	}

	// err == nil 则表示文件存在
	fmt.Println("文件存在")
}

4.文件路径操作

4.1.获取文件扩展名

package main

import (
	"fmt"
	"path/filepath"
)

func main() {
	ext := filepath.Ext("/images/logo.jpg")
	fmt.Println(ext)
}

输出:

.jpg

4.2.获取文件名

package main

import (
	"fmt"
	"path/filepath"
)

func main() {
	// 获取文件名字
	filename := filepath.Base("/images/logo.jpg")
	fmt.Println(filename)
	
	// 获取目录
	dir := filepath.Dir("/images/logo.jpg")
	fmt.Println(dir)
}

5.读写文件的高级用法

前面介绍的文件读写,是一次性完成文件的读写操作,比较方便,但是对于大文件的读写的性能优化和文件读写的细节控制就做不到了。

例子:

package main

import "os"

func main() {
	// 使用OpenFile打开文件, 并且设置文件内容以追加的形式添加到文件尾部
	f, err := os.OpenFile("./demo.txt", os.O_CREATE | os.O_APPEND |os.O_WRONLY, 0666)
	if err != nil {
		panic(err)
	}

	// 延迟关闭文件
	defer f.Close()

	// 写入文件内容
	f.WriteString("内容1")
	f.WriteString("内容2")
	f.WriteString("内容3")

}

5.1. OpenFile函数定义

func OpenFile(name string, flag int, perm FileMode) (file *File, err error)

参数说明:

  • name - 文件路径
  • flag - 文件打开模式,后面专门介绍
  • perm - 文件权限模式,例如: 0666 代表当前用户拥有读写权限

常用的文件打开模式:

  • O_CREATE - 如果文件不存在,则创建一个
  • O_APPEND - 写入文件的内容,自动追加到文件的尾部。
  • O_RDONLY - 打开一个只读的文件
  • O_WRONLY - 打开一个只写的文件
  • O_RDWR - 打开一个可以读写的文件

提示:上面这些文件打开模式标签是可以自由组合的。

例子:

// 打开一个只读的文件,并且写入内容自动追加到文件尾部,如果文件不存在则自动创建一个新的
f, err := os.OpenFile("./demo.txt", os.O_CREATE | os.O_APPEND |os.O_WRONLY, 0666)

5.2. File对象常用函数

OpenFile函数创建一个文件后返回的是File对象,下面是File对象常用的函数:

1.Read

func (f *File) Read(b []byte) (n int, err error)

Read方法从f中读取最多len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。文件终止标志是读取0个字节且返回值err为io.EOF。

2.ReadAt

func (f *File) ReadAt(b []byte, off int64) (n int, err error)

ReadAt从指定的位置(相对于文件开始位置)读取len(b)字节数据并写入b。它返回读取的字节数和可能遇到的任何错误。当n<len(b)时,本方法总是会返回错误;如果是因为到达文件结尾,返回值err会是io.EOF。

3.Write

func (f *File) Write(b []byte) (n int, err error)

Write向文件中写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。

4.WriteString

func (f *File) WriteString(s string) (ret int, err error)

WriteString类似Write,但接受一个字符串参数。

5.WriteAt

func (f *File) WriteAt(b []byte, off int64) (n int, err error)

WriteAt在指定的位置(相对于文件开始位置)写入len(b)字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值n!=len(b),本方法会返回一个非nil的错误。

6.Seek

func (f *File) Seek(offset int64, whence int) (ret int64, err error)

Seek设置下一次读/写的位置。offset为相对偏移量,而whence决定相对位置:0为相对文件开头,1为相对当前位置,2为相对文件结尾。它返回新的偏移量(相对开头)和可能的错误。

6.Close

func (f *File) Close() error

Close关闭文件f,使文件不能用于读写。它返回可能出现的错误。