如何使用Go读/写文件?

我一直在努力学习去,但我一直试图读取和写入普通文件。

我可以得到尽可能inFile, _ := os.Open(INFILE, 0, 0) ,但实际上获取文件的内容是没有意义的,因为读取函数采用[]byte作为参数。

 func (file *File) Read(b []byte) (n int, err Error) 

让我们制作一个Go 1兼容的列表,用于在Go中读取和写入文件。

由于文件API最近已经改变,大多数其他答案不适用于Go 1.他们也错过了重要的恕我直言bufio

在以下示例中,我通过读取文件并写入目标文件来复制文件。

从基础开始

 package main import ( "io" "os" ) func main() { // open input file fi, err := os.Open("input.txt") if err != nil { panic(err) } // close fi on exit and check for its returned error defer func() { if err := fi.Close(); err != nil { panic(err) } }() // open output file fo, err := os.Create("output.txt") if err != nil { panic(err) } // close fo on exit and check for its returned error defer func() { if err := fo.Close(); err != nil { panic(err) } }() // make a buffer to keep chunks that are read buf := make([]byte, 1024) for { // read a chunk n, err := fi.Read(buf) if err != nil && err != io.EOF { panic(err) } if n == 0 { break } // write a chunk if _, err := fo.Write(buf[:n]); err != nil { panic(err) } } } 

在这里我使用了os.Openos.Create ,它们是os.Create方便的包装器。 我们通常不需要直接调用OpenFile

注意处理EOF。 Read试图在每次调用时填充buf ,并且如果到达文件结尾,则返回io.EOF作为错误。 在这种情况下, buf仍然会保存数据。 随后对Read调用将返回零作为读取的字节数,并且与错误相同的io.EOF 。 任何其他错误将导致恐慌。

使用bufio

 package main import ( "bufio" "io" "os" ) func main() { // open input file fi, err := os.Open("input.txt") if err != nil { panic(err) } // close fi on exit and check for its returned error defer func() { if err := fi.Close(); err != nil { panic(err) } }() // make a read buffer r := bufio.NewReader(fi) // open output file fo, err := os.Create("output.txt") if err != nil { panic(err) } // close fo on exit and check for its returned error defer func() { if err := fo.Close(); err != nil { panic(err) } }() // make a write buffer w := bufio.NewWriter(fo) // make a buffer to keep chunks that are read buf := make([]byte, 1024) for { // read a chunk n, err := r.Read(buf) if err != nil && err != io.EOF { panic(err) } if n == 0 { break } // write a chunk if _, err := w.Write(buf[:n]); err != nil { panic(err) } } if err = w.Flush(); err != nil { panic(err) } } 

bufio只是在这里作为一个缓冲区,因为我们没有太多的数据。 在大多数其他情况下(特别是文本文件), bufio通过给我们一个很好的API来读写,它可以轻松灵活地处理,而在后台处理缓冲。

使用ioutil

 package main import ( "io/ioutil" ) func main() { // read the whole file at once b, err := ioutil.ReadFile("input.txt") if err != nil { panic(err) } // write the whole body at once err = ioutil.WriteFile("output.txt", b, 0644) if err != nil { panic(err) } } 

易如反掌! 但是只有在确定你不处理大文件的情况下才能使用它。

这是好的版本:

 package main import ( "io/ioutil"; ) func main() { contents,_ := ioutil.ReadFile("plikTekstowy.txt") println(string(contents)) ioutil.WriteFile("filename", contents, 0644) } 

使用io.Copy

 package main import ( "io" "log" "os" ) func main () { // open files r and w r, err := os.Open("input.txt") if err != nil { panic(err) } defer r.Close() w, err := os.Create("output.txt") if err != nil { panic(err) } defer w.Close() // do the actual work n, err := io.Copy(w, r) if err != nil { panic(err) } log.Printf("Copied %v bytes\n", n) } 

如果你不想重新发明轮子, io.Copyio.CopyN可以很好地为你服务。 如果你检查 io.Copy函数的源代码 ,它就是在Go库中打包的Mostafa解决scheme(实际上是“基本”的解决scheme)之一。 不过,他们正在使用比他大得多的缓冲区。

[]byte是全部或部分字节数组的片(类似于子string)。 将切片想象成一个带有隐藏指针字段的值结构,以便系统定位和访问数组(切片)的全部或部分,以及切片的长度和容量的字段,您可以使用len()cap()函数。

这里有一个适合你的工作入门套件,可以读取和打印二进制文件; 您将需要更改inName文字值以引用系统上的小文件。

 package main import ( "fmt"; "os"; ) func main() { inName := "file-rw.bin"; inPerm := 0666; inFile, inErr := os.Open(inName, os.O_RDONLY, inPerm); if inErr == nil { inBufLen := 16; inBuf := make([]byte, inBufLen); n, inErr := inFile.Read(inBuf); for inErr == nil { fmt.Println(n, inBuf[0:n]); n, inErr = inFile.Read(inBuf); } } inErr = inFile.Close(); } 

尝试这个:

 package main import ( "io"; ) func main() { contents,_ := io.ReadFile("filename"); println(string(contents)); io.WriteFile("filename", contents, 0x644); } 

哪个新的Go版本,读/写文件很容易。 从文件读取:

 package main import ( "fmt" "io/ioutil" ) func main() { data, err := ioutil.ReadFile("text.txt") if err != nil { return } fmt.Println(string(data)) } 

写入文件:

 package main import "os" func main() { file, err := os.Create("text.txt") if err != nil { return } defer file.Close() file.WriteString("test\nhello") } 

这将覆盖文件的内容(如果不存在,则创build一个新文件)。

看看这个文档,你应该只是声明一个types为[]的缓冲区,然后传给它读取,然后读取那么多字符,并返回实际读取的字符数(以及一个错误)。

文档说

Read从文件读取len(b)个字节。 它返回读取的字节数和一个错误,如果有的话。 EOF通过零计数发送,err设置为EOF。

这不行吗?

编辑:另外,我想你也许应该使用bufio包中声明的Reader / Writer接口,而不是使用os包。

Read方法需要一个字节参数,因为那是它将读入的缓冲区。 在一些圈子里,这是一个普通的成语,当你思考这个问题的时候,它是有道理的。

通过这种方式,您可以确定读取器将读取多less个字节,并检查返回结果,以查看实际读取的字节数,并适当地处理任何错误。

正如其他人指出他们的答案bufio可能是你想要从大多数文件阅读。

我会添加一个其他提示,因为它非常有用。 从文件中读取一行最好不要使用ReadLine方法,而要使用ReadBytes或ReadString方法。