英文:
What is the idiomatic way to write a packed binary file in Go that would produce the same output as this Python?
问题
我正在尝试弄清楚如何以Go语言编写与以下Python代码相对应的二进制文件的最佳方法:
import struct
f = open('tst.bin', 'wb')
fmt = 'iih'
f.write(struct.pack(fmt, 4, 185765, 1020))
f.close()
我已经尝试了一些在Github.com和其他一些来源上看到的示例,但似乎没有正确地使任何东西工作。在Go语言中,有什么惯用的方法来完成这样的任务?
以下是我目前在Go语言中实现的方式:
package main
import (
"fmt"
"os"
"encoding/binary"
)
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
aBuf := make([]byte, 4)
bBuf := make([]byte, 4)
cBuf := make([]byte, 2)
binary.LittleEndian.PutUint32(aBuf, 4)
binary.LittleEndian.PutUint32(bBuf, 185765)
binary.LittleEndian.PutUint16(cBuf, 1020)
binary.Write(fp, binary.LittleEndian, aBuf)
binary.Write(fp, binary.LittleEndian, bBuf)
binary.Write(fp, binary.LittleEndian, cBuf)
}
使用以下Python代码进行验证:
import numpy as np
data = np.fromfile('tst.bin', dtype='i4,i4,i2')
print(data)
英文:
I'm trying to figure out <del>how</del> the best way to write a binary file in Go that corresponds with the following Python:
import struct
f = open('tst.bin', 'wb')
fmt = 'iih'
f.write(struct.pack(fmt,4, 185765, 1020))
f.close()
I have been tinkering with some of the examples I've seen on Github.com and a few other sources <del>but I can't seem to get anything working correctly</del>. What is the idiomatic way to do this sort of thing in Go?
Here is how I am accomplishing this now (Golang):
package main
import (
"fmt"
"os"
"encoding/binary"
)
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
aBuf := make([]byte, 4)
bBuf := make([]byte, 4)
cBuf := make([]byte, 2)
binary.LittleEndian.PutUint32(aBuf, 4)
binary.LittleEndian.PutUint32(bBuf, 185765)
binary.LittleEndian.PutUint16(cBuf, 1020)
binary.Write(fp, binary.LittleEndian, aBuf)
binary.Write(fp, binary.LittleEndian, bBuf)
binary.Write(fp, binary.LittleEndian, cBuf)
}
Verified with this Python:
import numpy as np
data = np.fromfile('tst.bin', dtype='i4,i4,i2')
print(data)
答案1
得分: 0
如我在问题中提到的,我不确定这是否是最佳的方法,但经过一番尝试,这确实解决了我遇到的问题。我发布这个答案,以防其他人也在寻找答案:
package main
import (
"fmt"
"os"
"encoding/binary"
)
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
aBuf := make([]byte, 4)
bBuf := make([]byte, 4)
cBuf := make([]byte, 2)
binary.LittleEndian.PutUint32(aBuf, 4)
binary.LittleEndian.PutUint32(bBuf, 185765)
binary.LittleEndian.PutUint16(cBuf, 1020)
binary.Write(fp, binary.LittleEndian, aBuf)
binary.Write(fp, binary.LittleEndian, bBuf)
binary.Write(fp, binary.LittleEndian, cBuf)
}
稍微简化一下,使代码更简洁,我会这样做:
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
lineBuf := make([]byte, 10) //足够大以容纳两个4字节整数和一个2字节整数
binary.LittleEndian.PutUint32(lineBuf[0:4], 4) //打包为4字节
binary.LittleEndian.PutUint32(lineBuf[4:8], 185765)
binary.LittleEndian.PutUint16(lineBuf[8:10], 1020) //打包为2字节
binary.Write(fp, binary.LittleEndian, lineBuf)
}
英文:
As I mentioned in my question, I'm not sure this is THE idiomatic way to do this but after a fair bit of tinkering this does solve the problem I was having. Posting so there is at least one answer in case someone else comes looking:
package main
import (
"fmt"
"os"
"encoding/binary"
)
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
aBuf := make([]byte, 4)
bBuf := make([]byte, 4)
cBuf := make([]byte, 2)
binary.LittleEndian.PutUint32(aBuf, 4)
binary.LittleEndian.PutUint32(bBuf, 185765)
binary.LittleEndian.PutUint16(cBuf, 1020)
binary.Write(fp, binary.LittleEndian, aBuf)
binary.Write(fp, binary.LittleEndian, bBuf)
binary.Write(fp, binary.LittleEndian, cBuf)
}
Slightly cleaning this up to make it more brief I'll be doing something like this:
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
lineBuf := make([]byte, 10) //sized large enough to hold my two 4 byte ints and one 2 byte int
binary.LittleEndian.PutUint32(lineBuf[0:4], 4) //packing into 4 bytes
binary.LittleEndian.PutUint32(lineBuf[4:8], 185765)
binary.LittleEndian.PutUint16(lineBuf[8:10], 1020) //packing into 2 bytes
binary.Write(fp, binary.LittleEndian, lineBuf)
}
答案2
得分: 0
经过一些调整和对另一个问题的反馈后,我能够得出以下代码(看起来更简洁,但在生成一些大文件的测试后,我会发布性能反馈):
package main
import (
"os"
"encoding/binary"
)
type binData struct {
A int32
B int32
C int16
}
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
bd := binData{A: 4, B: 185765, C: 1020}
binary.Write(fp, binary.LittleEndian, &bd)
}
请注意,这只是代码的翻译部分,不包括任何其他内容。
英文:
After a little more tinkering and some feedback on another question I was able to come up with this (seems much cleaner but will post feedback on performance after testing with generating some large files):
package main
import (
"os"
"encoding/binary"
)
type binData struct {
A int32
B int32
C int16
}
func main() {
fp, err := os.Create("tst.bin")
if err != nil {
panic(err)
}
defer fp.Close()
bd := binData{A:4, B:185765, C:1020}
binary.Write(fp, binary.LittleEndian, &bd)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论