【问题标题】:How to concatenate bytes in Crystal如何在 Crystal 中连接字节
【发布时间】:2018-06-03 01:46:11
【问题描述】:

我正在测试字节或切片的序列化,只是学习和尝试。我想在一个 10 字节字段中绑定 3 个参数,但我现在不知道如何在 Crystal 中连接它们或者是否有可能。我知道我可以通过创建数组或元组来实现这一点,但我想尝试是否可以将参数混合到单个缓冲区中。

例如,我想要一个混合 3 个参数的自描述二进制记录 ID:

类型 (UInt8) |类别 (UInt8) |微秒 (UInt64) = 总共 80 位 - 10 字节

type = 1_u8 # 1 byte
categ = 4_u8 # 1 byte
usec = 1527987703211000_u64 # 8 bytes (Epoch)

如何将所有这些变量连接到一个连续的 10 字节缓冲区中?

我想通过索引来检索数据,比如:

type = buff[0,1]
categ = buff[1,1]
usec = buff[2,8].to_u64 # (Actually not possible)

【问题讨论】:

    标签: crystal-lang


    【解决方案1】:
    typ = 1_u8 # 1 byte
    categ = 4_u8 # 1 byte
    usec = 1527987703211000_u64 # 8 bytes (Epoch)
    
    FORMAT = IO::ByteFormat::LittleEndian
    
    io = IO::Memory.new(10)  # Specifying the capacity is optional
    
    io.write_bytes(typ, FORMAT)  # Specifying the format is optional
    io.write_bytes(categ, FORMAT)
    io.write_bytes(usec, FORMAT)
    
    buf = io.to_slice
    puts buf
    
    # --------
    
    io2 = IO::Memory.new(buf)
    
    typ2 = io2.read_bytes(UInt8, FORMAT)
    categ2 = io2.read_bytes(UInt8, FORMAT)
    usec2 = io2.read_bytes(UInt64, FORMAT)
    
    pp typ2, categ2, usec2
    
    Bytes[1, 4, 248, 99, 69, 92, 178, 109, 5, 0]
    typ2   # => 1_u8
    categ2 # => 4_u8
    usec2  # => 1527987703211000_u64
    

    这显示了一个为您的用例量身定制的示例,但 IO::Memory 通常应用于“连接字节”——只需写入即可。

    【讨论】:

      【解决方案2】:

      这不是您问题的答案,但是当我尝试连接实际的 Bytes[] 时,我一直在这里结束。 Oleh 的回答仍然适用,但我在这里尝试给出更通用的方法:

      # some bytes a
      a = Bytes[131, 4, 254, 47]
      
      # some other bytes b
      b = Bytes[97, 98, 99]
      
      # new buffer of sizes a and b
      c = IO::Memory.new a.bytesize + b.bytesize
      
      # without knowing the size of the slice, we just write byte by byte
      a.each do |v|
          # each byte can be represented by an u8
          c.write_bytes UInt8.new v
      end
      
      # same for b
      b.each do |v|
          c.write_bytes UInt8.new v
      end
      
      # here you have your new bytes slice
      c = c.to_slice
      # => Bytes[131, 4, 254, 47, 97, 98, 99]
      

      注意,这仅适用于IO::ByteFormat::LittleEndian,这是默认设置,因此在示例中省略

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-01
        • 2014-06-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多