В недавнем проекте Go мне нужно прочитать файл двоичных данных, сгенерированный Python, но из-за заполнения, binary.Read
в Go не читает его правильно. Ниже приведен минимальный пример моей проблемы.binary.Read не обрабатывает прокладку структуры, как ожидалось
структура Я имею дело с тем, если в следующем формате
type Index struct{
A int32
B int32
C int32
D int64
}
Как вы можете увидеть размер структуры составляет 4 + 4 + 4 + 8 = 20, но Python добавили дополнительные 4 байта для выравнивания , Таким образом, размер на самом деле 24.
Ниже приведен код работоспособного Python Я использую, чтобы написать эту структуру:
#!/usr/bin/env python
# encoding=utf8
import struct
if __name__ == '__main__':
data = range(1, 13)
format = 'iiiq' * 3
content = struct.pack(format, *data)
with open('index.bin', 'wb') as f:
f.write(content)
означает формат iiiq
Есть три 32 разрядные целые чисел и один 64-битное целое в структурах, что совпадает с ранее описанной структурой Index
. И работает этот код будет генерировать файл с именем index.bin
размером 72, который равен 24 * 3.
и ниже код Go Я использую для чтения index.bin
:
package main
import (
"encoding/binary"
"fmt"
"os"
"io"
"unsafe"
)
type Index struct {
A int32
B int32
C int32
D int64
}
func main() {
indexSize := unsafe.Sizeof(Index{})
fp, _ := os.Open("index.bin")
defer fp.Close()
info, _ := fp.Stat()
fileSize := info.Size()
entryCnt := fileSize/int64(indexSize)
fmt.Printf("entry cnt: %d\n", entryCnt)
readSlice := make([]Index, entryCnt)
reader := io.Reader(fp)
_ = binary.Read(reader, binary.LittleEndian, &readSlice)
fmt.Printf("After read:\n%#v\n", readSlice)
}
И это выход:
entry cnt: 3
After read:
[]main.Index{main.Index{A:1, B:2, C:3, D:17179869184}, main.Index{A:0, B:5, C:6, D:7}, main.Index{A:8, B:0, C:9, D:47244640266}}
Очевидно, что выход испорчен при чтении из созданного на Python файла.
Так что мой вопрос в том, как я могу прочитать файл сгенерированный питоном (с дополнением) в правильном режиме?
Это http://golang.org/ref/spec#Size_and_alignment_guarantees может быть полезным. – alex
@alex Если я серьезно не понимаю что-то, макет памяти здесь не имеет значения, так как 'binary.Read' просто считывает элементы структуры в порядке. –
Возможно, это поможет http://play.golang.org/p/bCfWmKTP25. – alex