Go 文件处理 - GO教程

Go 语言文件处理

在 Go 语言中,文件处理是一个非常重要的功能,它允许我们读取、写入和操作文件。无论是处理配置文件、日志文件,还是进行数据持久化,文件处理都是不可或缺的一部分。

Go 语言提供了丰富的标准库来支持文件处理,包括文件的打开、关闭、读取、写入、追加和删除等操作。

  1. os 是核心库 :提供底层文件操作(创建、读写、删除等),大多数场景优先使用。

  2. io 提供通用接口 :如 Reader / Writer ,可与文件、网络等数据源交互。

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

  4. ioutil 已弃用 :Go 1.16 后其功能迁移到 os io 包。

  5. path/filepath 处理路径 :跨平台兼容(Windows/Unix 路径分隔符差异)。

库名 主要方法/函数 用途说明 示例代码
os Create(name string) (*File, error) 创建文件(若存在则清空) file, err := os.Create("test.txt")
Open(name string) (*File, error) 只读方式打开文件 file, err := os.Open("data.txt")
OpenFile(name string, flag int, perm FileMode) (*File, error) 自定义模式打开文件(可指定读写、追加等) file, err := os.OpenFile("log.txt", os.O_APPEND|os.O_WRONLY, 0644)
ReadFile(name string) ([]byte, error) 一次性读取整个文件内容(小文件适用) data, err := os.ReadFile("config.json")
WriteFile(name string, data []byte, perm FileMode) error 一次性写入文件(覆盖原有内容) err := os.WriteFile("out.txt", []byte("Hello"), 0644)
Remove(name string) error 删除文件或空目录 err := os.Remove("temp.txt")
Rename(oldpath, newpath string) error 重命名或移动文件 err := os.Rename("old.txt", "new.txt")
Stat(name string) (FileInfo, error) 获取文件信息(大小、权限等) info, err := os.Stat("file.txt")
Mkdir(name string, perm FileMode) error 创建单个目录 err := os.Mkdir("mydir", 0755)
MkdirAll(path string, perm FileMode) error 递归创建多级目录 err := os.MkdirAll("path/to/dir", 0755)
ReadDir(name string) ([]DirEntry, error) 读取目录内容 entries, err := os.ReadDir(".")
io Copy(dst Writer, src Reader) (written int64, err error) Reader 复制数据到 Writer (如文件复制) io.Copy(dstFile, srcFile)
ReadAll(r Reader) ([]byte, error) Reader 读取所有数据(类似 os.ReadFile ,但针对接口) data, err := io.ReadAll(file)
bufio NewScanner(r Reader) *Scanner 创建逐行扫描器(适合逐行读取) scanner := bufio.NewScanner(file)
NewReader(rd io.Reader) *Reader 创建带缓冲的读取器(提高大文件读取效率) reader := bufio.NewReader(file)
NewWriter(w io.Writer) *Writer 创建带缓冲的写入器(提高写入效率) writer := bufio.NewWriter(file)
ioutil ReadFile(filename string) ([]byte, error) (已弃用,推荐 os.ReadFile data, err := ioutil.ReadFile("old.txt")
WriteFile(filename string, data []byte, perm os.FileMode) error (已弃用,推荐 os.WriteFile err := ioutil.WriteFile("out.txt", data, 0644)
TempDir(dir, pattern string) (name string, err error) (已弃用,推荐 os.MkdirTemp dir, err := ioutil.TempDir("", "tmp")
TempFile(dir, pattern string) (f *os.File, err error) (已弃用,推荐 os.CreateTemp file, err := ioutil.TempFile("", "temp-*")
path/filepath Join(elem ...string) string 跨平台安全的路径拼接 path := filepath.Join("dir", "file.txt")
Walk(root string, fn WalkFunc) error 递归遍历目录树 filepath.Walk(".", func(path string, info os.FileInfo, err error) error {...})
Abs(path string) (string, error) 获取绝对路径 absPath, err := filepath.Abs("file.txt")

不同场景推荐使用方法

场景 推荐方法 原因
读取小文件 os.ReadFile("file.txt") 简洁高效,自动处理打开/关闭
逐行读取大文件 bufio.NewScanner(file) 内存友好,逐行处理
高效写入大量数据 bufio.NewWriter(file) + writer.WriteString() 缓冲减少磁盘 I/O 次数
递归遍历目录 filepath.Walk("/path", callback) 自动处理子目录和错误
跨平台路径拼接 filepath.Join("dir", "file.txt") 自动处理不同操作系统的路径分隔符( / \

文件创建

在 Go 语言中,我们使用 os 包来创建文件。

os.Create 函数用于创建一个文件,并返回一个 *os.File 类型的文件对象。创建文件后,我们通常需要调用 Close 方法来关闭文件,以释放系统资源。

示例代码
packagemainimport("log""os")funcmain(){// 创建文件,如果文件已存在会被截断(清空)file,err:=os.Create("test.txt")iferr!=nil{log.Fatal(err)}deferfile.Close()// 确保文件关闭log.Println("文件创建成功")}

文件的打开与关闭

在 Go 语言中,我们使用 os 包来打开和关闭文件。

os.Open 函数用于打开一个文件,并返回一个 *os.File 类型的文件对象。打开文件后,我们通常需要调用 Close 方法来关闭文件,以释放系统资源。

打开文件

示例代码
packagemainimport("fmt""os")funcmain(){file,err:=os.Open("example.txt")iferr!=nil{fmt.Println("Error opening file:",err)return}deferfile.Close()fmt.Println("File opened successfully!")}

在上面的代码中,我们使用 os.Open 打开了一个名为 example.txt 的文件。如果文件打开失败,程序会打印错误信息并退出。 defer file.Close() 确保在函数返回前关闭文件。

关闭文件是一个重要的步骤,它可以防止文件描述符泄漏。在 Go 中,我们通常使用 defer 语句来确保文件在函数结束时被关闭。


文件的读取

Go 语言提供了多种读取文件的方式,包括逐行读取、一次性读取整个文件等。我们可以使用 bufio 包来逐行读取文件,或者使用 ioutil 包来一次性读取整个文件。

逐行读取文件

示例代码
packagemainimport("bufio""fmt""os")funcmain(){file,err:=os.Open("example.txt")iferr!=nil{fmt.Println("Error opening file:",err)return}deferfile.Close()scanner:=bufio.NewScanner(file)forscanner.Scan(){fmt.Println(scanner.Text())}iferr:=scanner.Err();err!=nil{fmt.Println("Error reading file:",err)}}

在上面的代码中,我们使用 bufio.NewScanner 创建了一个扫描器,然后通过 scanner.Scan() 逐行读取文件内容,并使用 scanner.Text() 获取每一行的文本。

一次性读取整个文件

示例代码
packagemainimport("fmt""io/ioutil")funcmain(){content,err:=ioutil.ReadFile("example.txt")iferr!=nil{fmt.Println("Error reading file:",err)return}fmt.Println(string(content))}

在这个例子中,我们使用 ioutil.ReadFile 一次性读取整个文件的内容,并将其转换为字符串打印出来。


文件的写入

Go 语言也提供了多种写入文件的方式,包括逐行写入、一次性写入等。我们可以使用 os 包来创建和写入文件。

示例代码
packagemainimport("log""os")funcmain(){// 方式1:直接写入字符串file,err:=os.Create("write1.txt")iferr!=nil{log.Fatal(err)}deferfile.Close()file.WriteString("直接写入字符串\n")// 方式2:写入字节切片data:=[]byte("写入字节切片\n")file.Write(data)// 方式3:使用fmt.Fprintf格式化写入fmt.Fprintf(file,"格式化写入: %d\n",123)}

逐行写入文件

示例代码
packagemainimport("bufio""fmt""os")funcmain(){file,err:=os.Create("output.txt")iferr!=nil{fmt.Println("Error creating file:",err)return}deferfile.Close()writer:=bufio.NewWriter(file)fmt.Fprintln(writer,"Hello, World!")writer.Flush()}

在这个例子中,我们使用 os.Create 创建了一个名为 output.txt 的文件,并使用 bufio.NewWriter 创建一个写入器。然后,我们使用 fmt.Fprintln 将字符串写入文件,并调用 writer.Flush() 确保所有数据都被写入文件。

一次性写入文件

示例代码
packagemainimport("fmt""io/ioutil")funcmain(){content:=[]byte("Hello, World!")err:=ioutil.WriteFile("output.txt",content,0644)iferr!=nil{fmt.Println("Error writing file:",err)return}fmt.Println("File written successfully!")}

在这个例子中,我们使用 ioutil.WriteFile 一次性将字节数组写入文件。 0644 是文件的权限模式,表示文件所有者可以读写,其他用户只能读取。


文件的追加写入

有时候我们需要在文件的末尾追加内容,而不是覆盖原有内容。Go 语言提供了 os.OpenFile 函数来实现这一功能。

示例代码
packagemainimport("fmt""os")funcmain(){file,err:=os.OpenFile("output.txt",os.O_APPEND|os.O_WRONLY,0644)iferr!=nil{fmt.Println("Error opening file:",err)return}deferfile.Close()if_,err:=file.WriteString("Appended text\n");err!=nil{fmt.Println("Error appending to file:",err)return}fmt.Println("Text appended successfully!")}

在这个例子中,我们使用 os.OpenFile 打开文件,并指定 os.O_APPEND 标志来在文件末尾追加内容。然后,我们使用 file.WriteString 将字符串追加到文件中。


文件的删除

在 Go 语言中,我们可以使用 os.Remove 函数来删除文件。

示例代码
packagemainimport("fmt""os")funcmain(){err:=os.Remove("output.txt")iferr!=nil{fmt.Println("Error deleting file:",err)return}fmt.Println("File deleted successfully!")}

在这个例子中,我们使用 os.Remove 删除了名为 output.txt 的文件。如果文件删除失败,程序会打印错误信息。


文件信息与操作

获取文件信息

示例代码
packagemainimport("fmt""log""os")funcmain(){fileInfo,err:=os.Stat("test.txt")iferr!=nil{log.Fatal(err)}fmt.Println("文件名:",fileInfo.Name())fmt.Println("文件大小:",fileInfo.Size(),"字节")fmt.Println("权限:",fileInfo.Mode())fmt.Println("最后修改时间:",fileInfo.ModTime())fmt.Println("是目录吗:",fileInfo.IsDir())}

检查文件是否存在

示例代码
import("fmt""os")funcmain(){if_,err:=os.Stat("test.txt");os.IsNotExist(err){fmt.Println("文件不存在")}else{fmt.Println("文件存在")}}

重命名和移动文件

示例代码
packagemainimport("log""os")funcmain(){err:=os.Rename("old.txt","new.txt")iferr!=nil{log.Fatal(err)}log.Println("重命名成功")}

目录操作

创建目录

示例代码
packagemainimport("log""os")funcmain(){// 创建单个目录err:=os.Mkdir("newdir",0755)iferr!=nil{log.Fatal(err)}// 递归创建多级目录err=os.MkdirAll("path/to/newdir",0755)iferr!=nil{log.Fatal(err)}}

读取目录内容

示例代码
packagemainimport("fmt""log""os")funcmain(){entries,err:=os.ReadDir(".")iferr!=nil{log.Fatal(err)}for_,entry:=rangeentries{info,_:=entry.Info()fmt.Printf("%-20s %8d %v\n",entry.Name(),info.Size(),info.ModTime().Format("2006-01-02 15:04:05"))}}

删除目录

示例代码
packagemainimport("log""os")funcmain(){// 删除空目录err:=os.Remove("emptydir")iferr!=nil{log.Fatal(err)}// 递归删除目录及其内容err=os.RemoveAll("path/to/dir")iferr!=nil{log.Fatal(err)}}

高级文件操作

文件复制

示例代码
packagemainimport("io""log""os")funcmain(){srcFile,err:=os.Open("source.txt")iferr!=nil{log.Fatal(err)}defersrcFile.Close()dstFile,err:=os.Create("destination.txt")iferr!=nil{log.Fatal(err)}deferdstFile.Close()bytesCopied,err:=io.Copy(dstFile,srcFile)iferr!=nil{log.Fatal(err)}log.Printf("复制完成,共复制 %d 字节",bytesCopied)}

文件追加

示例代码
packagemainimport("log""os")funcmain(){file,err:=os.OpenFile("log.txt",os.O_APPEND|os.O_CREATE|os.O_WRONLY,0644)iferr!=nil{log.Fatal(err)}deferfile.Close()if_,err:=file.WriteString("新的日志内容\n");err!=nil{log.Fatal(err)}}

临时文件和目录

示例代码
packagemainimport("fmt""log""os")funcmain(){// 创建临时文件tmpFile,err:=os.CreateTemp("","example-*.txt")iferr!=nil{log.Fatal(err)}deferos.Remove(tmpFile.Name())// 清理fmt.Println("临时文件:",tmpFile.Name())// 创建临时目录tmpDir,err:=os.MkdirTemp("","example-*")iferr!=nil{log.Fatal(err)}deferos.RemoveAll(tmpDir)// 清理fmt.Println("临时目录:",tmpDir)}