zoukankan      html  css  js  c++  java
  • python parse bit from bytes

    先说结论

    能用struct就用struct

    能转成int就转成int

    然后在int格式下 能 掩码&  移位>>。反而不是在bytes下。个人感觉这是一个“反直觉”的地方。不喜欢。所以记下来。

    比如,解析flv文件。

    按flv文件格式:

    假设就解析前9byte

    import struct

    f_stream = open(‘./xxx.flv’, 'rb') chunk = stream.read(9)

     

    1 最简洁的方法:

    先用标准库的struct.unpack解出整体结构 

    https://docs.python.org/3/library/struct.html

    the packed value is platform-dependent.

    Format

    C Type

    Python type

    Standard size

    Notes

    x

    pad byte

    no value

       

    c

    char

    bytes of length 1

    1

     

    b

    signed char

    integer

    1

    (1), (2)

    B

    unsigned char

    integer

    1

    (2)

    ?

    _Bool

    bool

    1

    (1)

    h

    short

    integer

    2

    (2)

    H

    unsigned short

    integer

    2

    (2)

    i

    int

    integer

    4

    (2)

    I

    unsigned int

    integer

    4

    (2)

    l

    long

    integer

    4

    (2)

    L

    unsigned long

    integer

    4

    (2)

    q

    long long

    integer

    8

    (2)

    Q

    unsigned long long

    integer

    8

    (2)

    n

    ssize_t

    integer

     

    (3)

    N

    size_t

    integer

     

    (3)

    e

    (6)

    float

    2

    (4)

    f

    float

    float

    4

    (4)

    d

    double

    float

    8

    (4)

    s

    char[]

    bytes

       

    p

    char[]

    bytes

       

    P

    void *

    integer

     

    (5)

    C

    我们这样写 

        format_str = '>3sBBI'
        flv, version, stream_type_bits, len_header = struct.unpack(format_str, chunk)

    注意倒数第二个stream_type_bits 给搞成了“B” 1 byte的 integer: 

    下面就可以位移了:

    #对int才可以& 和>>
    has_audio =  (stream_type_bits & 0x7) >> 2
    has_video = stream_type_bits &  0x1

    这样是最简单的。但对int 进行 位操作,而不是对bytes进行位操作,感觉非常反直觉。

    2 麻烦点的办法1

    不用struct。直接拿出int然后转成string,用string取bit,再转成int

    看着绕,但是写码也很简洁:

    stream_type_bits = format(chuck[4], 'b').zfill(8)
    has_audio = int(stream_type_bits[5], 2) #按bit字符串,按二进制转成int
    has_video = int(stream_type_bits[7], 2) # 同上

    对第一句的几点说明

    chuck[4]   从bytes里这样拿出来1个byte直接就给转成int了(又反直觉)
    format(int, 'b') 转成二进制格式的字符串,'101'
    zfill(8) 补足8位,在前面添加5个0 得到‘00000101’
     
    这种方法也比较简单,但是没用struct。数据少的时候可以用。但是其实不如位移操作直观
     

    3 麻烦点的办法2

    读出1个bytes 然后用bitarray

    from bitarray import bitarray
    
    #format_str = '>3sBBI'
    format_str = '>3sBsI'
    
    flv, version, stream_type_bits, len_header = struct.unpack(format_str, chunk)
    
    
    stream_type = bitarray(endian='big')
    stream_type.frombytes(stream_type_bytes)
    has_video, has_audio = stream_type[-1], stream_type[-3]

    如果需要修改bit,这样比较方便。所以也放在这了

    感觉python这方面设计的还是略显得反直觉。

  • 相关阅读:
    NuGet包介绍
    修改逻辑文件名
    检查扫描文件系统
    C# Newtonsoft.Json不序列字段
    HierarchyId通过父节点创建一个新的子节点
    常用SQL语句
    redis脚本
    asp.net 的一个简单进度条功能
    .Net C#向远程服务器Api上传文件
    使用IKVM在C#中调用JAVA程序
  • 原文地址:https://www.cnblogs.com/xuanmanstein/p/13967320.html
Copyright © 2011-2022 走看看