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だと考えないので面白かった。