Go 语言文件处理
在 Go 语言中,文件处理是一个非常重要的功能,它允许我们读取、写入和操作文件。无论是处理配置文件、日志文件,还是进行数据持久化,文件处理都是不可或缺的一部分。
Go 语言提供了丰富的标准库来支持文件处理,包括文件的打开、关闭、读取、写入、追加和删除等操作。
os
是核心库:提供底层文件操作(创建、读写、删除等),大多数场景优先使用。io
提供通用接口:如Reader
/Writer
,可与文件、网络等数据源交互。bufio
优化性能:通过缓冲减少 I/O 操作次数,适合频繁读写。ioutil
已弃用:Go 1.16 后其功能迁移到os
和io
包。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
方法来关闭文件,以释放系统资源。
实例
import (
"log"
"os"
)
func main() {
// 创建文件,如果文件已存在会被截断(清空)
file, err := os.Create("test.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close() // 确保文件关闭
log.Println("文件创建成功")
}
文件的打开与关闭
在 Go 语言中,我们使用 os
包来打开和关闭文件。
os.Open
函数用于打开一个文件,并返回一个 *os.File
类型的文件对象。打开文件后,我们通常需要调用 Close
方法来关闭文件,以释放系统资源。
打开文件
实例
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
fmt.Println("File opened successfully!")
}
在上面的代码中,我们使用 os.Open
打开了一个名为 example.txt
的文件。如果文件打开失败,程序会打印错误信息并退出。defer file.Close()
确保在函数返回前关闭文件。
关闭文件是一个重要的步骤,它可以防止文件描述符泄漏。在 Go 中,我们通常使用 defer
语句来确保文件在函数结束时被关闭。
文件的读取
Go 语言提供了多种读取文件的方式,包括逐行读取、一次性读取整个文件等。我们可以使用 bufio
包来逐行读取文件,或者使用 ioutil
包来一次性读取整个文件。
逐行读取文件
实例
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}
if err := scanner.Err(); err != nil {
fmt.Println("Error reading file:", err)
}
}
在上面的代码中,我们使用 bufio.NewScanner
创建了一个扫描器,然后通过 scanner.Scan()
逐行读取文件内容,并使用 scanner.Text()
获取每一行的文本。
一次性读取整个文件
实例
import (
"fmt"
"io/ioutil"
)
func main() {
content, err := ioutil.ReadFile("example.txt")
if err != nil {
fmt.Println("Error reading file:", err)
return
}
fmt.Println(string(content))
}
在这个例子中,我们使用 ioutil.ReadFile
一次性读取整个文件的内容,并将其转换为字符串打印出来。
文件的写入
Go 语言也提供了多种写入文件的方式,包括逐行写入、一次性写入等。我们可以使用 os
包来创建和写入文件。
实例
import (
"log"
"os"
)
func main() {
// 方式1:直接写入字符串
file, err := os.Create("write1.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
file.WriteString("直接写入字符串\n")
// 方式2:写入字节切片
data := []byte("写入字节切片\n")
file.Write(data)
// 方式3:使用fmt.Fprintf格式化写入
fmt.Fprintf(file, "格式化写入: %d\n", 123)
}
逐行写入文件
实例
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.Create("output.txt")
if err != nil {
fmt.Println("Error creating file:", err)
return
}
defer file.Close()
writer := bufio.NewWriter(file)
fmt.Fprintln(writer, "Hello, World!")
writer.Flush()
}
在这个例子中,我们使用 os.Create
创建了一个名为 output.txt
的文件,并使用 bufio.NewWriter
创建一个写入器。然后,我们使用 fmt.Fprintln
将字符串写入文件,并调用 writer.Flush()
确保所有数据都被写入文件。
一次性写入文件
实例
import (
"fmt"
"io/ioutil"
)
func main() {
content := []byte("Hello, World!")
err := ioutil.WriteFile("output.txt", content, 0644)
if err != nil {
fmt.Println("Error writing file:", err)
return
}
fmt.Println("File written successfully!")
}
在这个例子中,我们使用 ioutil.WriteFile
一次性将字节数组写入文件。0644
是文件的权限模式,表示文件所有者可以读写,其他用户只能读取。
文件的追加写入
有时候我们需要在文件的末尾追加内容,而不是覆盖原有内容。Go 语言提供了 os.OpenFile
函数来实现这一功能。
实例
import (
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("output.txt", os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("Error opening file:", err)
return
}
defer file.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
函数来删除文件。
实例
import (
"fmt"
"os"
)
func main() {
err := os.Remove("output.txt")
if err != nil {
fmt.Println("Error deleting file:", err)
return
}
fmt.Println("File deleted successfully!")
}
在这个例子中,我们使用 os.Remove
删除了名为 output.txt
的文件。如果文件删除失败,程序会打印错误信息。
文件信息与操作
获取文件信息
实例
import (
"fmt"
"log"
"os"
)
func main() {
fileInfo, err := os.Stat("test.txt")
if err != nil {
log.Fatal(err)
}
fmt.Println("文件名:", fileInfo.Name())
fmt.Println("文件大小:", fileInfo.Size(), "字节")
fmt.Println("权限:", fileInfo.Mode())
fmt.Println("最后修改时间:", fileInfo.ModTime())
fmt.Println("是目录吗:", fileInfo.IsDir())
}
检查文件是否存在
实例
"fmt"
"os"
)
func main() {
if _, err := os.Stat("test.txt"); os.IsNotExist(err) {
fmt.Println("文件不存在")
} else {
fmt.Println("文件存在")
}
}
重命名和移动文件
实例
import (
"log"
"os"
)
func main() {
err := os.Rename("old.txt", "new.txt")
if err != nil {
log.Fatal(err)
}
log.Println("重命名成功")
}
目录操作
创建目录
实例
import (
"log"
"os"
)
func main() {
// 创建单个目录
err := os.Mkdir("newdir", 0755)
if err != nil {
log.Fatal(err)
}
// 递归创建多级目录
err = os.MkdirAll("path/to/newdir", 0755)
if err != nil {
log.Fatal(err)
}
}
读取目录内容
实例
import (
"fmt"
"log"
"os"
)
func main() {
entries, err := os.ReadDir(".")
if err != nil {
log.Fatal(err)
}
for _, entry := range entries {
info, _ := entry.Info()
fmt.Printf("%-20s %8d %v\n",
entry.Name(),
info.Size(),
info.ModTime().Format("2006-01-02 15:04:05"))
}
}
删除目录
实例
import (
"log"
"os"
)
func main() {
// 删除空目录
err := os.Remove("emptydir")
if err != nil {
log.Fatal(err)
}
// 递归删除目录及其内容
err = os.RemoveAll("path/to/dir")
if err != nil {
log.Fatal(err)
}
}
高级文件操作
文件复制
实例
import (
"io"
"log"
"os"
)
func main() {
srcFile, err := os.Open("source.txt")
if err != nil {
log.Fatal(err)
}
defer srcFile.Close()
dstFile, err := os.Create("destination.txt")
if err != nil {
log.Fatal(err)
}
defer dstFile.Close()
bytesCopied, err := io.Copy(dstFile, srcFile)
if err != nil {
log.Fatal(err)
}
log.Printf("复制完成,共复制 %d 字节", bytesCopied)
}
文件追加
实例
import (
"log"
"os"
)
func main() {
file, err := os.OpenFile("log.txt",
os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
if _, err := file.WriteString("新的日志内容\n"); err != nil {
log.Fatal(err)
}
}
临时文件和目录
实例
import (
"fmt"
"log"
"os"
)
func main() {
// 创建临时文件
tmpFile, err := os.CreateTemp("", "example-*.txt")
if err != nil {
log.Fatal(err)
}
defer os.Remove(tmpFile.Name()) // 清理
fmt.Println("临时文件:", tmpFile.Name())
// 创建临时目录
tmpDir, err := os.MkdirTemp("", "example-*")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(tmpDir) // 清理
fmt.Println("临时目录:", tmpDir)
}
点我分享笔记
笔记需要是本篇文章的内容扩展!文章投稿,可点击这里
注册邀请码获取方式
分享笔记前必须登录!
注册邀请码获取方式
-->