テキストを最終行から取得する方法

[戻る]
spling 2006/10/30(月) 16:31:26
テキストファイルの最終行から1行ずつ取得する方法を探っています。

今考えているのは、
 @最初から順に読み込み、一行ずつCStringArrayに取り込んでから
   最初と最終をいれかえる。
 ASeekToEnd()で参照点を移動し、その後は CR/LFを検索しながら
   一行ずつ前に参照点を移動し読み込む
の二つです。

もっと他にいい方法がありそうな気がするのですが、
知識不足で思い浮かびません。

どなたかご存知の方、他にいいアイデアをお持ちの方が
いらっしゃいましたらご教授くださいませんでしょうか。
 
WindowsNT VC6.0 MFC使用

PATIO 2006/10/30(月) 17:18:30
丸付き文字は機種依存文字なのでWEB上の投稿に使わないほうがいいです。
使うなら(1)とか自分で打った方がいいです。

取り出せれば良いのであれば、1の方法で取り出しの時に最後から取り出せば
良いだけなので配列上で並べ替える必要はないと思います。
むしろファイルに書き戻すような場合を考えるとそのままにしておいて
逆順に取り出すメンバー関数でも作った方が良いのではと言う気もします。
2の方法でも良いとは思いますけれど、一々CR/LFをチェックしながらの
読み込みになって面倒なわりに恩恵が少ないし、コードもわかりにくくなりそうです。

あと、目の覚めるようなアイディアを求めているのであれば、
そういうアイディアはそうそう出てこないと思いますよ。
基本に忠実に作ってあった方が他の人がソースを見た時に理解しやすいと思うので
メンテナンス性を考えたらあんまり技巧に走らない方が良いです。

超初心者 2006/10/30(月) 17:23:56
テキストファイルが巨大なら(2)だな。

(2)って以下の事でしょ。
動作確認はしていないのでミスはあると思う。

ファイルの最後から1MB先頭へ移動した位置へシークする。
1MB読み込む。→char * buffer[〜];
buffer[1MB]=0;
改行を検索し改行の次のアドレスを配列にぶっこむ。→char * p[1MB];
buffer[0]は行の途中かもしれないので無視。

改行がN個見つかったとして
for(i=N-1;i>=0;--i)
{
使いたいものはp[i]だ。
p[i][-1]=0; // 0終端文字列にする
}

更に先ほどより1MB先頭へ移動した位置へシークする。
1MB+(p[0]-buffer)読み込む。→char * buffer[〜];
buffer[1MB+(p-buffer)+1]=0;

ファイル先頭に到達していなければ繰り返す。
欠点として改行を含めた1行が1MBより大きいとき誤動作するという点だ。

最後はbuffer[0]だ。

ところでこれってマジかよ
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200310/03100009.txt

超初心者 2006/10/30(月) 17:27:25
訂正

ファイル先頭に到達していなければ繰り返す。
ファイル先頭に到達したら先頭行bufferを忘れずに。

欠点として改行を含めた1行が1MBより大きいとき誤動作するという点だ。

PATIO 2006/10/31(火) 10:03:47
(2)は、文字通り、一文字ずつ読み込んでチェックしつつ文字数をカウントし、
ファイルポインタをファイルの先頭方向に移動して前の行の改行が見つかったら
その次の位置からカウントした文字数分だけ読み込むと言う事かと思ってました。
一文字ずつ読み込むならファイルのサイズはあんまり関係ないかもしれません。
まあ、あまりに大きいファイルだと読み込みきれないかもしれませんけれど。
メモリマップドファイルで扱った方が楽かもしれませんね。
これだとシークとか特に意識しないで良さそうですし。

蛇足
> ところでこれってマジかよ
> http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200310/03100009.txt
これは別にスレを立ててやった方が良さそうな気がしますけれど。

spling 2006/10/31(火) 17:30:57
[[解決]]
他の方法もいろいろと探ってみたのですが、
結局、ファイルサイズの増加を見込むと(2)の方法がニーズにあっている
ようです。
(2)の方法を採用することにしました。

みなさんありがとうございました。

古いスレッドには追加発言できません。