先日はお世話になりました。
また質問させていただきます。度々すみません。Del6personal使用です。
サイズが大きいテキストファイル(数十メガバイト)がありまして、
[名前a]
あああああ
あああああああ
abcde
[end]
[名前b]
いいいいい
いいいいい
[end]
[名前c]
ううう
ううう
uuuuu
ううう
[end]
・
・
・
[名前aaaaaa]
おおお
[end]
のような状態になっています。
([名前○]から[end]が一対で、これが大量にあります)
この中から
ある場合は[名前a]〜[end]までのデータ
ある場合は[名前b]〜[end]までのデータ
ある場合は[名前c]〜[end]までのデータ
を利用したいのですが。
現在は、Readlnで上から全ての行をposで名前を見て判断しています。
これですと、上のほうにあるデータはいいのですが、
下にあるほど時間がかかってしまいます。
こういう場合はどうように処理するのがよいのでしょうか?
よろしくお願いします。
TMemIniFileを使ってみてはどうでしょう?
本来
[a]
b=c
b=c
みたいな形式(iniファイル形式)のファイルを読み取るためのものですけど、
[a]をセクションと見立てて、
ReadSectionをつかえば、読み取ることはできると思います。
詳しい使い方はヘルプで。
ただし、[end]はほかのセクションとみなされるので、
読み込むことはできません。
あと、書き込みはその方法ではできません。
どうしても書き込みたい場合は、別の方法を考えたほうがいいでしょうね。
複数のテキストファイルを、ひとつにまとめるような。
メガ単位のファイルはさすがに試したことがないので、
どうできるかわかりませんけど。
メモリに余裕があるなら、TStringList, THashedStringList, TMemIniFile 等
で一気にメモリに読み込んで処理するのが速いでしょう。
たかみちえさんも書かれているように読むだけならTMemIniFileが手軽ですね。
読み書きするのならD6から導入されたTHashedStringListが良いと思います。
(TMemIniFileは内部的には、THashedStringListが使われているそうです。)
メモリに全部読み込むのはちょっと、と言う場合は、
初めに、インデックスを作っておくという手法があります。
手順としては下記のような感じです。
Readln で1行ずつ読み込みながら、[名前○]が見つかったら、名前とファイル
ポジションをTStringListまたはTHashedStringListに「名前○=ファイルポジ
ション」のように格納しておく。
検索するときは、名前を IndexOfName で検索して、ファイルポジションを読み
出し、ファイルポジションへ移動して、BlockRead か、TFileStream.Read で
ファイルから読み込む。読み込むサイズは、次のファイルポジション−現在の
ファイルポジションで取得する。
インデックスととして作ったTStringListは、ファイルとして保存しておけば、
次からそれを読み込むだけでインデックスとして利用できます。
書き込みもさせます。
と、メモリに全部読み込むのはちょっと。なので、
THashedStringList使ってやってみます。
お二方レスありがとうございました。
書き込みもするとなると、
追加だけならいいですが、途中に挿入したり、途中のデータの長さが変化する
場合、それ以降のデータを移動させる必要があるので、メモリに読み込まずに
やろうとすると結構大変です。
数十メガバイトの書き込みがそのたびに発生することになります。
挿入するデータでもディスク上では追加にしておいて、
適当なタイミングでまとめて書き込むとかの工夫が必要になってきます。
並び順はインデックスで管理することになります。
その場合、ファイルポジションだけでなく、サイズも格納しておく必要が
でてきます。
できるのなら、ファイルをセクション毎に分割して、管理した方が、
楽だと思います。
ツイート | ![]() |