如何在Go中读取打包的二进制数据? [英] How to read packed binary data in 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 更新和工作 >
包主
pre
导入(
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)
}
}
解决方案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 attemptsUPDATE 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屋!