题
我一直在试图了解我自己去,但我已经难倒从试图读写普通文件。
我能得到尽可能inFile, _ := os.Open(INFILE, 0, 0)
,但实际上获得文件的内容没有意义,因为读功能需要一个[]byte
作为参数。
func (file *File) Read(b []byte) (n int, err Error)
解决方案
让我们做的一切在进入读写文件的方式围棋1兼容列表。
由于文件API最近已改变和大多数其他的答案不工作一起去他们还错过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.Open
和os.Create
其是围绕方便包装os.OpenFile
。我们通常并不需要直接调用OpenFile
。
注意治疗EOF。 Read
试图填补buf
在每次调用,并返回io.EOF
作为误差如果达到文件的末尾这样做。在这种情况下ioutil
仍将保存数据。因之调用<=>返回零的字节数读取相同<=>的错误。任何其它的错误将导致死机。
是<=> 强>
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)
}
}
<=>只是充当缓冲器这里,是因为我们没有太多的做数据。在大多数其他情况下(特别是与文本文件)<=>是给我们一个很好的API 非常有用一>用于读取和写入方便,灵活,而它处理幕后缓冲。
是<=> 强>
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.CopyN
和<=>可以为你服务好。如果您检查io.Copy功能的源,它是(实际上是“基本”一)打包在去图书馆不过是穆斯塔法的解决方案之一。他们正在使用一显著较大的缓冲区比他,虽然。
[]byte
is a slice (similar to a substring) of all or part of a byte array. Think of the slice as a value structure with a hidden pointer field for the system to locate and access all or part of an array (the slice), plus fields for the length and capacity of the slice, which you can access using the len()
and cap()
functions.
Here's a working starter kit for you, which reads and prints a binary file; you will need to change the inName
literal value to refer to a small file on your system.
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();
}
With newer Go versions, reading/writing to/from file is easy. To read from a file:
package main
import (
"fmt"
"io/ioutil"
)
func main() {
data, err := ioutil.ReadFile("text.txt")
if err != nil {
return
}
fmt.Println(string(data))
}
To write to a file:
package main
import "os"
func main() {
file, err := os.Create("text.txt")
if err != nil {
return
}
defer file.Close()
file.WriteString("test\nhello")
}
This will overwrite the content of a file (create a new file if it was not there).
Try this:
package main
import (
"io";
)
func main() {
contents,_ := io.ReadFile("filename");
println(string(contents));
io.WriteFile("filename", contents, 0644);
}
Just looking at the documentation it seems you should just declare a buffer of type []byte and pass it to read which will then read up to that many characters and return the number of characters actually read (and an error).
The docs say
Read reads up to len(b) bytes from the File. It returns the number of bytes read and an Error, if any. EOF is signaled by a zero count with err set to EOF.
Does that not work?
EDIT: Also, I think you should perhaps use the Reader/Writer interfaces declared in the bufio package instead of using os package.
The Read method takes a byte parameter because that is the buffer it will read into. It's a common Idiom in some circles and makes some sense when you think about it.
This way you can determine how many bytes will be read by the reader and inspect the return to see how many bytes actually were read and handle any errors appropriately.
As others have pointed in their answers bufio is probably what you want for reading from most files.
I'll add one other hint since it's really useful. Reading a line from a file is best accomplished not by the ReadLine method but the ReadBytes or ReadString method instead.