在Go
语言中,一切均可视为文件,一切均可视为字节流。本文主要介绍文件读取/写入的几种方法。
文件读取是所有编程语言中最常见的操作之一。在实际项目的开发中,需要将大量的配置信息放在配置文件中,而不是硬编码到程序中,这样就可以根据实际情况灵活地进行调整,方便项目的部署。
在Go
语言中,读取文件的常用方式有三种:
代码如下:
package main
import (
"log"
"os"
)
func main() {
content, err := os.ReadFile("example.txt")
if err != nil {
log.Fatal(err)
}
log.Println("文件内容:", string(content))
}
代码如下:
package main
import (
"bufio"
"io"
"log"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
r := bufio.NewReader(file)
buffer := make([]byte, 1024)
for {
n, err := r.Read(buffer)
if err != nil {
if err == io.EOF {
break
}
log.Fatal(err)
}
// 分字节读取文件时,最后打印的时候应该调用string(buffer[:n])而不是调用string(buffer)来获取读取到的值,否则可能会打印出额外的字节。
log.Println("读取到的字节数:", n)
log.Println("读取到的内容:", string(buffer[:n]))
}
}
bufio
包实现了带缓存的I/O
操作,它封装了一个io.Reader
和io.Writer
对象,使其具有缓存和一些文本读写功能。把文件读取进缓冲之后再读取的时候就可以避免文件系统的I/O
读写,从而提高速度。代码如下:
package main
import (
"bufio"
"log"
"os"
)
func main() {
file, err := os.Open("example.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
log.Println("读取到的内容:", scanner.Text())
}
}
和文件读取操作类似,Go
语言中,写入文件的常用方式有以下三种:
当写入的内容不是很大时,最常见的写入方法就是将字符串整块写入到文件中,这种方法也是最简单的。
代码如下:
package main
import (
"log"
"os"
)
func main() {
f, err := os.Create("example.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
n, err := f.WriteString("Hello, world!")
if err != nil {
log.Fatal(err)
}
log.Println("写入的字节数:", n)
}
os.Create
方法不是以追加模式打开文件,如果将os.Create
方法用于已存在的文件,则会将文件的内容清空。将字符串整体写入文件虽然非常简单,但是如果要写入的内容非常大,那么可能会出现内存不足的问题。同样的,我们可以按字节写入文件,这样就相当于把大量内容分批写入到文件中。
代码如下:
package main
import (
"log"
"os"
)
func main() {
f, err := os.Create("example.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
content := []byte("Hello, world!")
i := 0
byteLen := 1024
for {
if i*byteLen > len(content) {
break
}
start, end := i*byteLen, (i+1)*byteLen
if (i+1)*byteLen > len(content) {
start, end = i*byteLen, len(content)
}
n, err := f.Write(content[start:end])
if err != nil {
log.Fatal(err)
}
i++
log.Println("写入的字节数:", n)
}
log.Println("写入完成")
}
Write
方法分字节数写入时,由于内容的长度不一定就是每批字节数的整数倍,因此最后一个字节切片需要进行特殊处理,否则写入的内容可能有额外的字节。代码如下:
package main
import (
"fmt"
"log"
"os"
)
func main() {
f, err := os.Create("example.txt")
if err != nil {
log.Fatal(err)
}
defer f.Close()
arr := []string{
"Hello World",
"Hello Golang",
}
for _, line := range arr {
n, err := fmt.Fprintln(f, line)
if err != nil {
log.Fatal(err)
}
log.Println("写入的字节数:", n)
log.Println("写入的内容:", line)
}
log.Println("写入完成")
}
f, err := os.OpenFile("example.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666)
。文中代码已上传至Github