gpt4 book ai didi

使用 RPM 进行字节到整数编码

转载 作者:IT王子 更新时间:2023-10-29 02:30:28 24 4
gpt4 key购买 nike

我正在尝试创建一个无需 librpm 和 rpmbuild 即可读取和创建 RPM 文件的 go 程序。这样做的大部分原因是为了更好地理解 go 编程。

我正在根据以下内容解析 RPM:https://github.com/jordansissel/fpm/wiki/rpm-internals

我正在查看 header 并尝试解析标签的数量 + 长度,并且我有以下代码

fi, err := os.Open("golang-1.1-2.fc19.i686.rpm")
...
// header
head := make([]byte, 16)
// read a chunk
_, err = fi.Read(head)
if err != nil && err != io.EOF { panic(err) }

fmt.Printf("Magic number %s\n", head[:8])
tags, read := binary.Varint(head[8:12])
fmt.Printf("Tag Count: %d\n", tags)
fmt.Printf("Read %d\n", read)

length, read := binary.Varint(head[12:16])
fmt.Printf("Length : %d\n", length)
fmt.Printf("Read %d\n", read)

我得到以下信息:

Magic number ���
Tag Count: 0
Read 1
Length : 0
Read 1

我打印出 slice 并看到了这个:

Tag bytes: [0 0 0 7]
Length bytes: [0 0 4 132]

然后我尝试这样做:

length, read = binary.Varint([]byte{4, 132})

返回长度为 2 并读取 1。

根据我正在阅读的内容,标签和长度应该是“4 字节‘标签计数’”,那么我如何将这四个字节作为一个数字呢?

编辑:根据@nick-craig-wood 和@james-henstridge 的反馈,下面是我的以下原型(prototype)代码,它可以满足我的需求:

package main

import (
"io"
"os"
"fmt"
"encoding/binary"
"bytes"
)

type Header struct {
// begin with the 8-byte header magic value: 8D AD E8 01 00 00 00 00
Magic uint64
// 4 byte 'tag count'
Count uint32
// 4 byte 'data length'
Length uint32
}

func main() {
// open input file
fi, err := os.Open("golang-1.1-2.fc19.i686.rpm")
if err != nil { panic(err) }
// close fi on exit and check for its returned error
defer func() {
if err := fi.Close(); err != nil {
panic(err)
}
}()

// ignore lead
fi.Seek(96, 0)

// header
head := make([]byte, 16)
// read a chunk
_, err = fi.Read(head)
if err != nil && err != io.EOF { panic(err) }

fmt.Printf("Magic number %s\n", head[:8])
tags := binary.BigEndian.Uint32(head[8:12])
fmt.Printf("Count Count: %d\n", tags)

length := binary.BigEndian.Uint32(head[12:16])
fmt.Printf("Length : %d\n", length)

// read it as a struct
buf := bytes.NewBuffer(head)
header := Header{}
err = binary.Read(buf, binary.BigEndian, &header)
if err != nil {
fmt.Println("binary.Read failed:", err)
}
fmt.Printf("header = %#v\n", header)
fmt.Printf("Count bytes: %d\n", header.Count)
fmt.Printf("Length bytes: %d\n", header.Length)
}

最佳答案

首先不要使用 Varint - 它不会像您认为的那样工作!

这样解码成go结构是最方便的方式

package main

import (
"bytes"
"encoding/binary"
"fmt"
)

type Header struct {
// begin with the 8-byte header magic value: 8D AD E8 01 00 00 00 00
Magic uint64
// 4 byte 'tag count'
Count uint32
// 4 byte 'data length'
Length uint32
}

var data = []byte{0x8D, 0xAD, 0xE8, 0x01, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 4, 132}

func main() {
buf := bytes.NewBuffer(data)
header := Header{}
err := binary.Read(buf, binary.BigEndian, &header)
if err != nil {
fmt.Println("binary.Read failed:", err)
}
fmt.Printf("header = %#v\n", header)

}

打印

header = main.Header{Magic:0x8dade80100000000, Count:0x7, Length:0x484}

Playground link

关于使用 RPM 进行字节到整数编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19043366/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com