File Operations.
About 777 wordsAbout 3 min
Golang
2024-11-8
概述
本章节讲述go
操作文件的方式。
读写文件
在 Go 语言中,文件使用指向 os.File
类型的指针来表示的,也叫做文件句柄。我们在前面章节使用到过标准输入 os.Stdin
和标准输出 os.Stdout
,他们的类型都是 *os.File
。
package main
import (
"bufio"
"fmt"
"io"
"os"
)
func main() {
inputFile, inputError := os.Open("input.dat")
if inputError != nil {
fmt.Printf("An error occurred on opening the inputfile\n" +
"Does the file exist?\n" +
"Have you got acces to it?\n")
return // exit the function on error
}
defer inputFile.Close()
// 将文件转换为bufio的Reader对象
// 按行读取文件
inputReader := bufio.NewReader(inputFile)
for {
inputString, readerError := inputReader.ReadString('\n')
fmt.Printf("The input was: %s", inputString)
if readerError == io.EOF {
return
}
}
}
将整个文件读取到一个串
可以使用 io/ioutil
包里的 ioutil.ReadFile()
方法,该方法第一个返回值的类型是 []byte
,里面存放读取到的内容,第二个返回值是错误,如果没有错误发生,第二个返回值为 nil。类似的,函数 WriteFile()
可以将 []byte
的值写入文件。
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
inputFile := "products.txt"
outputFile := "products_copy.txt"
// buf是一个 []byte 对象
buf, err := ioutil.ReadFile(inputFile)
if err != nil {
fmt.Fprintf(os.Stderr, "File Error: %s\n", err)
// panic(err.Error())
}
fmt.Printf("%s\n", string(buf))
err = ioutil.WriteFile(outputFile, buf, 0644) // oct, not hex
if err != nil {
panic(err.Error())
}
}
带缓冲读取
在很多情况下,文件的内容是不按行划分的,或者干脆就是一个二进制文件。在这种情况下,ReadString()
就无法使用了,我们可以使用 bufio.Reader
的 Read()
,它只接收一个参数:
buf := make([]byte, 1024)
...
// 类似的函数还有 ReadFull 等等,以控制对缓冲区的使用
n, err := inputReader.Read(buf)
if (n == 0) { break}
变量 n 的值表示读取到的字节数.
读取压缩包
compress
包提供了读取压缩文件的功能,支持的压缩文件格式为:bzip2
、flate
、gzip
、lzw
和 zlib
。
下面的程序展示了如何读取一个gzip
文件。
package main
import (
"fmt"
"bufio"
"os"
"compress/gzip"
)
func main() {
fName := "MyFile.gz"
var r *bufio.Reader
fi, err := os.Open(fName)
if err != nil {
fmt.Fprintf(os.Stderr, "%v, Can't open %s: error: %s\n", os.Args[0], fName, err)
os.Exit(1)
}
defer fi.Close()
fz, err := gzip.NewReader(fi)
if err != nil {
r = bufio.NewReader(fi)
} else {
r = bufio.NewReader(fz)
}
for {
line, err := r.ReadString('\n')
if err != nil {
fmt.Println("Done reading file")
os.Exit(0)
}
fmt.Println(line)
}
}
写文件
package main
import (
"os"
"bufio"
"fmt"
)
func main () {
// var outputWriter *bufio.Writer
// var outputFile *os.File
// var outputError os.Error
// var outputString string
outputFile, outputError := os.OpenFile("output.dat", os.O_WRONLY|os.O_CREATE, 0666)
if outputError != nil {
fmt.Printf("An error occurred with file opening or creation\n")
return
}
defer outputFile.Close()
outputWriter := bufio.NewWriter(outputFile)
outputString := "hello world!\n"
for i:=0; i<10; i++ {
outputWriter.WriteString(outputString)
}
// 讲缓冲区的内容写入文件
outputWriter.Flush()
}
果写入的东西很简单,我们可以使用 fmt.Fprintf(outputFile, "Some test data.\n")
直接将内容写入文件。fmt
包里的 F 开头的 Print 函数可以直接写入任何 io.Writer
,包括文件。
不使用缓冲区
package main
import "os"
func main() {
os.Stdout.WriteString("hello, world\n")
f, _ := os.OpenFile("test", os.O_CREATE|os.O_WRONLY, 0666)
defer f.Close()
f.WriteString("hello, world in a file\n")
}
文件拷贝
// filecopy.go
package main
import (
"fmt"
"io"
"os"
)
func main() {
CopyFile("target.txt", "source.txt")
fmt.Println("Copy done!")
}
// safe copy function
func CopyFile(dstName, srcName string) (written int64, err error) {
src, err := os.Open(srcName)
if err != nil {
return
}
defer src.Close()
dst, err := os.Create(dstName)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}