> 文档中心 > go语言基础-文件读写操作

go语言基础-文件读写操作

文章目录

    • 一. 前言
    • 二. 文件操作
      • 1. 创建文件
      • 2. 文件
      • 打开文件
      • 2. 打开文件
        • 2.1 语法:
        • 2.2 文件选项
        • 2.2.1 文件模式
        • 2.2.2 案例
          • 创建一个不存在的文件
          • 创建目录
          • 创建多级目录
        • 2.3 打开文件
        • 2.4、读取文件内容
          • 2.4.1 按字节读取
          • 2.4.2 一次性读取
          • 2.4.3 按行读取
      • 2.5、写内容 到文件
        • 2.5.1、写入字节流
        • 2.5.2 写入字符串
      • 2.5.3 在指定位置处写入内容
      • 2.6 文件的其它操作
        • 2.6.1 判断文件是否存在
        • 2.6.2 删除文件或目录
    • 总结

一. 前言

Go 语言的 os 包,拥有对文件进行操作的一系列方法、函数。
os.Open()函数能够打开一个文件,返回一个*File和一个err。

二. 文件操作

1. 创建文件

创建文件
语法:
os.Create(name string) (file *File, err error)

Create采用模式0644(文件创建者可读写但不可执行,同组以及其他人都只可读,不可写和执行)

创建一个名为name的文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于I/O;对应的文件描述符具有O_RDWR模式。

如果出错,err 不为 nil,错误底层类型是*PathError。

以下为示例代码:

package mainimport ("fmt""os")func CreateFile(filename string) {_, err := os.Create(filename)if err != nil {fmt.Println(err)} else {fmt.Println("create file successfully")}}func main() {CreateFile("mufengNote.txt")}

创建好的文件如图:
在这里插入图片描述
执行结果:
在这里插入图片描述

2. 文件

在这里插入图片描述

打开文件

案例一:按照字节读数据

package mainimport ("fmt""os")func main() {//打开文件var file, err = os.Open("./读取文件")//如果报错if err != nil {fmt.Println(err)}//延迟注册defer file.Close()// 读取文件var data = make([]byte, 3)fmt.Println(data)n, err := file.Read(data)if err != nil {fmt.Println(err)}fmt.Println(n)}

如果出现无法读取文件,在这里修改为相应的路径

go语言基础-文件读写操作

2. 打开文件

2.1 语法:

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

OpenFile是一个更一般性的文件打开函数,大多数调用者都应用Open或Create代替本函数。

它会使用指定的选项(如O_RDONLY等)、指定的模式(如0666等)打开指定名称的文件。

如果操作成功,返回的文件对象可用于I/O。如果出错,err 不为 nil,错误底层类型是*PathError。

2.2 文件选项

注意:不是所有的 flag 都能在特定系统里使用!

const (    O_RDONLY int = syscall.O_RDONLY // 只读模式打开文件    O_WRONLY int = syscall.O_WRONLY // 只写模式打开文件    O_RDWR   int = syscall.O_RDWR   // 读写模式打开文件    O_APPEND int = syscall.O_APPEND // 写操作时将数据附加到文件尾部    O_CREATE int = syscall.O_CREAT  // 如果不存在将创建一个新文件    O_EXCL   int = syscall.O_EXCL   // 和O_CREATE配合使用,文件必须不存在    O_SYNC   int = syscall.O_SYNC   // 打开文件用于同步I/O    O_TRUNC  int = syscall.O_TRUNC  // 如果可能,打开时清空文件)

2.2.1 文件模式

创建文件时,我们可以指定文件的权限,文件权限总共分三种:读(r)、写(w)、执行(x),其中:
读(r):4
写(w):2
执行(x):1

然后一个文件可被拥有者、拥有者所在组里的其他成员、以及除此以外的其他成员读写或执行(在赋予相应的权限的前提下)。

例如 0764 模式,代表:
7,即 rwx 权限,意思就是:文件拥有者可以读写并执行该文件
6. 即 rw- 权限,意思就是:文件拥有者所在的组里的其他成员可对文件进行读写操作
4. 即 r-- 权限,意思就是:除了上面提到的用户,其余用户只能对该文件进行读操作

2.2.2 案例

创建一个不存在的文件

创建一个不存在的文件,并且文件权限设为 rwxr-xr–

package mainimport ("fmt""os")func Openfile(filename string) {_, err := os.OpenFile(filename, os.O_CREATE, 0754)if err != nil {fmt.Println(err)} else {fmt.Println("create file sucessfully")}}func main() {Openfile("mufengNote1.txt")}
创建目录

创建单级目录用到的方法是 Mkdir(name string, perm FileMode) error

package mainimport ("fmt""os")func mkdir(dirname string, perm os.FileMode) {err := os.Mkdir(dirname, perm)if err != nil {fmt.Println(err)}fmt.Println(dirname, "sucessfully")}func main() {mkdir("Note", 0777)}

执行结果

go语言基础-文件读写操作

以上代码只能创建单级目录,想创建多级目录需要用下面的

创建多级目录

创建多级目录用到的方法是 MkdirAll(path string, perm FileMode) error。

权限位 perm 会应用在每一个被本函数创建的目录上。如果 path 指定了一个已经存在的目录,MkdirAll 不做任何操作并返回 nil

package mainimport ("fmt""os")func mkdirD(dirname string, perm os.FileMode) {err := os.MkdirAll(dirname, perm)if err != nil {fmt.Println(err)}fmt.Println(dirname, "made sucessfully")}func main() {mkdirD("Note1/mufeng", 0740)}

执行结果:

go语言基础-文件读写操作

2.3 打开文件

语法一:
os.Open(name string) (file *File, err error)

Open打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件模式是 O_RDONLY 模式。

file, err := os.Open(filename)

语法二:
os.OpenFile(name string, flag int, perm FileMode) (file *File, err error)

2.4、读取文件内容

2.4.1 按字节读取

循环读
读取的时候,要注意一个问题,就是文件有时候可能太大,需要我们循环多次去读取,这个时候需要设置两个“容器”,一个容器用来装每次读的内容,另一个容器用来累积读的所有内容,看下面示例代码:

package mainimport ("fmt""os")func ReadFile(filename string) {file, _ := os.OpenFile(filename, os.O_RDONLY, 0400)var read_buffer = make([]byte, 3)var content_buffer = make([]byte, 0)fileinfo, _ := file.Stat()size := fileinfo.Size()var length int64 = 0for length < size {n, _ := file.Read(read_buffer)content_buffer = append(content_buffer, read_buffer[:n]...)length += int64(n)}fmt.Println(string(content_buffer))}func main() {ReadFile("读取文件")}

执行结果:
在这里插入图片描述

2.4.2 一次性读取

只要获取到了文件大小(以字节为单位),我们也可以一次性读取文件内容:

package mainimport ("fmt""os")func ReadFile2(filename string) {file, _ := os.OpenFile(filename, os.O_RDONLY, 0400)fileinfo, _ := file.Stat()size := fileinfo.Size()//文件大小var read_buffer = make([]byte, size) //直接一步到位var length int64 = 0for length < size {n, _ := file.Read(read_buffer)length += int64(n)}fmt.Println(string(read_buffer))}func main() {ReadFile2("读取文件")}
2.4.3 按行读取

在正式介绍怎么按行读取之前,先简单介绍一下 bufio.NewReader(rd io.Reader) Reader,NewReader创建一个具有默认大小缓冲、从r读取的Reader。

看以下示例代码:

package mainimport ("bufio""fmt""io""os")func ReadFile3(filename string) {file, _ := os.OpenFile(filename, os.O_RDONLY, 0400)reader := bufio.NewReader(file)for i := 1; ; i++ {line, err := reader.ReadString('\n')if err != nil && err != io.EOF {fmt.Println(err)}fmt.Printf("第%d行:%s", i, line)if err == io.EOF {//读到文件结尾就退出break}}}func main() {ReadFile3("读取文件")}

2.4.4、一次性读取全部

一次性全部读取,要用到 io/ioutil 包里的 ReadAll(r io.Reader) ([]byte, error) 方法,ReadAll 从 r 读取数据直到 EOF 或遇到 error,返回读取的数据和遇到的错误。

成功的调用返回的 err 为 nil 而非 EOF。因为本函数定义为读取 r 直到 EOF,它不会将读取返回的 EOF 视为应报告的错误。

看以下示例代码:

package mainimport ("fmt""io/ioutil""os")func ReadFile4(filename string) {file, _ := os.OpenFile(filename, os.O_RDONLY, 0400)data, err := ioutil.ReadAll(file) //data 是一个 []byteif err != nil {return}fmt.Printf("%s", data)}func main() {ReadFile4("读取文件")}

执行以上代码,得到输出如下:

在这里插入图片描述

2.5、写内容 到文件

2.5.1、写入字节流

package mainimport ("fmt""os")func WriteByte(filename string, data []byte) {file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0200)if err != nil {fmt.Println(err)return}n, err := file.Write(data)fmt.Printf("写入了%d的字节", n)file.Close()}func main() {WriteByte("write_txt1", []byte("2022-04-16"))}

执行上述代码,输出结果为:

注意:上述代码中,打开文件的选项有一项 os.O_APPEND,这个很重要,有了这个,写文件是追加写,没有这个,写文件则是覆盖写。

2.5.2 写入字符串

package mainimport ("fmt""os")func WriteString(filename string, data string) {file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0200)if err != nil {fmt.Println(err)}n, err := file.WriteString(data)if err != nil {fmt.Println(err)return}fmt.Printf("写入了%d个字符串", n)file.Close()}func main() {WriteString("write_txt1", "2022-04-16")}

执行上述代码,输出结果为:

写入了9字节的内容

2.5.3 在指定位置处写入内容

package mainimport ("fmt""os")func WriteAt(filename string, data []byte, offset int64) {file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, 0200)if err != nil {fmt.Println(err)}n, err := file.WriteAt(data, offset) //覆盖写if err != nil {fmt.Println(err)}fmt.Printf("写入了%d字节的内容", n)file.Close()}func main() {WriteAt("write_txt1", []byte("wrold,"), int64(8))}

执行上述代码,输出结果为:
写入了7字节的内容

注意:打开文件的 os.O_APPEND 选项与 file.WriteAt 冲突,两个不能同时出现。

2.6 文件的其它操作

2.6.1 判断文件是否存在

判断文件存不存在用到了 os.Stat(filename string) 方法,该方法返回一个 FileInfo 和一个 error,通过 error 和 os.IsNotExist(error) 判断出文件存不存在,
其中 FileInfo 的结构如下所示,通过它,我们能了解到许多有关文件的信息。

type FileInfo interface {Name() string// base name of the fileSize() int64 // length in bytes for regular files; system-dependent for othersMode() FileMode     // file mode bitsModTime() time.Time // modification timeIsDir() bool // abbreviation for Mode().IsDir()Sys() interface{}   // underlying data source (can return nil)}

判断文件存不存在
代码如下所示:

package mainimport ("fmt""os")func IsExist(filename string) {_, err := os.Stat(filename)if err != nil && !os.IsNotExist(err) {fmt.Println(err)return}if os.IsNotExist(err) {fmt.Println(filename, "不存在")} else {fmt.Println(filename, "存在")}}func main() {IsExist("write_txt1")}

执行上述代码,输出结果为:

在这里插入图片描述

2.6.2 删除文件或目录

删除文件或单级目录

os.Remove(name string) 只能删除空目录或文件

package mainimport ("fmt""os")func Remove(name string) {err := os.Remove(name)if err != nil {fmt.Println(err)return}fmt.Println("删除", name, "成功")}func main() {Remove("write_txt1")}

但是你要删除一个目录的话,可能会报错,会提示当前的目录下不为空,这样的是无法删除的,如果你想删除怎么办呢?

删除文件或多级目录

删除多级目录用到的方法是 os.RemoveAll(path string),RemoveAll 删除 path 指定的文件,或目录及它包含的任何下级对象。它会尝试删除所有东西,除非遇到错误并返回。
如果 path 指定的对象不存在,RemoveAll 会返回 nil 而不返回错误。

package mainimport ("fmt""os")func RemoveP(filename string) {err := os.RemoveAll(filename)if err != nil {fmt.Println(err)}fmt.Println("删除", filename, "成功")}func main() {RemoveP("Note1")}

总结

关于文件的增删改查,就写到这里,后面我们再回来追加