走到这里的探索者们,对电脑是相当了解的,接下来用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中的一个。
- 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 //打开时截断常规可写文件。
我使用了创建文件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的角度,去思考和操作文件和文档!
文件/文档:大致生命流程,创建--重命名--修改权限--阅读/修改内容--删除