如何在Go中读取打包的二进制数据? [英] How to read packed binary data in Go?

查看:471
本文介绍了如何在Go中读取打包的二进制数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 <$> 

我试图找出最佳方式来阅读由Python制作的Go中的打包二进制文件,如下所示: c $ c> import struct
f = open('tst.bin','wb')
fmt ='iih'#please note this packed is binary:4byte int,4byte int,2byte int
f.write(struct.pack(fmt,4,185765,1020))
f.write(struct.pack(fmt,4,185765,1022))
f.close()

我一直在修改我在Github.com上看到的一些例子和其他一些资源但我似乎无法正常工作(更新显示工作方法)。 在Go中做这种事情的习惯用法是什么?这是几次尝试之一


$ b 更新和工作 >

 包主

导入(
fmt
os
encoding / binary
io


func main(){
fp,err:= os.Open( )

if err!= nil
lineBuf:= make([] byte,10)// 4字节int,4字节int,每行2字节int

for true {
_,err:=如果错误== io.EOF {
break
}

aVal:= int32(binary.LittleEndian.Uint32 (lineBuf [0:4]))//相同:int32(uint32(b [0])| uint32(b [1])<8 | uint32(b [2])<= 16 | ü int32(b [3])<24>
bVal:= int32(binary.LittleEndian.Uint32(lineBuf [4:8]))
cVal:= int16(binary.LittleEndian.Uint16 (lineBuf [8:10]))//同:int16(uint32(b [0])|) uint32(b [1])<8)
fmt.Println(aVal,bVal,cVal)
}
}
pre

解决方案

Python格式字符串是 iih 位有符号整数和一个16位有符号整数(请参阅文档)。您可以简单地使用第一个示例,但将结构更改为:

 类型binData结构{
A int32
b int32
C int16
}

func main(){
fp,err:= os.Open(tst.bin)

if err!= nil {
panic(err)
}

推迟fp.Close()

为{
事物:= binData {}
err:= binary.Read(fp,binary.LittleEndian,& thing)

if err == io.EOF {
break


fmt.Println(thing.A,thing.B,thing.C)
}
}

请注意,Python包装没有明确指定字节序,但是如果您确定运行它的系统生成了小端二进制文件, 。



编辑:添加 main()函数来解释我的意思。 / p>

编辑2:大写的结构体字段,所以 binary.Read 可以写入它们。


I'm trying to figure out the best way to read a packed binary file in Go that was produced by Python like the following:

import struct
f = open('tst.bin', 'wb')
fmt = 'iih' #please note this is packed binary: 4byte int, 4byte int, 2byte int
f.write(struct.pack(fmt,4, 185765, 1020))
f.write(struct.pack(fmt,4, 185765, 1022))
f.close()

I have been tinkering with some of the examples I've seen on Github.com and a few other sources but I can't seem to get anything working correctly (update shows working method). What is the idiomatic way to do this sort of thing in Go? This is one of several attempts

UPDATE and WORKING

package main

    import (
            "fmt"
            "os"
            "encoding/binary"
            "io"
            )

    func main() {
            fp, err := os.Open("tst.bin")

            if err != nil {
                    panic(err)
            }

            defer fp.Close()

            lineBuf := make([]byte, 10) //4 byte int, 4 byte int, 2 byte int per line

            for true {
                _, err := fp.Read(lineBuf)

                if err == io.EOF{
                    break
                }

                aVal := int32(binary.LittleEndian.Uint32(lineBuf[0:4])) // same as: int32(uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24)
                bVal := int32(binary.LittleEndian.Uint32(lineBuf[4:8]))
                cVal := int16(binary.LittleEndian.Uint16(lineBuf[8:10])) //same as: int16(uint32(b[0]) | uint32(b[1])<<8)
                fmt.Println(aVal, bVal, cVal)
            }
    }

解决方案

The Python format string is iih, meaning two 32-bit signed integers and one 16-bit signed integer (see the docs). You can simply use your first example but change the struct to:

type binData struct {
    A int32
    B int32
    C int16
}

func main() {
        fp, err := os.Open("tst.bin")

        if err != nil {
                panic(err)
        }

        defer fp.Close()

        for {
            thing := binData{}
            err := binary.Read(fp, binary.LittleEndian, &thing)

            if err == io.EOF{
                break
            }

            fmt.Println(thing.A, thing.B, thing.C)
        }
}

Note that the Python packing didn't specify the endianness explicitly, but if you're sure the system that ran it generated little-endian binary, this should work.

Edit: Added main() function to explain what I mean.

Edit 2: Capitalized struct fields so binary.Read could write into them.

这篇关于如何在Go中读取打包的二进制数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆