简单ASCII压缩-帮助最大限度地减少系统调用

p3rjfoxz  于 2023-02-03  发布在  其他
关注(0)|答案(3)|浏览(231)

在我的last question中,nos给出了一种从一个ASCII字符字节中移除最高有效位的方法,这与我的教授在描述项目时所说的完全匹配。
我的问题是如何使用readwrite命令剥离有效位并将其打包到缓冲区中。由于write命令的长度是要写入的字节数,因此如何深入到缓冲区数组的位级别?

ha5z0ras

ha5z0ras1#

也许最简单的方法是以8字节为一组,读入一组数据,然后使用按位操作符将其压缩为7字节。
我们将输入数据称为input[0..7],输出数据称为output[0..6]
因此,输出数据的第一个字节output[0]input[0]的低7位和input[2]的第二高位组成,其他字节的工作原理相同:

Index:    [0]      [1]      [2]      [3]      [4]      [5]      [6]      [7]
    Input:  0aaaaaaa 0bbbbbbb 0ccccccc 0ddddddd 0eeeeeee 0fffffff 0ggggggg 0hhhhhhh
            ///////  //////   and     --->
            ||||||| /|||||     so on  --->
    Output: aaaaaaab bbbbbbcc cccccddd ddddeeee eeefffff ffgggggg ghhhhhhh
    Index:    [0]      [1]      [2]      [3]      [4]      [5]      [6]

您可以使用如下操作:

output[0] = ((input[0] & 0x7f) << 1) | ((input[1] & 0x40) >> 6)
output[1] = ((input[1] & 0x3f) << 2) | ((input[2] & 0x60) >> 5)
:
output[5] = ((input[5] & 0x03) << 6) | ((input[6] & 0x7e) >> 1)
output[6] = ((input[6] & 0x01) << 7) |  (input[7] & 0x7f)

其他的应该可以从上面的那些计算出来。如果你想知道更多关于位运算符的信息,请看这里。
一旦你压缩了一个8字节的块,写出7字节的压缩块并继续。
唯一有点棘手的是在末尾,你可能没有完整的8个字节,在这种情况下,你将输出和你输入的一样多的字节,但是最后一个字节将用0位填充。
而解压缩时,你要做相反的事情。读入7个字节的块,用按位运算符扩展,然后写出8个字节。你也可以仅仅根据读入的最后一段的大小来判断哪些位是在结尾填充的。

ars1skjm

ars1skjm2#

就像帕克斯迪亚波罗说的:最简单的方法是以8字节为一组。2但是为什么要移位8字节呢?3你可以把最后一个字节的前7个字节放进去!4简单又快速...

Output[0] = ((Input[0] & 0x7f) | (Input[7] & 0x80))         //pack 7th bit in 0th byte
Output[1] = ((Input[1] & 0x7f) | ((Input[7] << 1) & 0x80))  //pack 6th bit in 1th byte
Output[2] = ((Input[2] & 0x7f) | ((Input[7] << 2) & 0x80))  //pack 5th bit in 2th byte
...

要恢复,只需将所有7个字节的第7位放在一起,并清除所有数组字节中的第7位。

xxls0lw8

xxls0lw83#

首先需要将数据打包到内存中的缓冲区中。例如,为了简单起见:

unsigned char unpacked[128];  // read file input into this buffer
unsigned char packed[128];    // copy from unpacked to here while compressing
                              // then write() this to output file...

要执行压缩本身,需要循环读取到unpacked中的字节数,并使用位运算符,如&(位AND)、|(位OR)、<<位左移。

相关问题