RLE(ランレンングス)法はわかりやすいなあ。
1B 1B 1B 1B 2C 2C 33 98 98 98
というデータを
04 1B 02 2C 01 33 03 98
というような、データとそれが連続して出た回数で書き記すような方法をランレングス法(RLE)と呼びます。
でも少し考えるとわかることがありまして。連続出現が0回のデータなんて出てこないですよね。あと、1回と2回の場合は別にこの方法をやっても小さくならないし。とかいうことで、もうちょっと工夫もできそうですね。
とりあえずなんも工夫せずに、
回数(1byte) データ(1byte)
の連続形式にエンコードするプログラムを書いた。
enc.c。標準入力から得たデータをRLEにかけて標準出力にあうとぷっと。
#include <stdio.h> int main(){ unsigned char buf[2], count; count = 1; fread(&buf[0], 1, 1, stdin); while(fread(&buf[1], 1, 1, stdin) != 0){ if(buf[0] != buf[1] || count == 255){ fwrite(&count, 1, 1, stdout); fwrite(&buf[0], 1, 1, stdout); count = 1; } else { ++count; } buf[0] = buf[1]; } return 0; }
dec.c。標準入力から得たRLEなデータを復号して標準出力に。
#include <stdio.h> int main(){ unsigned char buf, count; while(fread(&count, 1, 1, stdin) != 0){ fread(&buf, 1, 1, stdin); for(;count>0;--count) fwrite(&buf, 1, 1, stdout); } return 0; }
こんなんを
% gcc enc.c -o enc % gcc dec.c -o dec
コンパイルして、
% cat hoge aaaaaaabc aaaabbbbbbbbccccc ccccccccccccaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbeeeeee aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa % cat hoge |./enc >hoge.rle % ll hoge* -rw-r--r-- 1 sun31048 J03A 135 Nov 19 20:16 hoge -rw-r--r-- 1 sun31048 J03A 30 Nov 19 20:17 hoge.rle % rm -f hoge % ll hoge* -rw-r--r-- 1 sun31048 J03A 30 Nov 19 20:17 hoge.rle % cat hoge.rle |./dec >hoge % ll hoge* -rw-r--r-- 1 sun31048 J03A 135 Nov 19 20:17 hoge -rw-r--r-- 1 sun31048 J03A 30 Nov 19 20:17 hoge.rle % cat hoge aaaaaaabc aaaabbbbbbbbccccc ccccccccccccaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbeeeeee aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
できたー。
% cat jpn.txt |./enc >jpn.txt.rle % ll jpn.txt* -rw-r--r-- 1 sun31048 J03A 231295 Nov 19 19:16 jpn.txt -rw-r--r-- 1 sun31048 J03A 443822 Nov 19 20:19 jpn.txt.rle
うはー、これはひどい。