在Golang的标准库中,io包定义了基础的I/O接口,这些接口是很多I/O操作的核心,文件读写操作也可以基于io包的相关能力实现,不需要依赖过于复杂的额外逻辑。

io包核心接口说明
io包中定义了几个和文件读写密切相关的接口,理解这些接口是掌握文件读写的基础:
- io.Reader:定义了Read方法,用于从数据源读取数据,文件对象就实现了这个接口
- io.Writer:定义了Write方法,用于向目标写入数据,文件对象同样实现了这个接口
- io.ReadWriter:组合了Reader和Writer接口,同时支持读写操作
- io.Copy:通用的复制函数,可以将Reader的数据复制到Writer中,常用于文件复制场景
基础文件读取实现
使用io包读取文件时,首先需要打开文件,获取实现了io.Reader接口的文件对象,再通过Read方法读取数据。
逐块读取文件内容
这种方式适合读取大文件,避免一次性加载全部内容占用过多内存:
package main
import (
"fmt"
"io"
"os"
)
func main() {
// 打开文件,返回的文件对象实现了io.Reader接口
file, err := os.Open("test.txt")
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
// 函数结束后关闭文件
defer file.Close()
// 定义缓冲区,每次读取1024字节
buf := make([]byte, 1024)
for {
// 调用Read方法读取数据,n为实际读取的字节数
n, err := file.Read(buf)
if err != nil {
// 读取到文件末尾时err为io.EOF
if err == io.EOF {
break
}
fmt.Println("读取文件失败:", err)
return
}
// 处理读取到的数据
fmt.Print(string(buf[:n]))
}
}
使用io.ReadAll读取全部内容
如果文件较小,需要一次性读取全部内容,可以使用io.ReadAll方法:
package main
import (
"fmt"
"io"
"os"
)
func main() {
file, err := os.Open("test.txt")
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
// 读取文件全部内容
content, err := io.ReadAll(file)
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Println("文件内容:", string(content))
}
基础文件写入实现
写入文件需要先以写入模式打开文件,获取实现了io.Writer接口的文件对象,再调用Write方法写入数据。
写入字符串到文件
package main
import (
"fmt"
"io"
"os"
)
func main() {
// 以写入模式打开文件,如果文件不存在则创建,权限为0644
file, err := os.OpenFile("output.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
// 要写入的内容
content := "这是使用io包写入的文件内容"
// 将字符串转换为字节切片写入
n, err := io.WriteString(file, content)
if err != nil {
fmt.Println("写入文件失败:", err)
return
}
fmt.Printf("成功写入%d字节内容n", n)
}
使用io.Copy复制文件
io.Copy可以直接将一个Reader的数据复制到Writer中,非常适合实现文件复制功能:
package main
import (
"fmt"
"io"
"os"
)
func main() {
// 打开源文件
srcFile, err := os.Open("source.txt")
if err != nil {
fmt.Println("打开源文件失败:", err)
return
}
defer srcFile.Close()
// 创建目标文件
dstFile, err := os.OpenFile("dest.txt", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
fmt.Println("创建目标文件失败:", err)
return
}
defer dstFile.Close()
// 复制源文件内容到目标文件
written, err := io.Copy(dstFile, srcFile)
if err != nil {
fmt.Println("复制文件失败:", err)
return
}
fmt.Printf("成功复制%d字节内容n", written)
}
缓冲读写操作
如果需要频繁进行读写操作,可以使用bufio包配合io接口实现缓冲读写,减少系统调用次数,提升性能:
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
// 打开文件用于读写
file, err := os.OpenFile("buffer.txt", os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0644)
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
// 创建缓冲写入器,底层依赖io.Writer
writer := bufio.NewWriter(file)
// 写入数据到缓冲区
_, err = writer.WriteString("第一行内容n")
if err != nil {
fmt.Println("写入缓冲区失败:", err)
return
}
_, err = writer.WriteString("第二行内容n")
if err != nil {
fmt.Println("写入缓冲区失败:", err)
return
}
// 将缓冲区数据刷入文件
err = writer.Flush()
if err != nil {
fmt.Println("刷新缓冲区失败:", err)
return
}
// 将文件指针移到开头,准备读取
_, err = file.Seek(0, io.SeekStart)
if err != nil {
fmt.Println("移动文件指针失败:", err)
return
}
// 创建缓冲读取器,底层依赖io.Reader
reader := bufio.NewReader(file)
for {
// 按行读取内容
line, err := reader.ReadString('n')
if err != nil {
if err == io.EOF {
break
}
fmt.Println("读取文件失败:", err)
return
}
fmt.Print("读取到行:", line)
}
}
注意事项
- 文件操作完成后一定要及时关闭,避免资源泄漏,通常使用defer语句关闭文件
- 读取文件时要注意处理
io.EOF错误,这是文件读取结束的正常标识 - 写入文件时要根据需求选择合适的打开模式,比如追加模式需要添加
os.O_APPEND标志 - 大文件操作优先使用逐块读取的方式,避免内存占用过高