如何读取文件中的每7位作为整数?

时间:2015-03-02 23:19:03

标签: c#

我有一些文件,其中每7位代表一个小端整数。

到目前为止,我有一个实现将字节读入字节数组,转换为字符串,使用循环索引在BitArray中放入7个字符,并根据索引做2 ^ x,但这似乎非常慢(文件只有20KB,但需要花费5分钟才能解析)而且也有太多的演员阵容是最好的方式。

有没有办法直接从文件中读取一组7位?

1 个答案:

答案 0 :(得分:9)

如果没有打包这些7位整数,那么使用每个字节的最低有效7位就很简单了:

Byte b; Int32 nb;
while( (nb = reader.ReadByte()) != -1 ) {
    b = (Byte)nb;

    Byte value = b & 0x7F;
    yield return value;
}

如果这些是打包字节,那么它会更有趣:)

您需要1到2个字节才能使用,从中提取值。我假设输入是Byte的流(为简化API而使用IEnumerator表示),其中7位打包如下:

7-bit  |0                                 |1                                 |2                                 |3                                 |4
Bytes  |0                                      |1                                      |2                                      |3
Bits   |0   |1   |2   |3   |4   |5   |6   |7   |0   |1   |2   |3   |4   |5   |6   |7   |0   |1   |2   |3   |4   |5   |6   |7   |0

算法如下:

  1. 维护一个“位索引”(bi),告诉我们下一个7位整数开始的位偏移量(在每个字节中)。
  2. 读取一个字节(b0),取前7位并将其返回。
  3. 将位索引增加7。
  4. 7 + 7大于8(字节大小)所以我们需要另一个字节。读取另一个字节并将其(b1)与前一个字节(b0)组合成一个可以一次读取的16位值
  5. 通过从中读取位(bi + 7)来提取下一个7位值,将其移位以使其有用,然后将其返回。
  6. 重复。
  7. 这里可能存在一些错误,如果您发现任何错误,请告诉我们。

    public static IEnumerable<Byte> ReadPacked7BitInts(IEnumerator<Byte> inputBytes) {
    
        Int32 bi = 0; // bit-index
    
        if( !inputBytes.MoveNext() ) yield break;
        Byte b0 = inputBytes.Current;
    
        while( true ) {
            if( bi == 0 ) yield return b0 & 0x7F;
            if( bi == 1 ) yield return (b0 >> 1) & 0x7F;
            else {
                // Read another byte
                if( !inputBytes.MoveNext() ) yield break;
                Byte b1 = inputBytes.Current;
                UInt16 value = (UInt16)b0 | ((UInt16)b1 << 8);
    
                yield return ( value >> bi ) & 0x7F;
            }
    
            bi = (bi + 7) % 8;
        }
    }