type newreader new golang cast bytes bufio array buffer go unpack

buffer - newreader - ¿Cómo descomprimo varias formas de enteros en un búfer de bytes en Golang?



string in go (2)

Puede evitar crear un nuevo búfer cada vez usando .Next() para omitir los bytes que no desea leer:

{ // 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) }

O puede evitar leer un fragmento por fragmento y crear una estructura de encabezado que lea directamente con binary.Read . 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) }

Necesito extraer varios campos en un búfer de bytes. Se me ocurrió esta solución:

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) }

¿Hay una forma mejor / idiomática / directa de hacer esto?

  • Quiero mantener las compensaciones explícitas
  • Quiero leer desde el búfer de bytes, no buscar y leer el archivo cuando sea posible.

Tengo un paquete binpacker para manejar esas situaciones

ejemplo

datos de ejemplo:

buffer := new(bytes.Buffer) packer := binpacker.NewPacker(buffer) unpacker := binpacker.NewUnpacker(buffer) packer.PushByte(0x01) packer.PushUint16(math.MaxUint16)

descomprimirlo:

var val1 byte var val2 uint16 var err error val1, err = unpacker.ShiftByte() val2, err = unpacker.ShiftUint16()

O

var val1 byte var val2 uint16 var err error unpacker.FetchByte(&val1).FetchUint16(&val2) unpacker.Error() // Make sure error is nil