2009/04/19(日)続・UOのジャーナル保存
久しぶりに C を書きたくなったので、ミソな部分+αを書いてみた。
- シングルバイトな<LF> を取り除いて
- 諸悪の根源を除去
- <CR> も邪魔なので取り除いて
- ついでに <LF> が連続する場合も取り除いちゃう
後は
- UTF-16-LE な文字コードを UTF-8 か Shift-JIS に変換
- マルチプラットフォームで文字コード変換できるライブラリってあるんかな
- 処理結果をファイルに保存
- 10行くらいの追加でとりあえず OK
UO のジャーナルファイルは一度のゲームで数百KB 程度になるらしいので、一度に処理するバッファのサイズは 128KB くらいがちょうどいいのかなぁ。
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
int main(int argc, char **argv)
{
char *file, *buf, *newbuf;
int index, newindex, lfflag, lfappered, crflag;
FILE *filep;
size_t bufsize = 1024 * 128; /* 128KB でいいかな? */
size_t gottenbuf;
if (argc < 2) {
fprintf(stderr, "Please indicate an UO\'s Journal.\n");
}
filep = fopen(argv[1], "r");
if (!filep) {
fprintf(stderr, "%s could not be opened.\n", argv[1]);
exit(-1);
}
buf = malloc(sizeof(char) * bufsize);
newbuf = malloc(sizeof(char) * bufsize);
memset(newbuf, 0x00, bufsize);
memset(buf, 0x00, bufsize);
crflag = lfflag = 0;
while (gottenbuf = fread(buf, sizeof(char), bufsize, filep)) {
newindex = 0;
for(index = 0; index < gottenbuf; index++) {
if (buf[index] == 0x0d) {
lfflag = 1;
} else if (lfflag && buf[index] == 0x00) {
/* 前のバイトが 0x0d かつ今見てるものが 0x00 なら 0x0d00 を挿入 */
if(lfappered) {
/* <LF> が連続している場合は読み飛ばす(何もしない) */
lfflag = 0;
lfappered = 0;
} else {
newbuf[newindex] = 0x0d;
newindex++;
newbuf[newindex] = buf[index];
newindex++;
lfflag = 0;
/* 一文字前は <LF> だったことを示すフラグを立てる */
lfappered = 1;
}
} else if (buf[index] == 0x0a) {
/* <CR> は いらない子 */
crflag = 1;
lfappered = 0;
} else if (crflag && buf[index] == 0x00) {
crflag = 0;
lfappered = 0; /* 実際はここでフラグ立ってることはないはず */
} else {
/* 改行文字以外の文字は普通に読み込む。かつ各フラグクリア */
newbuf[newindex] = buf[index];
newindex++;
lfflag = 0;
crflag = 0;
lfappered = 0;
}
}
fwrite(newbuf, sizeof(char), newindex, stdout);
memset(newbuf, 0x00, bufsize);
memset(buf, 0x00, bufsize);
}
close(filep);
free(buf);
free(newbuf);
}
自分でバッファを切り出して~とかバッファが変なところで切れた場合にどうするか~とか Perlだと考えないので面白かった。