将字符包装成5位并将结果写入文件(C ++)

时间:2014-04-30 17:44:53

标签: c++ bit-packing

我有一个包含字符的向量。这些字符只能是字母表中的26个大写字母,因此表示这些字符的位数可以从8减少到5.然后我需要将结果写入文件,以便以后使用。

我目前的想法是A..Z的3个最高有效位都是相同的,因此我可以使用5个最低有效位来唯一地识别字符?但是我很难将这些未格式化的数据写入文件。

我将如何执行此操作并将结果写入文件?

5 个答案:

答案 0 :(得分:1)

要将字符缩小为5位,您可以使用ch & 0x1Fch - 'A';既不适用于EBCDIC,也不适用于EBCDIC 可能不是问题。 (如果是:在字符串中的表查找 可以使用返回索引的所有大写字母。)

之后,它变得复杂了。最简单的解决方案是 定义一个位数组,如:

class BitArray
{
    std::vector<unsigned char> myData;
    int byteIndex( int index ) { return index / 8; }
    unsigned char bitMask( int index ) { return 1 << (index % 8); }
    int byteCount( int bitCount )
    { 
        return byteIndex( bitCount )
            + (bitIndex( bitCount) != 0 ? 1 : 0);
    }
public:
    BitArray( int size ) : myData( byteCount( size ) ) {}
    void set( index )
    {
        myData[byteIndex( index )] |= bitMask( index );
    }
    void reset( index )
    {
        myData[byteIndex( index )] &= ~bitMask( index );
    }
    bool test( index )
    {
        return (myData[byteIndex( index ) & bitMask( index )) != 0;
    }
};

(您需要更多来提取数据,但我不确定是什么 你需要它的格式。)

然后循环遍历字符串:

BitArray results( 5 * s.size() );
for ( int index = 0; index != s.size(); ++ index ) {
    for ( int pos = 0; pos != 5; ++ pos ) {
        results.set( 5 * index + pos );
    }
}

这将毫无问题地工作。当我尝试使用它时(或 在遥远的过去(对于霍夫曼而言) 编码,在C中,因为这是在1980年代,它也是方式 太慢了。如果你的字符串相当短,今天可能是 足够。否则,你需要一个更复杂的 算法,跟踪已经使用了多少位 在最后一个字节中,并进行适当的移位和掩码 一次插入尽可能多的位:最多两次移位和 或每次插入的操作,而不是这里的情况。 这就是我最终使用的。 (但我没有代码 我不能轻易发布一个例子。)

答案 1 :(得分:0)

您可以使用的最小数据单位是8位。您将不得不采用位移,但您只能以8位为一组读取/写入数据,因此您需要额外的逻辑来处理它。如果您的输入至少有8个5位字母,则一次合并8个字母,使总共40位,并将其写入文件为5个8位字节。根据需要继续,直到剩下少于8个5位的字母,然后将它们合并在一起并将余数填充到8的偶数倍并将其写入文件。

答案 2 :(得分:0)

  

我有一个[chars]矢量,只能是26个大写字母

您可以相对轻松地编写代码:将文本拆分为八个字符的块,并将编码后的文本写入五个字节的块中,如下所示:

          76543210 76543210 76543210 76543210 76543210 76543210 76543210 76543210
ORIGINAL: 000AAAAA 000BBBBB 000CCCCC 000DDDDD 000EEEEE 000FFFFF 000GGGGG 000HHHHH

          76543210 76543210 76543210 76543210 76543210
ENCODED:  AAAAABBB BBCCCCCD DDDDEEEE EFFFFFGG GGGHHHHH

如果您的最后一个块没有足够的字符,请使用“pad”字符(全部),这些字符不用于编码26个字母中的任何一个。

答案 3 :(得分:0)

你能做到吗?肯定。

我认为您只需使用gzip编写压缩文件就可以获得更多成功和轻松。

答案 4 :(得分:0)

您可以尝试使用我的PackedArray代码。

它实现了一个随机访问容器,其中项目在位级别打包。换句话说,它就像你能够操纵一个例如uint9_tuint17_t数组:

PackedArray principle:
  . compact storage of <= 32 bits items
  . items are tightly packed into a buffer of uint32_t integers

PackedArray requirements:
  . you must know in advance how many bits are needed to hold a single item
  . you must know in advance how many items you want to store
  . when packing, behavior is undefined if items have more than bitsPerItem bits

PackedArray general in memory representation:
  |-------------------------------------------------- - - -
  |       b0       |       b1       |       b2       |
  |-------------------------------------------------- - - -
  | i0 | i1 | i2 | i3 | i4 | i5 | i6 | i7 | i8 | i9 |
  |-------------------------------------------------- - - -

  . items are tightly packed together
  . several items end up inside the same buffer cell, e.g. i0, i1, i2
  . some items span two buffer cells, e.g. i3, i6