在Go语言中,编写与Python相同输出的紧凑二进制文件的惯用方式是什么?

huangapple go评论73阅读模式
英文:

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(&#39;tst.bin&#39;, &#39;wb&#39;)
fmt = &#39;iih&#39;
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 (
        &quot;fmt&quot;
        &quot;os&quot;
        &quot;encoding/binary&quot;
        )


func main() {
        fp, err := os.Create(&quot;tst.bin&quot;)

        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(&#39;tst.bin&#39;, dtype=&#39;i4,i4,i2&#39;)

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 (
        &quot;fmt&quot;
        &quot;os&quot;
        &quot;encoding/binary&quot;
        )


func main() {
        fp, err := os.Create(&quot;tst.bin&quot;)

        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(&quot;tst.bin&quot;)

        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 (
        &quot;os&quot;
        &quot;encoding/binary&quot;
        )

type binData struct {
    A int32
    B int32
    C int16
}

func main() {
        fp, err := os.Create(&quot;tst.bin&quot;)

        if err != nil {
                panic(err)
        }

        defer fp.Close()
        bd := binData{A:4, B:185765, C:1020}

        binary.Write(fp, binary.LittleEndian, &amp;bd)
}

huangapple
  • 本文由 发表于 2015年12月4日 07:01:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/34077889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定