英文:
How to read a binary file in Go
问题
我完全不了解Go语言,我正在尝试逐字节或逐几个字节地读取二进制文件。文档没有提供太多帮助,我也找不到任何教程或简单的示例(顺便说一句,Google为什么给他们的语言取了一个难以搜索的名字?)。基本上,我应该如何打开一个文件,然后将一些字节读入缓冲区?有什么建议吗?
英文:
I'm completely new to Go and I'm trying to read a binary file, either byte by byte or several bytes at a time. The documentation doesn't help much and I cannot find any tutorial or simple example (by the way, how could Google give their language such an un-googlable name?). Basically, how can I open a file, then read some bytes into a buffer? Any suggestion?
答案1
得分: 31
用于操作文件的os
包是你的朋友:
f, err := os.Open("myfile")
if err != nil {
panic(err)
}
defer f.Close()
要更多地控制文件的打开方式,可以参考os.OpenFile()
(文档)。
对于读取文件,有很多种方法。os.Open
返回的os.File
类型(上面示例中的f
)实现了io.Reader
接口(它有一个正确签名的Read()
方法),可以直接用来读取一些数据到缓冲区(一个[]byte
),或者可以包装在一个带缓冲的读取器(类型为bufio.Reader
)中。
特别针对二进制数据,encoding/binary
包可能会有用,可以将一系列字节读取到某种类型化的数据结构中。你可以在这里的Go文档中看到一个示例。binary.Read()
函数可以与使用os.Open()
函数读取的文件一起使用,因为如我所提到的,它是一个io.Reader
。
还有一个简单易用的io/ioutil
包,它允许你一次性读取整个文件到一个字节切片中(ioutil.ReadFile()
,它接受一个文件名,所以你甚至不需要自己打开/关闭文件),或者ioutil.ReadAll()
,它接受一个io.Reader
并返回一个包含整个文件的字节切片。这里是ioutil的文档。
最后,正如其他人提到的,你可以使用"golang"来搜索关于Go语言的信息,你应该能找到你需要的一切。golang-nuts邮件列表也是寻找答案的好地方(在发帖之前先搜索一下,很多问题已经有答案了)。要查找第三方包,可以查看godoc.org网站。
希望对你有帮助。
英文:
For manipulating files, the os
package is your friend:
f, err := os.Open("myfile")
if err != nil {
panic(err)
}
defer f.Close()
For more control over how the file is open, see os.OpenFile()
instead (doc).
For reading files, there are many ways. The os.File
type returned by os.Open
(the f
in the above example) implements the io.Reader
interface (it has a Read()
method with the right signature), it can be used directly to read some data in a buffer (a []byte
) or it can also be wrapped in a buffered reader (type bufio.Reader
).
Specifically for binary data, the encoding/binary
package can be useful, to read a sequence of bytes into some typed structure of data. You can see an example in the Go doc here. The binary.Read()
function can be used with the file read using the os.Open()
function, since as I mentioned, it is a io.Reader
.
And there's also the simple to use io/ioutil
package, that allows you to read the whole file at once in a byte slice (ioutil.ReadFile()
, which takes a file name, so you don't even have to open/close the file yourself), or ioutil.ReadAll()
which takes a io.Reader
and returns a slice of bytes containing the whole file. Here's the doc on ioutil.
Finally, as others mentioned, you can google about the Go language using "golang" and you should find all you need. The golang-nuts mailing list is also a great place to look for answers (make sure to search first before posting, a lot of stuff has already been answered). To look for third-party packages, check the godoc.org website.
HTH
答案2
得分: 19
这是我用来将整个二进制文件读入内存的方法
func RetrieveROM(filename string) ([]byte, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
stats, statsErr := file.Stat()
if statsErr != nil {
return nil, statsErr
}
var size int64 = stats.Size()
bytes := make([]byte, size)
bufr := bufio.NewReader(file)
_,err = bufr.Read(bytes)
return bytes, err
}
英文:
This is what I use to read an entire binary file into memory
func RetrieveROM(filename string) ([]byte, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
stats, statsErr := file.Stat()
if statsErr != nil {
return nil, statsErr
}
var size int64 = stats.Size()
bytes := make([]byte, size)
bufr := bufio.NewReader(file)
_,err = bufr.Read(bytes)
return bytes, err
}
答案3
得分: 10
例如,要计算文件中零字节的数量:
package main
import (
"fmt"
"io"
"os"
)
func main() {
f, err := os.Open("filename")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
data := make([]byte, 4096)
zeroes := 0
for {
data = data[:cap(data)]
n, err := f.Read(data)
if err != nil {
if err == io.EOF {
break
}
fmt.Println(err)
return
}
data = data[:n]
for _, b := range data {
if b == 0 {
zeroes++
}
}
}
fmt.Println("zeroes:", zeroes)
}
英文:
For example, to count the number of zero bytes in a file:
package main
import (
"fmt"
"io"
"os"
)
func main() {
f, err := os.Open("filename")
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
data := make([]byte, 4096)
zeroes := 0
for {
data = data[:cap(data)]
n, err := f.Read(data)
if err != nil {
if err == io.EOF {
break
}
fmt.Println(err)
return
}
data = data[:n]
for _, b := range data {
if b == 0 {
zeroes++
}
}
}
fmt.Println("zeroes:", zeroes)
}
答案4
得分: 3
你不能像在C语言中那样随意地将原始类型转换为(char*),所以对于任何二进制数据的(反)序列化,请使用encoding/binary包。
http://golang.org/pkg/encoding/binary。
我无法改进那里的示例。
英文:
You can't whimsically cast primitive types to (char*) like in C, so for any sort of (de)serializing of binary data use the encoding/binary package.
http://golang.org/pkg/encoding/binary .
I can't improve on the examples there.
答案5
得分: 0
这里是使用Read
方法的一个示例:
package main
import (
"io"
"os"
)
func main() {
f, e := os.Open("a.go")
if e != nil {
panic(e)
}
defer f.Close()
for {
b := make([]byte, 10)
_, e = f.Read(b)
if e == io.EOF {
break
} else if e != nil {
panic(e)
}
// 在这里做一些操作
}
}
https://golang.org/pkg/os#File.Read
英文:
Here is an example using Read
method:
package main
import (
"io"
"os"
)
func main() {
f, e := os.Open("a.go")
if e != nil {
panic(e)
}
defer f.Close()
for {
b := make([]byte, 10)
_, e = f.Read(b)
if e == io.EOF {
break
} else if e != nil {
panic(e)
}
// do something here
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论