第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

binary.Read 未按預期處理結(jié)構(gòu)填充

binary.Read 未按預期處理結(jié)構(gòu)填充

Go
慕桂英546537 2021-10-11 13:37:15
在最近的一個 Go 項目中,我需要讀取一個由 Python 生成的二進制數(shù)據(jù)文件,但由于填充,binary.Read在 Go 中無法正確讀取它。以下是我的問題的最小示例。我處理的結(jié)構(gòu)是否具有以下格式type Index struct{    A int32    B int32    C int32    D int64}如您所見,結(jié)構(gòu)體的大小為 4+4+4+8=20,但 Python 額外添加了 4 個字節(jié)用于對齊。所以大小實際上是24。下面是我用來編寫這個結(jié)構(gòu)體的可運行 Python 代碼:#!/usr/bin/env python# encoding=utf8import structif __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位的整數(shù),并且在結(jié)構(gòu)中,其是與相同的一個64位的整數(shù)Index余前面定義結(jié)構(gòu)。運行此代碼將生成一個名為index.bin72的文件,它等于 24 * 3。下面是我用來閱讀的 Go 代碼index.bin:package mainimport (        "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: 3After 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 生成的文件中讀取時,輸出是混亂的。所以我的問題是,如何在 Go 中正確讀取 Python 生成的文件(帶填充)?
查看完整描述

3 回答

?
慕妹3242003

TA貢獻1824條經(jīng)驗 獲得超6個贊

例如,


package main


import (

    "bufio"

    "encoding/binary"

    "fmt"

    "io"

    "os"

)


type Index struct {

    A int32

    B int32

    C int32

    D int64

}


func readIndex(r io.Reader) (Index, error) {

    var index Index

    var buf [24]byte

    _, err := io.ReadFull(r, buf[:])

    if err != nil {

        return index, err

    }

    index.A = int32(binary.LittleEndian.Uint32(buf[0:4]))

    index.B = int32(binary.LittleEndian.Uint32(buf[4:8]))

    index.C = int32(binary.LittleEndian.Uint32(buf[8:12]))

    index.D = int64(binary.LittleEndian.Uint64(buf[16:24]))

    return index, nil

}


func main() {

    f, err := os.Open("index.bin")

    if err != nil {

        fmt.Fprintln(os.Stderr, err)

        return

    }

    defer f.Close()

    r := bufio.NewReader(f)

    indexes := make([]Index, 0, 1024)

    for {

        index, err := readIndex(r)

        if err != nil {

            if err == io.EOF {

                break

            }

            fmt.Fprintln(os.Stderr, err)

            return

        }

        indexes = append(indexes, index)

    }

    fmt.Println(indexes)

}

輸出:


[{1 2 3 4} {5 6 7 8} {9 10 11 12}]

輸入:


00000000  01 00 00 00 02 00 00 00  03 00 00 00 00 00 00 00  |................|

00000010  04 00 00 00 00 00 00 00  05 00 00 00 06 00 00 00  |................|

00000020  07 00 00 00 00 00 00 00  08 00 00 00 00 00 00 00  |................|

00000030  09 00 00 00 0a 00 00 00  0b 00 00 00 00 00 00 00  |................|

00000040  0c 00 00 00 00 00 00 00                           |........|


查看完整回答
反對 回復 2021-10-11
?
料青山看我應如是

TA貢獻1772條經(jīng)驗 獲得超8個贊

我發(fā)現(xiàn)添加填充字段不太舒服。我找到了一個更好的方法。


下面是完美運行的新 golang 讀取代碼:


package main


import (

    "fmt"

    "os"

    "io"

    "io/ioutil"

    "unsafe"

)


type Index struct {

    A int32

    B int32

    C int32

    // Pad 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)


    reader := io.Reader(fp)

    allBytes, _ := ioutil.ReadAll(reader)

    readSlice := *((*[]Index)(unsafe.Pointer(&allBytes)))

    realLen := len(allBytes) / int(indexSize)

    readSlice = readSlice[:realLen]

    fmt.Printf("After read:\n%#v\n", readSlice)

}

輸出:


After read:

[]main.Index{main.Index{A:1, B:2, C:3, D:4}, main.Index{A:5, B:6, C:7, D:8}, main.Index{A:9, B:10, C:11, D:12}}

此解決方案不需要顯式填充字段。


這里的本質(zhì)是,如果讓golang將整個字節(jié)轉(zhuǎn)換為Indexstruct的切片,它似乎能夠很好地處理padding。


查看完整回答
反對 回復 2021-10-11
  • 3 回答
  • 0 關(guān)注
  • 226 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號