当前位置: 首页 > 面试题库 >

如何在Golang的字节缓冲区中解压缩各种形式的整数?

严宏旷
2023-03-14
问题内容

我需要提取字节缓冲区中的各个字段。我想出了以下解决方案:

func (fs *FileSystem) readSB() {
    // fs.f is a *os.File
    buf := make([]byte, 1024)
    fs.f.ReadAt(buf, 1024)

    // Offset: type
    var p *bytes.Buffer

    // 0: uint32
    p = bytes.NewBuffer(buf[0:])
    binary.Read(p, binary.LittleEndian, &fs.sb.inodeCount)
    // 4: uint32
    p = bytes.NewBuffer(buf[4:])
    binary.Read(p, binary.LittleEndian, &fs.sb.blockCount)
    // 20: uint32
    p = bytes.NewBuffer(buf[20:])
    binary.Read(p, binary.LittleEndian, &fs.sb.firstDataBlock)
    // 24: uint32
    p = bytes.NewBuffer(buf[24:])
    binary.Read(p, binary.LittleEndian, &fs.sb.blockSize)
    fs.sb.blockSize = 1024 << fs.sb.blockSize
    // 32: uint32
    p = bytes.NewBuffer(buf[32:])
    binary.Read(p, binary.LittleEndian, &fs.sb.blockPerGroup)
    // 40: uint32
    p = bytes.NewBuffer(buf[40:])
    binary.Read(p, binary.LittleEndian, &fs.sb.inodePerBlock)
}

有没有更好/惯用/直接的方法呢?

  • 我想让偏移量保持明确
  • 我想从字节缓冲区中读取,而不是在可能的情况下从文件中查找和读取。

问题答案:

通过使用.Next()跳过不想读取的字节,可以避免每次创建新缓冲区:

{
    // Offset: type
    p := bytes.NewBuffer(buf)

    // 0: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.inodeCount)

    // 4: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.blockCount)

    // Skip [8:20)
    p.Next(12)

    // 20: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.firstDataBlock)

    // 24: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.blockSize)
    fs.sb.blockSize = 1024 << fs.sb.blockSize

    // Skip [28:32)
    p.Next(4)

    // 32: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.blockPerGroup)

    // Skip [36:40)
    p.Next(4)

    // 40: uint32
    binary.Read(p, binary.LittleEndian, &fs.sb.inodePerBlock)
}

或者,您可以避免逐块阅读,而创建一个标头结构,您可以使用binary.Read以下方法直接读取它:

type Head struct {
    InodeCount      uint32  //  0:4
    BlockCount      uint32  //  4:8
    Unknown1        uint32  //  8:12
    Unknown2        uint32  // 12:16
    Unknown3        uint32  // 16:20
    FirstBlock      uint32  // 20:24
    BlockSize       uint32  // 24:28
    Unknown4        uint32  // 28:32
    BlocksPerGroup  uint32  // 32:36
    Unknown5        uint32  // 36:40
    InodesPerBlock  uint32  // 40:44
}

func main() {
    var header Head

    err = binary.Read(file, binary.LittleEndian, &header)

    if err != nil {
        log.Fatal(err)
    }

    log.Printf("%#v\n", header)
}


 类似资料:
  • 问题内容: 我有一堆来自某些Web请求的文件,有些文件是gzip压缩的,我需要将它们解压缩并将其打印为字符串。这是我第一次尝试使用golang,尝试了一些在网上找到的示例,但无法正常使用。 这是我尝试的最后一个测试: 但它显示了错误:panic:,与其他一些示例相同。 如何解压缩字节数组的内容? 问题答案: 这根本不是gzip数据。正确的gzip数据以魔术序列开头,即。就此而言,它正确地抱怨 gz

  • 问题内容: 我有一个流时间序列,我有兴趣保留最后4个元素,这意味着我希望能够弹出第一个元素并将其添加到末尾。本质上我需要一个环形缓冲区。 哪个Java集合最适合此用途?向量? 问题答案: 考虑CircularFifoBuffer Apache的Common.Collections。与Queue不同,你不必维护基础集合的有限大小,只要达到极限就可以包装它。 由于以下属性,CircularFifoBu

  • 问题内容: 有没有一种方法可以使用BufferedReader读取ByteBuffer而不必先将其转换为String?我想读取相当大的ByteBuffer作为文本行,并且出于性能方面的考虑,我想避免将其写入磁盘。在ByteBuffer上调用toString不起作用,因为生成的String太大(它抛出java.lang.OutOfMemoryError:Java堆空间)。我本来以为API中会有一些东

  • 环形缓冲区接口 结构体 struct   rt_ringbuffer   环形缓冲区控制块 更多...   枚举 函数 void  rt_ringbuffer_init (struct rt_ringbuffer *rb, rt_uint8_t *pool, rt_int16_t size)   初始化环形缓冲区   void  rt_ringbuffer_reset (struct rt_rin

  • Javascript ArrayBuffer或TypedArrays没有任何类型的appendByte()、appendBytes()或appendBuffer()方法。所以,如果我想一次填充一个数组缓冲一个值,我该怎么做呢?

  • 问题内容: 我有一些字符串,每个字符串大约1万个字符。它们中有很多重复。它们是序列化的JSON对象。我想轻松地将它们压缩为字节数组,然后从字节数组解压缩它们。 我怎样才能最轻松地做到这一点?我正在寻找方法,因此可以执行以下操作: 问题答案: 你可以试试