ハフマン符号をファイルに保存したい。これどうやってするの?ハフマン コードを文字列に保存していますが、生成されたファイルのサイズが元のファイルよりも大きくなります。
3 に答える
非常に簡単な方法は、次のように一度に 1 ビットずつ書き込むことです。
unsigned char acc; // Accumulator of bit waiting to be written
int bitcount; // How many bits are aready present in the accumulator
// write a single bit (0/1)
void writebit(int bit)
{
acc |= (bit << bitcount);
if (++bitcount == 8)
{
writebyte(acc);
acc = 0;
bitcount = 0;
}
}
少しだけ読み返す手順は対称的です
unsigned char acc; // bits waiting to be extracted
int bitcount; // how many bits are still available in acc
int readbit()
{
if (bitcount == 0)
{
bitcount = 8;
acc = readbyte();
}
--bitcount;
return (acc >> (7 - bitcount)) & 1;
}
もちろん、これは最も単純な方法ですが、エンコードされたデータを正しく保存してロードできるようになるまで、コードの速度について心配することはありません。
例:
次のハフマン符号化された記号があるとします。
A - 0
B - 10
C - 110
D - 111
そして、シーケンスをエンコードしたい
A B A A C D A D B B
次に、順番に呼び出します
writebit(0); // A
writebit(1); writebit(0); // B
writebit(0); // A
writebit(0); // A
writebit(1); writebit(1); writebit(0); // C
writebit(1); writebit(1); writebit(1); // D
writebit(0); // A
writebit(1); writebit(0); // B
writebit(1); writebit(0); // B
したがって、書き込まれる実際のバイト数は次のようになります。
(01100010) = 0x62
(01010111) = 0x57
(表示されているコードは最下位ビットから始まることに注意してください。つまり、記号を認識したい場合は、括弧内のビット シーケンスを右から左に読む必要があります)。
あなたが保存しているのは 1 と 0 の文字列だと思います。真のハフマン コードは、バイナリで保存し、後で解析する必要があります。出力を単に文字列として保存するだけでは、ハフマン コードの目的が無効になります。各 0 と 1 は 1 ではなく 8 ビットです。
おそらく、各パターン/文字のバイト全体を保存しています。
e が最も一般的な文字であるとしましょう。ビットパターンは 0 になります。
z が最も一般的でない文字で、1 で始まるパターンがあるとしましょう。1111 111 に割り当てましょう。
書き込みたいファイルは次のようになります。
0111 1111
あなたはおそらくこれを書いています:
0000 0000 0111 1111.
これを行うには、ビット演算を利用する必要があります。