简体   繁体   English

为什么binary.Read()无法正确读取整数?

[英]Why isn't binary.Read() reading integers correctly?

I'm trying to read a binary file in Go. 我正在尝试在Go中读取二进制文件。

Essentially I have a struct like this: 本质上,我有这样的结构:

type foo struct {
    A int16
    B int32
    C [32]byte
    // and so on...
}

and I'm reading from the file into the struct like this: 我正在从文件中读取到这样的结构:

fi, err := os.Open(fname)
// error checking, defer close, etc.
var bar foo
binary.Read(fi, binary.LittleEndian, &bar)

Now, that should work, but I'm getting some weird results. 现在,这应该可行,但是我得到了一些奇怪的结果。 For instance, when I read into the struct I should get this: 例如,当我读到结构时,我应该得到这个:

A: 7
B: 8105
C: // some string

but what I get is this: 但是我得到的是:

A: 7
B: 531169280
C: // some correct string

The reason for this is because when binary.Read() is reading the file, after it reads the []byte{7, 0} as int16(7) (the correct value for A ), it comes across the slice []byte{0, 0, 169, 31} and tries to convert it into an int32 . 这样做的原因是因为当binary.Read()读取文件时,它在将[]byte{7, 0} int16(7) []byte{7, 0}读取为int16(7)A的正确值)之后,遇到了切片[]byte{0, 0, 169, 31}并尝试将其转换为int32 However, binary.Read() 's conversion does this: 但是, binary.Read()的转换可以做到这一点:

uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 where b is the byte slice. uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 ,其中b是字节片。

But what really confuses me is doing the exact same thing in C works perfectly fine. 但是真正令我感到困惑的是,在C语言中做同样的事情完全可以正常工作。

If I write this in 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
}

I get the correct results. 我得到正确的结果。 Why is my C code getting this correct while my Go code isn't? 为什么我的C代码为什么不正确,而我的Go代码却不正确呢?

Assuming the first two characters of the string aren't '\\000' 假设字符串的前两个字符不是'\\ 000'

what you've got there is an alignment problem, your C compiler is putting an extra two bytes of padding after the int16, Go isn't 您所遇到的问题是对齐问题,您的C编译器在int16之后放置了两个额外的填充字节,Go不是

easiest fix is probably just to add a dummy (padding) int16 after 'A' 最简单的解决方法可能只是在'A'之后添加一个哑元(填充)int16

type foo struct 
{
    A int16
    A_pad int16
    B int32
    C [32]byte
}

or the may be a way to tell go that the int32 needs to be "4-byte aligned" 或可能是一种判断int32需要“ 4字节对齐”的方式

if you know of one please edit this answer or post a comment 如果您认识一个人,请编辑此答案或发表评论

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 =  7

0000a91fh that will be the  int field, little endian format = the big number
...

your struct needs a second short field to absorb the 0000h
then 
0700h = 7
0000h = 0 in new field
a91f0000 = 8105
....

which indicates (amongst other things) that the struct is missing 
the expected 2 byte padding between the short and the int fields
does the C code have #pragma pack?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM