17、做中学 | 初三下期 Golang文件操作

走到这里的探索者们,对电脑是相当了解的,接下来用go和系统来次对话!

一、go的角度认识文件

1. 什么是文件

在面向对象编程语言中,一切皆对象,而在操作系统(如:Linux)一切皆文件!我们记录的txt文件,办公的excel文件,拍的照片jpg文件,录的语音mp4文件,拍的视频mp4文件...都是文件。他们都是进行保存我们的数据。

2. 输入流/输出流

编程操作文件的过程,是通过流的形式进行操作的!

图中出现了"流"的概念,和流的经历的路径,具体意思如下:

流:数据在数据源(文件)和程序(内存)之间经历的路径 (上班下班来回路线)

输入流:数据从数据源(文件)到程序(内存)的路径 (从家到公司的路线)

输出流:数据从程序(内存)到数据源(文件)的路径 (从公司到家的路线)

站在了内存的角度去看流的方向

二、文件操作

https://studygolang.com/pkgdoc

os包File结构体下,有一些公用的文件操作方法

1. 打开/关闭文件

1.1 打开文件

根据官网学习网站,os包File结构体下需要调用这个方法,进行打开文件

go 复制代码
func Open(name string) (file *File, err error)

在d盘新建一个txt文档,进行打开文件

go 复制代码
	// 返回file指针对象,err为异常接收
	file, err := os.Open("d:\\file.txt")

	// 进行处理接收的异常 这里直接结束main
	if err != nil {
		return
	}

	fmt.Printf("file: %v", file)

来到了公司(内存),我们不能一直上班,这时需要打卡下班...

1.2 关闭文件(有打开必有关闭)

打卡下班!!!

go 复制代码
func (f *File) Close() error

没有入参,返回抛出的异常。

go 复制代码
	// 关闭文件 接收抛出的异常
	err = file.Close()

	// 异常处理  这里直接打印
	if err != nil {
		fmt.Println(err)
	}

2. 读文件

2.1 读取小文件

一次性加载全部内容到内存,适合读取小文件

go 复制代码
package main

import (
	"fmt"
	"os"
)

func main() {
	file, err := os.ReadFile("d:\\file.txt")
	if err != nil {
		return
	}
	fmt.Println(string(file))
	//《泊船瓜洲》
	//宋朝·王安石
	//京口瓜洲一水间,钟山只隔数重山。
	//春风又绿江南岸,明月何时照我还。
}

2.2 按行读取文件

获取到文件对象,进行每行内容加载到内存,适合大文件

bufio 优化性能:通过缓冲减少 I/O 操作次数,适合频繁读写。

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	// 打开文件
	file, err := os.Open("d:\\file.txt")
	if err != nil {
		return
	}

	// 关闭文件
	defer file.Close()

	// 读取文件
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
		fmt.Println("------------------")
	}

	if scanner.Err() != nil {
		fmt.Println(scanner.Err())
	}
	//《泊船瓜洲》
	//------------------
	//宋朝·王安石
	//------------------
	//京口瓜洲一水间,钟山只隔数重山。
	//------------------
	//春风又绿江南岸,明月何时照我还。
	//------------------
}

3. 写文件

3.1 小文件写入

打开文件并写入,使用OpenFile方法进行模式选择和权限赋予

go 复制代码
package main

import (
	"fmt"
	"os"
)

func main() {
	// 打开文件的同时 如果有则进行清空写入 无则进行创建并写入
	file, err := os.OpenFile("d:\\writerfile.txt", os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	// 写入一个文件 提前创建了一个空文件
	file.WriteString("hello golang2\n")
}

上边我们看到OpenFile方法中入参有俩个陌生的参数,模式和参数

打开文件模式列表如下

必须项:必须指定O_RDONLY、O_WRONLY或O_RDWR中的一个。

  1. O_RDONLY int=syscall.O_RDONLY //以只读方式打开文件。
  2. O_WRONLY int=syscall.O_WRONLY //以写方式打开文件。
  3. O_RDWR int=syscall.O_RDWR //以读写方式打开文件。

可选项:其余的值可以被输入或输入以控制行为。

  1. O_APPEND int=syscall.O_APPEND //写入时向文件追加数据。
  2. O_CREATE int=syscall.O_CREAT //如果不存在,则创建一个新文件。
  3. O_EXCL int=syscall.O_EXCL //与O_CREATE一起使用时,文件必须不存在。
  4. O_SYNC int=syscall.O_SYNC //打开同步I/O。
  5. O_TRUNC int=syscall.O_TRUNC //打开时截断常规可写文件。

我使用了创建文件O_CREAT模式 和写入O_WRONLY模式,想创建文件并写人内容!

第二个陌生的参数是0666是什么意思呢?这个熟悉Linux的探索者们一定不陌生,这个就是文件的权限

所以你需要什么权限相加就行,0666意思如下

0:代表八进制

6:所有者 拥有r(读)和w(写)权限

6:所属组 拥有r(读)和w(写)权限

6:其他人拥有r(读)和w(写)权限

3.2 按行写入

go 复制代码
package main

import (
	"bufio"
	"os"
)

func main() {
	// 打开文件
	file, err := os.Create("d:\\fileWriterLine.txt")
	if err != nil {
		return
	}

	// 关闭文件
	defer file.Close()

	// 写入文件
	writer := bufio.NewWriter(file)
	arr := []string{
		"《泊船瓜洲》",
		"宋朝·王安石",
		"京口瓜洲一水间,钟山只隔数重山。",
		"春风又绿江南岸,明月何时照我还。",
	}
	for _, line := range arr {
		writer.WriteString(line)
		writer.WriteString("\n")
	}

	writer.Flush()
}

为什么最后会有个Flush方法呢?原因是NewWriter是带缓存的,进行批次写入,就像十字路口攒了一批人,可以闯红灯一样...

三、小练习

了解了怎么文件是什么,如何通过go去操作文件,那么开始来个小练习

练习内容如下

go 复制代码
	// 1. 创建一个文件
	// 2. 按行写入
	// 3. 追加写入时间
	// 4. 进行文件重命名
	// 5. 按行读取文件
	// 6. 删除文件

根据上边的需求内容,进行编写

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	// 1. 创建一个文件
	// 2. 按行写入
	// 3. 追加写入时间
	// 4. 进行文件重命名
	// 5. 按行读取文件
	// 6. 删除文件

	// 1. 创建一个文件
	fileWriter, err := os.OpenFile("d:\\file.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	if err != nil {
		fmt.Printf("open file failed, err:%v\n", err)
		return
	}

	// 2. 按行写入文件
	writer := bufio.NewWriter(fileWriter)
	arr := []string{
		"《泊船瓜洲》",
		"宋朝·王安石",
		"京口瓜洲一水间,钟山只隔数重山。",
		"春风又绿江南岸,明月何时照我还。",
	}
	for _, line := range arr {
		writer.WriteString(line)
		writer.WriteString("\n")
	}

	writer.Flush()

	// 3. 追加写入时间
	fileWriter.WriteString("\n" + "2021-09-02 15:05:05")
	fileWriter.Sync()

	// 方法结束后,进行关闭文件
	fileWriter.Close()

	// 4. 文件重命名
	err = os.Rename("d:\\file.txt", "d:\\fileTest.txt")
	if err != nil {
		fmt.Printf("rename file failed, err:%v\n", err)
		return
	}

	// 5. 按行读取文件
	fileRead, err := os.Open("d:\\fileTest.txt")
	if err != nil {
		fmt.Printf("open file failed, err:%v\n", err)
		return
	}
	// 按行读取
	scanner := bufio.NewScanner(fileRead)
	for scanner.Scan() {
		fmt.Println(scanner.Text())
		fmt.Println("------------")
	}
	if scanner.Err() != nil {
		fmt.Println(scanner.Err())
	}

	// 关闭读文件流
	fileRead.Close()

	// 6. 删除文件
	err = os.Remove("d:\\fileTest.txt")
	if err != nil {
		fmt.Printf("remove file failed, err:%v\n", err)
		return
	}

}

文件其它方法调用方法大致相同,在特定的场景和需求下,进行合理使用!本篇为引导篇,不做全部列举!

平常电脑操作的文件的时候,我们都是通过鼠标右键,选择功能进行操作!

现在学了go,我们站在了go的角度,去思考和操作文件和文档!

文件/文档:大致生命流程,创建--重命名--修改权限--阅读/修改内容--删除

相关推荐
倚肆1 小时前
Spring Boot CORS 配置详解:CorsConfigurationSource 全面指南
java·spring boot·后端
databook1 小时前
告别盲人摸象,数据分析的抽样方法总结
后端·python·数据分析
v***44672 小时前
springboot之集成Elasticsearch
spring boot·后端·elasticsearch
q***72192 小时前
Spring Boot(快速上手)
java·spring boot·后端
CoderYanger2 小时前
C.滑动窗口——1423. 可获得的最大点数
java·开发语言·算法·leetcode·1024程序员节
全栈陈序员2 小时前
【Python】基础语法入门(九)—— 代码规范、调试技巧与性能初探
开发语言·python·代码规范
合作小小程序员小小店2 小时前
图书管理系统,基于winform+sql sever,开发语言c#,数据库mysql
开发语言·数据库·sql·microsoft·c#
Yue丶越2 小时前
【C语言】数据在内存中的存储
c语言·开发语言·网络
FakeOccupational2 小时前
电路笔记(信号):网线能传多少米?网线信号传输距离
开发语言·笔记·php