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

【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语言中文件的相关操作。

http://www.xdnf.cn/news/11811.html

相关文章:

  • tauri2项目中自定义执行cmd命令界面卡死以及中文出错问题
  • Elasticsearch中的监控(Monitoring)功能介绍
  • 【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
  • 八:操作系统设备管理之I/O 操作方法
  • AI编程规范失控?三大策略用Cursor Rules精准约束
  • 电子手机商城源码+springboot+vue3(带用户协同过滤个性化推荐算法)
  • DexUMI:以人手为通用操作界面,实现灵巧操作
  • 平面上的最接近点对
  • 怎么通过 jvmti 去 hook java 层函数
  • 构建高效可靠的电商 API:设计原则与实践指南
  • PyTorch学习笔记 - 损失函数
  • unix/linux,sudo,其历史争议、兼容性、生态、未来展望
  • 如何有效删除 iPhone 上的所有内容?
  • 激光干涉仪:解锁协作机器人DD马达的精度密码
  • 前端工具库lodash与lodash-es区别详解
  • ES海量数据更新及导入导出备份
  • 设计模式之单例模式(二): 心得体会
  • UE 5 和simulink联合仿真,如果先在UE5这一端结束Play,过一段时间以后**Unreal Engine 5** 中会出现显存不足错误
  • 功能测试、性能测试、安全测试详解
  • 近端策略优化(PPO,Proximal Policy Optimization)
  • vue实现点击按钮input保持聚焦状态
  • Oracle实用参考(13)——Oracle for Linux静默安装(1)
  • springboot 微服务 根据tomcat maxthread 和 等待用户数量,达到阈值后,通知用户前面还有多少用户等待,请稍后重试
  • 低代码采购系统搭建:鲸采云+能源行业订单管理自动化案例
  • Electron打包前端和后端为exe
  • el-table 树形数据,子行数据可以异步加载
  • 破解HTTP无状态:基于Java的Session与Cookie协同工作指南
  • 618浴室柜推荐,小户型浴室柜怎么选才省心?
  • 江科大睡眠,停止,待机模式hal库实现
  • MySQL范式和反范式