猿问

为什么 binary.Read() 不能正确读取整数?

我正在尝试在 Go 中读取二进制文件。


基本上我有一个这样的结构:


type foo struct {

    A int16

    B int32

    C [32]byte

    // and so on...

}

我正在从文件中读取到结构中,如下所示:


fi, err := os.Open(fname)

// error checking, defer close, etc.

var bar foo

binary.Read(fi, binary.LittleEndian, &bar)

现在,这应该可行,但我得到了一些奇怪的结果。例如,当我读入结构时,我应该得到这个:


A: 7

B: 8105

C: // some string

但我得到的是:


A: 7

B: 531169280

C: // some correct string

这样做的原因是因为在binary.Read()读取文件时,在读取[]byte{7, 0}as int16(7)( 的正确值A)后,它遇到切片[]byte{0, 0, 169, 31}并尝试将其转换为int32. 但是,binary.Read()的转换是这样做的:


uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24b字节切片在哪里。


但真正让我困惑的是在 C 中做完全相同的事情工作得很好。


如果我用 C 写这个:


int main()

{

    int fd;

    struct cool_struct {

        short int A;

        int32_t B;

        char C[32];

        // you get the picture...

    } foo;

    int sz = sizeof(struct cool_struct);

    const char* file_name = "/path/to/my/file"


    fd = open(file_name, O_RDONLY);

    // more code

    read(fd, &foo, sz);

    // print values

}

我得到了正确的结果。为什么我的 C 代码正确而我的 Go 代码不是?


ABOUTYOU
浏览 253回答 2
2回答

慕森王

假设字符串的前两个字符不是 '\000'你有一个对齐问题,你的 C 编译器在 int16 后面多放了两个字节的填充,Go 不是最简单的解决方法可能只是在“A”之后添加一个虚拟(填充)int16type foo struct&nbsp;{&nbsp; &nbsp; A int16&nbsp; &nbsp; A_pad int16&nbsp; &nbsp; B int32&nbsp; &nbsp; C [32]byte}或者这可能是一种告诉 go int32 需要“4 字节对齐”的方法如果您知道一个,请编辑此答案或发表评论

慕桂英4014372

given:0000000: 0700 0000 a91f 0000 7074 732f 3300 0000 ........pts/3...the fields, per the struct, are:0700h that will be the short int field, little endian format =&nbsp; 70000a91fh that will be the&nbsp; int field, little endian format = the big number...your struct needs a second short field to absorb the 0000hthen&nbsp;0700h = 70000h = 0 in new fielda91f0000 = 8105....which indicates (amongst other things) that the struct is missing&nbsp;the expected 2 byte padding between the short and the int fieldsdoes the C code have #pragma pack?
随时随地看视频慕课网APP

相关分类

Go
我要回答