我有一些文件,其中每7位代表一个小端整数。
到目前为止,我有一个实现将字节读入字节数组,转换为字符串,使用循环索引在BitArray中放入7个字符,并根据索引做2 ^ x,但这似乎非常慢(文件只有20KB,但需要花费5分钟才能解析)而且也有太多的演员阵容是最好的方式。
有没有办法直接从文件中读取一组7位?
答案 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
算法如下:
bi
),告诉我们下一个7位整数开始的位偏移量(在每个字节中)。b0
),取前7位并将其返回。b1
)与前一个字节(b0
)组合成一个可以一次读取的16位值bi + 7
)来提取下一个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;
}
}