当前位置: 首页 > news >正文

【Golang笔记04】Go语言中文件操作的学习笔记

Golang笔记04:文件操作学习笔记

一、文件操作

Go语言中,文件操作的标准类库有很多,例如:osio等包都可以用于操作文件。

1.1、打开文件

Go语言中,可以使用os包中提供的Open()函数来打开文件,另外,还可以使用OpenFile()函数来打开文件。

1.1.1、Open()函数
  • Open(name string)函数:打开指定文件,返回值一个File文件指针,以及err错误。
package mainimport ("fmt""os"
)func main() {// 打开文件file, err := os.Open("demo.txt")if err != nil {fmt.Println("文件打开失败:", err)return}fmt.Println(file.Name())
}

需要注意的一点是,Open()函数打开的文件如果不存在,那么就会返回err信息,提示打开文件失败的信息。

Open()函数中,如果没有指定具体路径,那么Go默认会从当前程序文件所在目录下,去寻找指定的文件。Open()函数底层实际上还是基于OpenFile()函数实现的,只不过是采用只读的模式打开文件。

1.1.2、OpenFile()函数
  • OpenFile(name string,flag int,perm FileMode)函数:采用指定模式,打开文件,返回值一个File文件指针,以及err错误。

flag参数是用于设置文件打开模式的,例如:只读可读可写等模式。flag参数值可以从os包中的常量值获取,如下所示:

os.O_RDONLY:只读模式。
os.O_WRONLY:只写模式。
os.O_RDWR:读写模式。
os.O_APPEND:写入时将数据追加到文件末尾。
os.O_CREATE:如果文件不存在,创建一个新文件。
os.O_TRUNC:如果文件已存在,将其长度截断为 0。
os.O_EXCL:与 os.O_CREATE 一起使用,如果文件已存在,则返回错误。// Flags to OpenFile wrapping those of the underlying system. Not all
// flags may be implemented on a given system.
const (// 只读模式// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.O_RDONLY int = syscall.O_RDONLY // open the file read-only.// 只写模式O_WRONLY int = syscall.O_WRONLY // open the file write-only.// 可读可写模式O_RDWR   int = syscall.O_RDWR   // open the file read-write.// 追加写入模式// The remaining values may be or'ed in to control behavior.O_APPEND int = syscall.O_APPEND // append data to the file when writing.// 文件不存在,则会创建文件O_CREATE int = syscall.O_CREAT  // create a new file if none exists.O_EXCL   int = syscall.O_EXCL   // used with O_CREATE, file must not exist.O_SYNC   int = syscall.O_SYNC   // open for synchronous I/O.O_TRUNC  int = syscall.O_TRUNC  // truncate regular writable file when opened.
)

FileMode是用于设置文件权限的,例如:文件的读、写、执行权限等;这个参数接收一个八进制数字,例如:

0400:文件所有者具有读权限。
0200:文件所有者具有写权限。
0100:文件所有者具有执行权限。
0040:所属组具有读权限。
0020:所属组具有写权限。
0010:所属组具有执行权限。
0004:其他用户具有读权限。
0002:其他用户具有写权限。
0001:其他用户具有执行权限。
0666:所有用户都有读写权限,但没有执行权限。
0755:文件所有者有读写执行权限,所属组和其他用户有读执行权限。
0644:文件所有者有读写权限,所属组和其他用户有读权限。const (// The single letters are the abbreviations// used by the String method's formatting.ModeDir        FileMode = 1 << (32 - 1 - iota) // d: is a directoryModeAppend                                     // a: append-onlyModeExclusive                                  // l: exclusive useModeTemporary                                  // T: temporary file; Plan 9 onlyModeSymlink                                    // L: symbolic linkModeDevice                                     // D: device fileModeNamedPipe                                  // p: named pipe (FIFO)ModeSocket                                     // S: Unix domain socketModeSetuid                                     // u: setuidModeSetgid                                     // g: setgidModeCharDevice                                 // c: Unix character device, when ModeDevice is setModeSticky                                     // t: stickyModeIrregular                                  // ?: non-regular file; nothing else is known about this file// Mask for the type bits. For regular files, none will be set.ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice | ModeCharDevice | ModeIrregularModePerm FileMode = 0777 // Unix permission bits
)

案例代码:

package mainimport ("fmt""os"
)func main() {// 打开文件file, err := os.OpenFile("demo.txt", os.O_RDWR, 0666)if err != nil {fmt.Println("文件打开失败:", err)return}fmt.Println(file.Name())
}
1.1.3、Lstat()函数

如果只是单纯的想要获取文件的一些信息,而不需要打开文件,那么可以使用os包提供的Lstat()函数。通过这个函数可以获取下面这些信息内容:

type FileInfo interface {// 文件名称Name() string       // base name of the file// 文件大小,单位字节Size() int64        // length in bytes for regular files; system-dependent for others// 文件模式Mode() FileMode     // file mode bits// 文件修改时间ModTime() time.Time // modification time// 文件模式是否为一个目录,其实就是判断当前是不是目录IsDir() bool        // abbreviation for Mode().IsDir()// Sys() any           // underlying data source (can return nil)
}

案例代码:

package mainimport ("fmt""os"
)func main() {// 获取文件信息fileInfo, err := os.Lstat("demo.txt")if err != nil {panic(err)}fmt.Printf("%v\n", fileInfo)// 文件名称filename := fileInfo.Name()fmt.Println("文件名称:", filename)// 文件大小sizes := fileInfo.Size()fmt.Println("文件大小:", sizes)// 文件模式fileMode := fileInfo.Mode()fmt.Println("文件模式:", fileMode)// 文件最后修改时间modTime := fileInfo.ModTime()fmt.Println("修改时间:", modTime)// 是否目录dir := fileInfo.IsDir()fmt.Println("是否目录:", dir)// 基础信息sysInfo := fileInfo.Sys()fmt.Println("基础信息:", sysInfo)
}// 执行结果
&{demo.txt 32 {956629883 31181961} {1301374767 31181966} {1301374767 31181966} 0 11 0 0 {{} {0 0}} D:\environment\GoWorks\src\go-study\demo.txt 0 0 0 false}
文件名称: demo.txt
文件大小: 11
文件模式: -rw-rw-rw-
修改时间: 2025-05-24 17:29:09.6358703 +0800 CST
是否目录: false
基础信息: &{32 {956629883 31181961} {1301374767 31181966} {1301374767 31181966} 0 11}
1.1.4、close()函数

打开文件之后,如果不需要使用文件了,那么在最后需要将文件关闭,可以调用os.close()函数关闭文件。

关闭文件的目的是为了让其他的人可以访问这个文件,因为如果打开文件,而没有关闭文件,那么此时其他的人就没办法操作这个文件,因为这个文件正在被使用中。

package mainimport ("fmt""os"
)func main() {// 打开文件file, err := os.Open("demo.txt")if err != nil {panic(err)}// 关闭文件defer func(file *os.File) {err := file.Close()if err != nil {fmt.Println("文件关闭失败", err)panic("文件关闭失败")}}(file)fmt.Println("文件名称:", file.Name())
}

之前有学习了defer延迟函数,所以,一般是在文件不需要使用之后,可以在defer延迟函数里面调用os.close()关闭文件。

1.2、读取文件内容

当我们打开文件之后,就可以读取文件里面的内容啦。Go语言中,打开文件的时候会返回一个File文件指针,通过这个文件指针就可以读取文件里面的存储的内容。

1.2.1、Read读取文件

File文件指针中提供了两个方法,分别是:Read(b []byte)ReadAt(b []byte, off int64)两个方法。

  • Read()方法的作用是:读取文件的内容,存储到字节切片里面。
  • ReadAt()方法的作用是:从文件指定位置开始读取数据,并且将读取的数据存储到字节切片里面。

注意:两个方法的返回值都是int类型,表示从文件中实际读取的字节数。

如何将文件中的内容都读取出来呢???

要想读取整个文件的内容,需要通过循环的方式来实现,假设:文件总大小是4096字节,每次读取1024字节,那么则需要循环读取4次才可以读取完成。案例代码:

package mainimport ("errors""fmt""io""os"
)// ReadFile 读取文件数据
func ReadFile(f *os.File) ([]byte, error) {// 分配字节切片buffer := make([]byte, 0, 512)// 循环读取数据(死循环)for {// 容量不足时候,需要扩容if len(buffer) == cap(buffer) {buffer = append(buffer, 0)[:len(buffer)]}// 读取的数据,存储到 实际位置->最大容量位置 之间的位置offset, err := f.Read(buffer[len(buffer):cap(buffer)])// 将已经读取的数据写入到字节切片里面buffer = buffer[:len(buffer)+offset]if err != nil {if errors.Is(err, io.EOF) {err = nil}// 返回数据,结束死循环return buffer, err}}
}func main() {// 打开文件file, err := os.Open("demo.txt")if err != nil {panic(err)}// 关闭文件defer func(file *os.File) {err := file.Close()if err != nil {fmt.Println("文件关闭失败", err)panic("文件关闭失败")}}(file)// 读取文件内容bytes, err := ReadFile(file)if err != nil {panic("文件读取失败:" + err.Error())}fmt.Println("文件内容:")fmt.Println(string(bytes))
}
1.2.2、os.ReadFile()方法

上面案例中,我们自己通过for循环,实现了一个读取文件内容的ReadFile函数,里面的代码看着有点多,Go语言中其实已经给我们封装了ReadFile中的代码,在os包下面。

os包下面,提供了一个ReadFile()方法,使用这个方法只需要指定文件名称,就可以将文件内容读取到字节切片里面,返回值是字节切片,最后将字节切片转换成字符串即可。

package mainimport ("fmt""os"
)func main() {// 读取文件bytes, err := os.ReadFile("demo.txt")if err != nil {panic("文件读取失败:" + err.Error())}fmt.Println("文件内容:")fmt.Println(string(bytes))
}
1.2.3、io.ReadAll()方法

除了os.ReadFile()方法,还有另外一个方法也可以读取文件中的内容,那就是io包中提供的ReadAll()方法。这个方法可以读取文件中的所有内容,返回一个字节切片,将其转换字符串即可。

package mainimport ("fmt""io""os"
)func main() {// 打开文件file, err := os.OpenFile("demo.txt", os.O_RDWR, 0666)if err != nil {panic("文件打开失败:" + err.Error())}// 读取文件bytes, err := io.ReadAll(file)if err != nil {panic("文件读取失败:" + err.Error())}fmt.Println("文件内容:")fmt.Println(string(bytes))
}

以上,就是读取文件内容的三种方式。

1.3、写入文件内容

os包中提供了写入数据到文件中的方法,分别是Write()WriteString()WriteAt()方法。

1.3.1、Write()方法
  • Write(b []byte)方法:将字节切片内容写入到File文件里面,返回值有一个int类型,表示实际写入的字节数。
package mainimport ("fmt""os"
)func main() {// 打开文件file, err := os.OpenFile("demo.txt", os.O_RDWR, 0666)if err != nil {panic("文件打开失败:" + err.Error())}// 写入数据count, err := file.Write([]byte("hello World!!!"))if err != nil {panic("文件读取失败:" + err.Error())}fmt.Println("实际写入内容字节数:", count)
}
1.3.2、WriteString()方法
  • WriteString()方法:可以直接将一个字符串内容,写入到File文件里面,返回值有一个int类型,表示实际写入的字节数。
package mainimport ("fmt""os"
)func main() {// 打开文件file, err := os.OpenFile("demo.txt", os.O_RDWR, 0666)if err != nil {panic("文件打开失败:" + err.Error())}// 写入数据count, err := file.WriteString("hello World!!!")if err != nil {panic("文件读取失败:" + err.Error())}fmt.Println("实际写入内容字节数:", count)
}
1.3.3、WriteAt()方法
  • WriteAt(b byte[], off int64)方法:在文件指定位置,开始写入字节切片内容,返回值有一个int类型,表示实际写入的字节数。
package mainimport ("fmt""os"
)func main() {// 打开文件file, err := os.OpenFile("demo.txt", os.O_RDWR, 0666)if err != nil {panic("文件打开失败:" + err.Error())}// 写入数据count, err := file.WriteAt([]byte("666"), 4)if err != nil {panic("文件读取失败:" + err.Error())}fmt.Println("实际写入内容字节数:", count)
}

需要注意的是,这个方法会将指定位置之后的内容,覆盖写入新的字节切片内容。

1.4、复制文件

Go语言中也提供了两个复制文件的方法,一个是os包提供的ReadFrom()方法,另一个是io包提供的Copy()方法。

1.4.1、ReadFrom()方法
  • ReadFrom(r io.Reader)方法:os.File文件指针提供的一个方法,这个方法的作用就是从源文件读取内容到目标文件里面。这个方法会返回一个int类型,表示实际复制的字节数。
package mainimport ("fmt""os"
)func main() {// 打开文件1file, err := os.OpenFile("demo.txt", os.O_RDWR, 0666)if err != nil {panic("文件1打开失败:" + err.Error())}// 打开文件2file2, err2 := os.OpenFile("demo2.txt", os.O_RDWR|os.O_CREATE, 0666)if err2 != nil {panic("文件2打开失败:" + err2.Error())}// 复制文件offset, err3 := file2.ReadFrom(file)if err3 != nil {panic("文件复制失败:" + err3.Error())}fmt.Println("实际字节数:", offset)
}
1.4.2、io.Copy()方法

另外,io包也提供了一个Copy()方法,这个方法也可以实现文件复制的功能。

  • Copy(dst Writer,src Reader)方法:复制文件,返回一个int类型的written参数,表示实际写入的字节数。
package mainimport ("fmt""io""os"
)func main() {// 打开文件1file, err := os.OpenFile("demo.txt", os.O_RDWR, 0666)if err != nil {panic("文件1打开失败:" + err.Error())}// 打开文件2file2, err2 := os.OpenFile("demo2.txt", os.O_RDWR|os.O_CREATE, 0666)if err2 != nil {panic("文件2打开失败:" + err2.Error())}// 复制文件written, err3 := io.Copy(file2, file)if err3 != nil {panic("文件复制失败:" + err3.Error())}fmt.Println("实际写入字节数:", written)
}

需要注意的一点,Copy()方法也可以适用于目录的复制。

1.5、文件重命名

os包下还提供了一个Rename()函数,这个函数的作用是移动或重命名文件、目录。

  • Rename(oldpath,newpath string)函数:重命名或移动目录、文件。
package mainimport ("fmt""os"
)func main() {// 移动、重命名文件err := os.Rename("demo.txt", "demo-rename.txt")if err != nil {panic("文件移动、重命名失败")}fmt.Println("文件移动成功")
}

1.6、删除文件

os包下也提供了两个删除文件、目录的函数,分别是:Remove()RemoveAll()函数。

1.6.1、Remove()函数
  • Remove(name string)函数:删除单个文件、单个目录,如果目录下存在其他文件或目录,则会删除失败。
package mainimport ("fmt""os"
)func main() {// 删除文件err := os.Remove("demo2.txt")if err != nil {panic("文件删除失败")}fmt.Println("文件删除成功")
}
1.6.2、RemoveAll()函数
  • RemoveAll(path string)函数:删除指定路径下的文件和目录,会将其子级文件和目录全部删除。
package mainimport ("fmt""os"
)func main() {// 删除文件err := os.RemoveAll("dir")if err != nil {panic("文件删除失败")}fmt.Println("文件删除成功")
}

1.7、目录操作

目录操作和文件操作类型,其实目录也是一种特殊的文件,Go中目录的操作有读取目录、创建目录。

1.7.1、读取目录

读取目录有两个方法可以使用,分别是:

  • os.ReadDir()函数:os包下提供的读取目录的方法,这个方法只需要传递一个目录路径即可。
  • os.File.ReadDir()方法:File文件对象提供的方法,这个方法需要文件对象进行调用。

上面两个方法,虽然是读取目录,但其实是读取目录下的所有文件和子目录,只能读取一层目录。

package mainimport ("fmt""os"
)func main() {// 读取目录dir, err := os.ReadDir("dirA")if err != nil {panic(err)}// 遍历目录for _, file := range dir {fmt.Println(file.Name())}
}

注意:ReadDir()方法只能读取一层目录,如果想要读取子目录下的文件,那么可以使用递归的方式来完成。

package mainimport ("fmt""os"
)func dfsReadDir(path string) {dir, err := os.ReadDir(path)if err != nil {fmt.Println(err)return}// 遍历目录for _, file := range dir {if file.IsDir() {// 拼接完整路径,不然无法读取目录path = path + "/" + file.Name()fmt.Println("目录==>", path)dfsReadDir(path)} else {fmt.Println("文件==>", file.Name())}}
}func main() {// 读取目录dfsReadDir("dirA")
}
1.7.2、创建目录

创建目录可以使用MkDir()MkDirAll()两个函数,MkDir()函数只能够创建一层目录,而MkDirAll()可以创建多层目录。

  • Mkdir(name string, perm FileMode)方法:创建一层目录,如果目录已经存在,则会发生panic错误。
  • MkdirAll(path string, perm FileMode)方法:创建多层目录,如果目录已经存在,则不会重新创建
package mainimport ("fmt""os"
)func main() {// 创建一层目录err := os.Mkdir("dir", 0666)if err != nil {panic(err)}fmt.Println("目录创建成功")// 创建多层目录err = os.MkdirAll("dir/dirB/dirC/dirD", 0666)if err != nil {panic(err)}fmt.Println("多层目录创建成功")
}

以上,就是Go语言中文件的相关操作。

相关文章:

  • 卓健易控ZJ-LIMS 实验室管理系统:为医院建设注入强大动力​
  • Vue + Element Plus 实战:大文件切片上传 + 断点续传
  • 网络各类型(BMA,NBMA,P2P)
  • 机器学习的数学基础:假设检验
  • 【Vue】初学Vue(setup函数,数据响应式, 脚手架 )
  • 一键 Ubuntu、Debian、Centos 换源(阿里源、腾讯源等)
  • 链表题解——环形链表【LeetCode】
  • 鸿蒙Navigation路由导航-基本使用介绍
  • 书籍转圈打印矩阵(8)0604
  • 《PyTorch Hub:解锁深度学习模型的百宝箱》
  • x86 汇编逻辑运算全解析:从【位操作】到实际应用(AND,OR,NOT,XOR,TEST)
  • NeRF PyTorch 源码解读 - NDC空间
  • 6.04打卡
  • 使用 React Native 开发鸿蒙(HarmonyOS)运动健康类应用的系统化准备工作
  • Axios学习笔记
  • 《高等数学》(同济大学·第7版)第一章第七节无穷小的比较
  • 稻米分类和病害检测数据集(猫脸码客第237期)
  • Springfox 和 Knife4j 集成404 问题
  • el-input限制输入数字,输入中文后数字校验失效
  • 回归任务和分类任务损失函数详解
  • 罗湖网站建设费用/百度竞价价格查询
  • 学校网站的图片轮播怎么做/湘潭网页设计
  • 企业购物网站建设/阳山网站seo
  • 陕西省西安市网站建设公司/十大免费b2b网站
  • 邵阳网站建设的话术/市场营销四大基本策略
  • 破网站怎么注册/发布外链的平台有哪些