文件读写基础 #
文件操作是程序与外部世界交互的重要方式。Go语言提供了多种文件读写方法,从简单便捷的函数到精细控制的操作。
读取整个文件 #
使用 os.ReadFile #
最简单的读取文件方式是使用 os.ReadFile,它一次性读取整个文件内容:
go
package main
import (
"fmt"
"os"
)
func main() {
content, err := os.ReadFile("example.txt")
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Println("文件内容:")
fmt.Println(string(content))
}
os.ReadFile 返回字节切片 []byte,需要转换为字符串显示。
使用 io/ioutil 包 #
在Go 1.16之前,ioutil.ReadFile 是常用方法:
go
package main
import (
"fmt"
"io/ioutil"
)
func main() {
content, err := ioutil.ReadFile("example.txt")
if err != nil {
fmt.Println("读取文件失败:", err)
return
}
fmt.Println(string(content))
}
注意: 从Go 1.16开始,
ioutil.ReadFile已被废弃,建议使用os.ReadFile。
写入文件 #
使用 os.WriteFile #
写入文件最简单的方法是使用 os.WriteFile:
go
package main
import (
"fmt"
"os"
)
func main() {
content := []byte("Hello, Go文件写入!\n这是第二行内容。")
err := os.WriteFile("output.txt", content, 0644)
if err != nil {
fmt.Println("写入文件失败:", err)
return
}
fmt.Println("文件写入成功!")
}
文件权限 0644 表示:
- 所有者:读写权限 (6 = 4+2)
- 组:读权限 (4)
- 其他:读权限 (4)
打开文件进行读写 #
使用 os.Open 只读打开 #
go
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
buf := make([]byte, 1024)
n, err := file.Read(buf)
if err != nil {
fmt.Println("读取失败:", err)
return
}
fmt.Printf("读取了 %d 字节\n", n)
fmt.Println(string(buf[:n]))
}
使用 os.OpenFile 自定义模式 #
os.OpenFile 提供更灵活的文件打开方式:
go
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.OpenFile("example.txt", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
_, err = file.WriteString("\n追加的新内容")
if err != nil {
fmt.Println("写入失败:", err)
return
}
fmt.Println("内容追加成功!")
}
常用文件打开标志:
| 标志 | 说明 |
|---|---|
os.O_RDONLY |
只读模式 |
os.O_WRONLY |
只写模式 |
os.O_RDWR |
读写模式 |
os.O_CREATE |
文件不存在则创建 |
os.O_APPEND |
追加模式 |
os.O_TRUNC |
打开时清空文件 |
os.O_EXCL |
与O_CREATE一起使用,文件必须不存在 |
使用 bufio 进行缓冲读写 #
缓冲读写可以提高I/O性能,特别适合处理大文件:
缓冲读取 #
go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
scanner := bufio.NewScanner(file)
lineNum := 1
for scanner.Scan() {
fmt.Printf("第%d行: %s\n", lineNum, scanner.Text())
lineNum++
}
if err := scanner.Err(); err != nil {
fmt.Println("读取错误:", err)
}
}
缓冲写入 #
go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
file, err := os.Create("output.txt")
if err != nil {
fmt.Println("创建文件失败:", err)
return
}
defer file.Close()
writer := bufio.NewWriter(file)
for i := 1; i <= 5; i++ {
_, err := writer.WriteString(fmt.Sprintf("第%d行内容\n", i))
if err != nil {
fmt.Println("写入失败:", err)
return
}
}
writer.Flush()
fmt.Println("写入完成!")
}
重要: 使用
bufio.Writer时,必须调用Flush()方法确保所有数据写入文件。
使用 io.Copy 复制文件 #
go
package main
import (
"fmt"
"io"
"os"
)
func main() {
src, err := os.Open("source.txt")
if err != nil {
fmt.Println("打开源文件失败:", err)
return
}
defer src.Close()
dst, err := os.Create("destination.txt")
if err != nil {
fmt.Println("创建目标文件失败:", err)
return
}
defer dst.Close()
copied, err := io.Copy(dst, src)
if err != nil {
fmt.Println("复制失败:", err)
return
}
fmt.Printf("复制了 %d 字节\n", copied)
}
读取特定位置 #
使用 Seek 方法可以定位文件读写位置:
go
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
fmt.Println("打开文件失败:", err)
return
}
defer file.Close()
offset, err := file.Seek(10, 0)
if err != nil {
fmt.Println("定位失败:", err)
return
}
fmt.Printf("当前位置: %d\n", offset)
buf := make([]byte, 20)
n, _ := file.Read(buf)
fmt.Println(string(buf[:n]))
}
Seek 的第二个参数表示起始位置:
0- 文件开头1- 当前位置2- 文件末尾
实用示例:统计文件行数 #
go
package main
import (
"bufio"
"fmt"
"os"
)
func countLines(filename string) (int, error) {
file, err := os.Open(filename)
if err != nil {
return 0, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
count := 0
for scanner.Scan() {
count++
}
return count, scanner.Err()
}
func main() {
count, err := countLines("example.txt")
if err != nil {
fmt.Println("错误:", err)
return
}
fmt.Printf("文件共有 %d 行\n", count)
}
小结 #
| 方法 | 适用场景 | 特点 |
|---|---|---|
os.ReadFile |
小文件读取 | 简单便捷,一次性读取 |
os.WriteFile |
小文件写入 | 简单便捷,覆盖写入 |
os.Open |
只读操作 | 需要手动管理 |
os.OpenFile |
复杂文件操作 | 灵活控制打开模式 |
bufio |
大文件处理 | 缓冲提高性能 |
io.Copy |
文件复制 | 高效复制 |
选择合适的文件读写方法取决于具体需求。小文件可以使用便捷函数,大文件推荐使用缓冲读写。