Go语言进阶篇——文件

文件的打开

文件的常见的两种打开方式是基于os包所提供的两个函数:

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

相对于前者,OpenFile可以提供更加细致的操作,而前者就是对后者的一个简单封装

我们首先来看第一种使用方法,我们只需要提供对应的文件名就可以了,代码如下:

func main() {file, err := os.Open("test.txt")defer file.Close()if err != nil {fmt.Println("文件访问异常")return}
}

文件的查找路径默认为项目go.mod文件所在的路径,由于项目下并没有该文件,所以自然会返回一个错误。

因为IO错误的类型有很多,所以有时后需要我们去手动的去判断文件是否存在,而os包也为此提供了方便函数,修改后的函数如下:

func main() {file, err := os.Open("test.txt")defer file.Close()if os.IsNotExist(err) {fmt.Println("file not found")} else if err != nil {fmt.Println("error")} else {fmt.Println("file found")}
}

事实上第一种函数读取的文件仅仅只是只读的,无法被修改,Open函数内部实现

func Open(name string) (*File, error) {return OpenFile(name, O_RDONLY, 0)
}

通过OpenFile函数可以控制更多细节,例如修改文件描述符和文件权限,关于文件描述符,os包下提供了以下常量以供使用。

解释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   // 以同步IO的方式打开文件O_TRUNC  int = syscall.O_TRUNC  // 当打开的时候截断可写的文件
)

关于文件权限的则提供了以下常量。

解释const (ModeDir        = fs.ModeDir        // d: 目录ModeAppend     = fs.ModeAppend     // a: 只能添加ModeExclusive  = fs.ModeExclusive  // l: 专用ModeTemporary  = fs.ModeTemporary  // T: 临时文件ModeSymlink    = fs.ModeSymlink    // L: 符号链接ModeDevice     = fs.ModeDevice     // D: 设备文件ModeNamedPipe  = fs.ModeNamedPipe  // p: 具名管道 (FIFO)ModeSocket     = fs.ModeSocket     // S: Unix 域套接字ModeSetuid     = fs.ModeSetuid     // u: setuidModeSetgid     = fs.ModeSetgid     // g: setgidModeCharDevice = fs.ModeCharDevice // c: Unix 字符设备, 前提是设置了 ModeDeviceModeSticky     = fs.ModeSticky     // t: 黏滞位ModeIrregular  = fs.ModeIrregular  // ?: 非常规文件// 类型位的掩码. 对于常规文件而言,什么都不会设置.ModeType = fs.ModeTypeModePerm = fs.ModePerm // Unix 权限位, 0o777
)

我们下面可以实现一个以读写模式打开一个文件的代码例子,权限为0666,表示为所有人都可以对该文件进行读写,且不存在时会自动创建。

func main() {file, err := os.OpenFile("test.txt", os.O_CREATE|os.O_RDWR, 0666)if os.IsNotExist(err) {fmt.Println("文件不存在")} else if err != nil {fmt.Println("文件打开有异常")} else {fmt.Println("文件打开成功", file.Name())defer file.Close()}
}

文件的读取

常见的文件读取

当我们成功打开文件以后,我们就可以开始进行读取操作了,对于读取文件的操作,os.file提供了以下几个公开的方法

// 将文件读进传入的字节切片
func (f *File) Read(b []byte) (n int, err error) // 相较于第一种可以从指定偏移量读取
func (f *File) ReadAt(b []byte, off int64) (n int, err error) func 

大部分情况下第一种情况使用的较多,针对第一种方法,我们需要自己编写逻辑来进行读取时切片的动态扩容,代码如下:

func ReadFile(f *os.File) ([]byte, error) {buffer := make([]byte, 0, 512)for {if len(buffer) == cap(buffer) {//扩容buffer = append(buffer, 0)[:len(buffer)]}//继续读取offerset, err := f.Read(buffer[len(buffer):cap(buffer)])buffer = buffer[:len(buffer)+offerset]// 发生错误时if err != nil {if errors.Is(err, io.EOF) {err = nil}return buffer, err}}
}

剩余逻辑为:

func main() {file, err := os.OpenFile("test.txt", os.O_CREATE|os.O_RDWR, 0666)if err != nil {fmt.Println("文件打开异常")} else {fmt.Println("文件打开成功", file.Name())}bytes, err := ReadFile(file)if err != nil {fmt.Println("文件读取异常")} else {fmt.Println("文件读取成功", bytes)}file.Close()
}

除此之外,我们还可以使用两个方便函数来进行文件读取,分别是os包下的ReadFile函数以及io包下的ReadAll函数,相对于前者而言,我们只需要提供文件路径即可,而后者我们则需要提供一个io.Raeder类型的实现。

os.ReadFile

函数形式

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

使用例子:

func main() {bytes, err := os.ReadFile("README.txt")if err != nil {fmt.Println(err)} else {fmt.Println(string(bytes))}
}

io.ReadAll

函数形式:

func ReadAll(r Reader) ([]byte,error)

示例:

func main() {file, err := os.OpenFile("README.txt", os.O_RDWR|os.O_CREATE, 0666)if err != nil {fmt.Println("文件访问异常")} else {fmt.Println("文件打开成功", file.Name())bytes, err := io.ReadAll(file)if err != nil {fmt.Println(err)} else {fmt.Println(string(bytes))}file.Close()}
}

文件的写入

os.File结构体提供以下几种方法来供我们写入数据:

//写入字节切片
func (f *file) Write(b []byte) (int,error)//写入字符串
func (f *file) WriteString(s string) (int,error) 从指定位置开始写,当以os.O_APPEND模式打开时,会返回错误
func (f *File) WriteAt(b []byte, off int64) (n int, err error)

如果我们要对文件写入数据。我们需要以O_WRONLYO_RDWR

模式打开文件,否则无法写入,接下来我们来看一个示例:

func main() {file, err := os.OpenFile("README.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND|os.O_TRUNC, 0666)if err != nil {fmt.Println("文件访问异常")} else {fmt.Println("文件打开成功", file.Name())for i := 0; i < 5; i++ {offset, err := file.WriteString("hello world!\n")if err != nil {fmt.Println(offset, err)}}fmt.Println(file.Close())}
}

向文件写入字节切片也是类似的操作,就不再赘述。对于写入文件的操作标准库同样提供了方便函数,分别是os.WriteFileio.WriteString

os.WriteFile

func WriteFile(name string, data []byte, perm FileMode) error

使用例子如下

func main() {err := os.WriteFile("README.txt", []byte("hello world!\n"), 0666)if err != nil {fmt.Println(err)}
}

此时文件内容如下

hello world!

io.WriteString

func WriteString(w Writer, s string) (n int, err error) 

使用例子如下

func main() {file, err := os.OpenFile("README.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND|os.O_TRUNC, 0666)if err != nil {fmt.Println("文件访问异常")} else {fmt.Println("文件打开成功", file.Name())for i := 0; i < 5; i++ {offset, err := io.WriteString(file, "hello world!\n")if err != nil {fmt.Println(offset, err)}}fmt.Println(file.Close())}
}

文件的复制

对于复制文件而言,需要同时打开两个文件,第一种方法是将原文件中的数据读取出来,然后写入目标文件中,代码示例如下

解释func main() {// 从原文件中读取数据data, err := os.ReadFile("README.txt")if err != nil {fmt.Println(err)return}// 写入目标文件err = os.WriteFile("README(1).txt", data, 0666)if err != nil {fmt.Println(err)} else {fmt.Println("复制成功")}
}

os.File.ReadFrom

另一种方法是使用os.File提供的方法ReadFrom,打开文件时,一个只读,一个只写。

func (f *File) ReadFrom(r io.Reader) (n int64, err error)

使用示例如下

解释func main() {// 以只读的方式打开原文件origin, err := os.OpenFile("README.txt", os.O_RDONLY, 0666)if err != nil {fmt.Println(err)return}defer origin.Close()// 以只写的方式打开副本文件target, err := os.OpenFile("README(1).txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)if err != nil {fmt.Println(err)return}defer target.Close()// 从原文件中读取数据,然后写入副本文件offset, err := target.ReadFrom(origin)if err != nil {fmt.Println(err)return}fmt.Println("文件复制成功", offset)
}

io.Copy

还有一种方法就是使用io.Copy方便函数

func Copy(dst Writer, src Reader) (written int64, err error)

使用示例如下

解释func main() {// 以只读的方式打开原文件origin, err := os.OpenFile("README.txt", os.O_RDONLY, 0666)if err != nil {fmt.Println(err)return}defer origin.Close()// 以只写的方式打开副本文件target, err := os.OpenFile("README(1).txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666)if err != nil {fmt.Println(err)return}defer target.Close()// 复制written, err := io.Copy(target, origin)if err != nil {fmt.Println(err)} else {fmt.Println(written)}
}

文件重命名

重命名也可以理解为移动文件,会用到os包下的Rename函数。

func Rename(oldpath, newpath string) error

示例如下

解释func main() {err := os.Rename("README.txt", "readme.txt")if err != nil {fmt.Println(err)} else {fmt.Println("重命名成功")}
}

**注意:**重命名文件夹,移动文件夹同样适用。

文件的删除

删除操作相较于其他操作要简单的多,只会用到os包下的两个函数

解释// 删除单个文件或者空目录,当目录不为空时会返回错误
func Remove(name string) error// 删除指定目录的所有文件和目录包括子目录与子文件
func RemoveAll(path string) error 

使用起来十分的简单,下面是删除目录的例子

解释func main() {// 删除当前目录下所有的文件与子目录err := os.RemoveAll(".")if err != nil {fmt.Println(err)}else {fmt.Println("删除成功")}
}

下面删除单个文件的例子

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/717527.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

码垛工作站:食品生产企业的转型助推器

在当今高度自动化的工业生产中&#xff0c;码垛工作站的应用正逐渐成为一种趋势。某食品生产企业在面临市场竞争加剧、人工成本上升等多重压力下&#xff0c;决定引入码垛工作站&#xff0c;以期实现生产流程的升级与变革。 一、码垛工作站引入背景 该企业主要从事休闲食品的…

Android 中的 LinearLayout 布局

在 Android 开发中&#xff0c;布局是至关重要的一部分&#xff0c;它决定了应用程序的界面结构和用户体验。LinearLayout 是 Android 中最常用的布局之一&#xff0c;它以线性方式排列子视图&#xff0c;可以垂直或水平布局。在这篇博客中&#xff0c;我们将深入了解 LinearLa…

数据结构实现-栈和队列

顺序栈 #include <iostream> using namespace std; #define MaxSize 50//顺序栈 template<typename ElemType> struct SqStack{ElemType data[MaxSize];int top; };//初始化 template<typename ElemType> void InitStack(SqStack<ElemType>&s){s.…

Postman和Jmeter的区别

1.用例组织方式不同 jmeter组织方式相对比较扁平&#xff0c;没有工作空间的概念&#xff0c;直接就是测试计划 postman组织方式会比较轻量级&#xff0c;只要是针对单个的HTTP请求 2.支持的接口类型与测试类型上 jmeter会更强大&#xff0c;可以支持REST、Soap等等&#xf…

Kotlin 协程遇见 Flow:打造更优雅的数据流处理

Kotlin Flow 是 Kotlin 协程库中的一个组件&#xff0c;它提供了处理异步数据流的能力。Kotlin Flow 类似于 RxJava 中的 Observable&#xff0c;但它完全基于 Kotlin 协程设计&#xff0c;使得异步流的操作变得更加简单和直观。 Flow 是冷流&#xff08;cold stream&#xff…

【贪心算法】Leetcode 455.分发饼干 376. 摆动序列 53. 最大子数组和

【贪心算法】Leetcode 455 分发饼干 376. 摆动序列【规律很多】53. 最大子数组和 455 分发饼干局部最优推全局最优&#xff1a;尽量用大饼干去满足大胃口的小朋友 376. 摆动序列【规律很多】思想&#xff1a;注意考虑一个坡度留首尾两个点、平坡、首尾 53. 最大子数组和【好思想…

15.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-发送通信数据包至分析工具

上一个内容&#xff1a;14.数据包分析工具界面与通信设计 码云地址&#xff08;master 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/titan 码云版本号&#xff1a;2d6491e3c51a1a7ab4da0ee6dc4cf566a80fd6e1 代码下载地址&#xff0c;在 titan 目录下&…

模版进阶C++

非类型模版 之前我们写的模版都是在不知道模版&#xff08;类&#xff09;中有的变量的类型是什么的时候&#xff0c;我们先用模版参数定义&#xff0c;当类实例化的时候在传参确认 非类型模版&#xff1a;模版参数定义的时候也可以定义整型类型&#xff08;c20之后才支持其…

奇点云:SAFe框架下,我们对平台软件工程生产线做了4项改造

导读&#xff1a; 客户规模扩大&#xff0c;如何保证大数据软件产品和服务质量始终如一&#xff1f;几乎所有成长中的软件厂商&#xff0c;尤其是需要通过私有化部署交付的厂商&#xff0c;都会面临这个问题。正如《人月神话》中多次表明的&#xff0c;单纯地增加人手、扩大团队…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的植物病害检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;开发高效的植物病害检测系统对于提升农业生产效率和作物健康管理意义重大。本篇博客详细阐述了如何运用深度学习技术构建一个植物病害检测系统&#xff0c;并提供了完整的实现代码。该系统基于先进的YOLOv8算法&#xff0c;对YOLOv7、YOLOv6、YOLOv5进行了性能…

考研数学——高数:微分方程

一、一阶线性微分方程 两种形式&#xff1a; 非齐次&#xff1a; 齐次&#xff1a; 推导过程 推导公式的过程一般由特殊到一般&#xff1a;所以先求解齐次方程的解 &#xff08;然后对等式两边同时积分&#xff09; 再来求非齐次方程的解&#xff0c;由…

【测开求职】2023秋招快手一面面经

已经过了百度测开三面,快手这个一面比百度的要难很多,可能也是遇到了比较严格的面试官,感觉其他面经没有这么难。30分钟实习,20分钟算法题,20分钟八股,没有问项目。 实习 diff遇到了哪些痛点diff是全量还是增量一些字段的增加或者枚举值的增加可以用diff测吗有哪些自动化…

03-grafana的下拉列表选项制作-grafana的变量

一、准备环境 为了实现下拉列表筛选的样例&#xff0c;我们监控两个linux节点&#xff1b; 目前&#xff0c;我们已经有了一个节点了&#xff0c;再添加一个&#xff1b; 二、grafana的仪表盘变量 如果想给仪表盘自定义下拉列表&#xff0c;那么&#xff0c;需要设置变量&#…

线上问题——2021-12-27 父子线程共用线程池导致死锁故障

一、事故现象 从早上6点开始edu-wings-admin的timer-task和mq就开始报警任务堆积&#xff0c;且数量持续上升&#xff0c;到6点50左右mq也开始告警&#xff0c;8点左右发现问题&#xff0c;开始排查&#xff0c;直到11点才找到问题&#xff0c;任务开始正常消费。 二、事故影响…

haproxy集成国密ssl功能[下]

上接[haproxy集成国密ssl功能上 4. 源码修改解析 以下修改基本围绕haproxy的ssl_sock.c进行修改来展开的,为了将整个实现逻辑能够说明清楚,下述内容有部分可能就是直接摘抄haproxy的原有代码没有做任何修改,而大部分增加或者修改的内容则进行了特别的说明。 4.1 为bind指令…

基于springboot+vue的疾病防控综合系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

计算机设计大赛 深度学习猫狗分类 - python opencv cnn

文章目录 0 前言1 课题背景2 使用CNN进行猫狗分类3 数据集处理4 神经网络的编写5 Tensorflow计算图的构建6 模型的训练和测试7 预测效果8 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **基于深度学习猫狗分类 ** 该项目较为新颖&a…

Python测试框架pytest介绍用法

1、介绍 pytest是python的一种单元测试框架&#xff0c;同自带的unittest测试框架类似&#xff0c;相比于unittest框架使用起来更简洁、效率更高 pip install -U pytest 特点&#xff1a; 1.非常容易上手,入门简单,文档丰富&#xff0c;文档中有很多实例可以参考 2.支持简单的单…

C++内存模型与内存序

写在前面 在真正了解Memory Order的作用之前&#xff0c;曾经简单地将Memory Order等同于mutex和atomic来进行线程间数据同步&#xff0c;或者用来限制线程间的执行顺序&#xff0c;其实这是一个错误的理解。直到后来仔细研究了Memory Order之后&#xff0c;才发现无论是功能还…

Android 12 设置默认的屏幕亮度百分比

1、安卓每个版本的更新&#xff0c; 其核心代码也会随之更新&#xff0c;本次为Android 12 版本默认屏幕亮度的修改。 其中涉及的核心代码主要有&#xff1a; packages\apps\Settings\src\com\android\settings\display\BrightnessLevelPreferenceController.java frameworks…