将字符打包为5位,并将结果写入文件(C++)

Packing chars into 5 bits and writing results to file (C++)

本文关键字:文件 C++ 结果 字符 5位      更新时间:2023-10-16

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

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

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

要将字符减少到5位,可以使用ch & 0x1Fch - 'A';两者都不适用于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,因为这是在20世纪80年代(,它也是太慢了。如果你的弦很短,今天,它可能是足够的否则,您将需要一个更复杂的跟踪已经使用了多少位的算法在最后一个字节中,并对一次插入尽可能多的位:最多两个移位和而不是像这里的情况那样为5次。这就是我最终使用的。(但我没有密码再也没有了,所以我不能轻易地发布一个例子。(

你能做到吗?当然

我认为只使用gzip编写压缩文件会更成功、更轻松。

我有一个字符向量,它只能是字母表中的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个字母中的任何一个。

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

您可以试试我的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