Go语言中,文件的读写操作有很多种方式。比如以二进制字节码byte方式读取写入,亦或将整个文件的内容读入内存之类的方法。从实用角度上来说,为了避免文件过大把内存吃满,按行读取string字符串的方式最为常见。同样以string类型写入文件也是通用的方法。
创建一个txt文件
% cat config.txt
113 334 556
113 324 589
115 331 557
456 213 509
按行读取文件方法一(bufio.NewReader)
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings" // 注意是strings包,不是string包
)
func main() {
// 获取文件句柄
f, err := os.Open("config.txt")
// 最后要记得关闭文件
defer func() {
if err := f.Close(); err != nil {
fmt.Println("文件打开错误")
}
}()
if err != nil {
fmt.Println(err)
}
// 实例化bufio接口,传入句柄文件
buf := bufio.NewReader(f)
for {
// 循环读取文件内容,每次读取一行
// 以回车为一行结束的标志按行读取文件,返回值是string类型
line, err := buf.ReadString('\n') // 注意这里传入的分隔符是[]byte字节类型格式,必须使用单引号
//if err != nil { // 遇到错误
// fmt.Println(err)
// fmt.Println("文件读取错误")
// break
if err == io.EOF { //读到最后一行遇到结尾,正常切割字符串
//遇到io.EOF则表示文件最后一个字符读完,即最后一行内容的结尾。
// io.EOF可以看做是对文件最后一行内容的处理步骤
// 这一点比较特殊,要特别处理一下最后一行内容的收集操作,不然最后一行就被丢弃了
LineSlice := strings.Split(strings.Trim(line, "\n"), " ")
fmt.Printf("%v\n", LineSlice)
break
} else if err != nil { // 遇到其他错误
fmt.Println(err)
fmt.Println("文件读取错误")
break
} else { // 没遇到 结尾或错误,正常切割字符串
// strings.Trim(line, "\n") 去除每行字符串中的换行符
// strings.Split(line, " ") 以空格<" ">做为分割付,切割字符串,返回slice
LineSlice := strings.Split(strings.Trim(line, "\n"), " ")
fmt.Printf("%v\n", LineSlice)
}
}
}
执行结果,每一行都被存入一个切片之中
% go run main.go
[113 334 556]
[113 324 589]
[115 331 557]
[456 213 509]
按行读取文件方法二(bufio.NewScanner)
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
f, err := os.Open("config.txt")
defer func() {
if err := f.Close(); err != nil {
fmt.Println(err)
}
}()
if err != nil {
fmt.Println(err)
}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
stringList := strings.Split(line, " ")
fmt.Println(stringList)
}
}
运行结果是一样的,明显方法二的代码更为简洁
% go run main.go
[113 334 556]
[113 324 589]
[115 331 557]
[456 213 509]
按行写入文件
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
//OpenFile操作操作符:
//O_RDONLY:只读模式打开文件;
//O_WRONLY:只写模式打开文件;
//O_RDWR:读写模式打开文件;
//O_APPEND:写操作时将数据附加到文件尾部(追加);
//O_CREATE:如果不存在将创建一个新文件;
//O_EXCL:和 O_CREATE 配合使用,文件必须不存在,否则返回一个错误;
//O_SYNC:当进行一系列写操作时,每次都要等待上次的 I/O 操作完成再进行;
//O_TRUNC:如果可能,在打开时清空文件。
// 文件不存在就创建并打开写模式,文件存在就打开追加模式
f, err := os.OpenFile("config.txt", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
defer f.Close()
if err != nil {
fmt.Println("文件打开失败")
}
// 实例化NewWriter()方法
writer := bufio.NewWriter(f)
// 在原文件后追加一个回车符
if _, err := writer.WriteString("\n"); err != nil {
fmt.Println("写入文件缓存失败")
}
// 写入5行字符串
for i := 1; i < 6; i++ {
str := fmt.Sprintf("写入第< %d >行内容\n", i)
fmt.Printf("%s", str)
// 把内容写入缓存
// 返回写入的写入文件长度和写入结果
if _, err := writer.WriteString(str); err != nil {
fmt.Println("写入文件缓存失败")
break
}
// 把缓存刷入磁盘
if err := writer.Flush(); err != nil {
fmt.Println("缓存内容写入磁盘失败")
break
}
}
}
查看写入文件的效果
% cat config.txt
113 334 556
113 324 589
115 331 557
456 213 509
写入第< 1 >行内容
写入第< 2 >行内容
写入第< 3 >行内容
写入第< 4 >行内容
写入第< 5 >行内容