【问题标题】:How to read a binary file in Go如何在 Go 中读取二进制文件
【发布时间】:2013-01-08 23:13:53
【问题描述】:

我对 Go 完全陌生,我正在尝试读取一个二进制文件,一次一个字节或几个字节。文档没有多大帮助,我找不到任何教程或简单的例子(顺便说一句,谷歌怎么会给他们的语言起这样一个不可搜索的名字?)。基本上,我怎样才能打开一个文件,然后将一些字节读入缓冲区?有什么建议吗?

【问题讨论】:

标签: file-io go


【解决方案1】:

对于操作文件,os 包是你的朋友:

f, err := os.Open("myfile")
if err != nil {
   panic(err)
}
defer f.Close()

如需更多控制文件的打开方式,请参阅os.OpenFile() 而不是(doc)

对于读取文件,有很多方法。 os.Open返回的os.File类型(上例中的f)实现了io.Reader接口(它有一个Read()方法,签名正确),可以直接用来读取里面的一些数据一个缓冲区(a []byte)或者它也可以包装在一个缓冲的阅读器中(类型bufio.Reader)。

对于二进制数据,encoding/binary 包非常有用,可以将字节序列读入某种类型化的数据结构中。您可以在Go doc here 中查看示例。 binary.Read() 函数可以与使用os.Open() 函数读取的文件一起使用,因为正如我所提到的,它是一个io.Reader

还有一个简单易用的io/ioutil 包,它允许你在一个字节片中一次读取整个文件(ioutil.ReadFile(),它需要一个文件名,所以你甚至不必打开/自己关闭文件),或ioutil.ReadAll() 接受io.Reader 并返回包含整个文件的字节切片。这是doc on ioutil

最后,正如其他人所提到的,您可以使用“golang”在 Google 上搜索有关 Go 语言的信息,您应该会找到所需的一切。 golang-nuts mailing list 也是一个寻找答案的好地方(发帖前一定要先搜索一下,很多东西已经有答案了)。要查找第三方软件包,请查看godoc.org 网站。

HTH

【讨论】:

    【解决方案2】:

    例如,计算文件中零字节的数量:

    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)
    }
    

    【讨论】:

      【解决方案3】:

      这是我用来将整个二进制文件读入内存的方法

      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
      }
      

      【讨论】:

      • 为什么不直接使用 Go io/ioutil 包中的 func ReadFile(filename string) ([]byte, error)
      • @djhworld 很有趣,我现在正在用 Go 编写一个模拟器,在谷歌搜索二进制文件后偶然发现了你的答案;)
      【解决方案4】:

      您不能像在 C 中那样异想天开地将原始类型转换为 (char*),因此对于二进制数据的任何类型的(反)序列化,请使用 encoding/binary 包。 http://golang.org/pkg/encoding/binary 。 我无法改进那里的示例。

      【讨论】:

        【解决方案5】:

        这里是一个使用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)
              }
              // do something here
           }
        }
        

        https://golang.org/pkg/os#File.Read

        【讨论】:

          猜你喜欢
          • 2019-04-10
          • 1970-01-01
          • 1970-01-01
          • 2011-01-26
          • 2016-03-08
          • 1970-01-01
          • 2013-02-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多