ファイル内検索を速く行うには?

解決


KAZE  2005-06-15 19:07:09  No: 90465

Win2000、VB.NETです。
固定長のテキストファイルの中から、
一致する文字列を見つけるというプログラムなんですが、
データが20000行近くあり、DO〜LOOPを使用すると、
対象の列が最初と最後の場合で、検索時間に
大きな幅ができてしまいます。
何か良い解決方法をご存知の方、ご教授願います!


ねろ  2005-06-15 20:38:14  No: 90466

検索してその後どうするかにもよるのですが、
ファイルから文字の検索となると、
DosのFindが速いのだが。。。


KAZE  2005-06-15 20:50:11  No: 90467

>ねろさん
アドバイスありがとうございます。

>検索してその後どうするかにもよるのですが、
テキストからデータを引っ張り出してきて、
VBで作成した画面上に項目毎に貼り付けていきます。

書き忘れですが、検索対象の部分が
昇順で並べられているので、二分法など
使えないでしょうか。。。


0123  2005-06-15 21:06:18  No: 90468

こんなプログラムでテストしてみました。
20万件の最後で一致するようにデータを作りました。
結果1秒もかからないですよ。

  Dim a(200000) As String
  Dim i As Long
  
  For i = 1 To 200000
    a(i) = "number" & Format(i)
  Next
  
  Debug.Print Now
  For i = 1 To 200000
    If a(i) = "number200000" Then
      Debug.Print a(i)
      Exit For
    End If
  Next
  Debug.Print Now

PCのスペックはPentium4 2.53GHz メモリは512MB DDRです


KAZE  2005-06-16 00:40:46  No: 90469

>0123さん
ありがとうございます。

申し訳ないのですが、今回はファイルI/Oでして。。。
1行目と20,000行目では、
5秒くらいの差がついてしまうのです。


0123  2005-06-16 00:50:35  No: 90470

まだまだ書かれていない仕様がありそうですね。
他に条件があるのであれば先に書いておいたほうがいいですよ。

例えば文字列の部分一致を考慮するのか完全一致のみとするのか
データの書式が決まっているのかないのか等々...

後から小出しの条件は回答する側にとって2度手間になります。


もげ  2005-06-16 03:05:14  No: 90471

こういうのはgrepとかfindstrなどのツールを使うほうがVBより速いかも。

Line Input # で1行づつ読んでるのなら...
メモリに余裕あるなら、GetとかFileSystemObjectのReadAllでメモリ上に展開してからモロモロの処理を行うとか、
とりあえず、何行目か決まっているのであれば、
テキストファイルの指定行を瞬時に読込む    
http://www.bcap.co.jp/hanafusa/VBHLP/FSO13.htm
とか、

あと、PCのスペックにも激しく依存するので、
ターゲットになるマシンスペックと、目標タイム(何秒以内)とか
が具体的になれば、「燃え」られる人も出てくるかもしれない(^^;。


ささ  2005-06-16 06:44:02  No: 90472

目標タイム(何秒以内)よりも、改善"率"が重要。

今30分かかっている処理で、
そのうち一部の処理で25分かかっています。その処理を20%改善して
20分に...とかさ
性能改善としてはそうゆう情報の方が俄然、燃える。

何%の改善を目標としているの?性能改善のために、
工数はどれほど割けるの?それによってアプローチの仕方も変わります。

たとえそれが10秒の短縮だとしても
1%の改善を行うのに2日も3日もそれだけに時間をかけてられないでしょ?
普通は?

#っとちょっと内容が真面目すぎて面白みが無かったかな?


ねろ  2005-06-16 18:02:21  No: 90473

ファイル上のデーターが固定長で、ソートされているのなら、FileStreamクラスの
Seekメソドと、BinaryReaderクラスのReadChars等を使って、二分木検索をすれば
いいのでは。
又は検索が複数回行われる場合は、最初に一旦全てのデーターを読み、検索にかかわる
頭の数文字分を配列データーに入れておいて、検索時は先ず配列から該当の文字
拾い出して、一致するデーターだけ配列のインデックスをKeyにファイルから読み込む
等の方式もありかな。

ファイルから文字列を検索する場合、ハードディスクや、ネットワークからデーターを
読み出す訳ですから、データーが何行有るというよりも、ファイル全体の大きさが、
処理時間に関しては支配的になります。
たとえば、
『80バイトの固定長データーがソートされて20,000行程度、ファイルに保存されています。
この中から複数回文字を検索するのですが、現在ファイルの頭から一行ずつ読み込んで
検索しているので、検索文字がファイルの最後の方に有ると5秒程度かかってしまいます。
これを革命的に短縮する方法を。。。。。』等と書けば判りやすいのでは。
更に、データーの形式は
ID=XXXXXXXXXX NAME=YYYYYYYYYY ...  
X,Yは半角英数字、改行付き
などと書けば親切。

マシンスペックに関しては、データーが保存されているメディアの読み出し速度、
たとえばハードディスクに保存されているので有れば、ハードディスクのスペックが、
ネットワーク上のファイルであればであれば、ネットワークのスピードが処理速度に
関しては支配的になります。

ハードディスクはUltra ATA/100 、シークタイム8 ms avg
フォーマット方式ははNTFS...
等と書くのは少々行き過ぎ。。。


夏の朝も天玉うどん  2005-06-19 02:45:39  No: 90474

>>検索してその後どうするかにもよるのですが、
>テキストからデータを引っ張り出してきて、
>VBで作成した画面上に項目毎に貼り付けていきます。

例えば以下のようなことであればファイルを1回パスするだけでおこなえます。(ファイル内が昇順に並べ替え済みとして)
品番に対する価格を求めるような例

品番                      価格(本当はこの時点では不明)
jj-123456          5.500
xx-123456          6.600
dd-123456               4.800
aa-123456               5.700
のようなものを求めたいと仮定すれば品番側をソートし

品番                      価格(これを求める)
aa-123456               5.700
dd-123456               4.800
jj-123456          5.500
xx-123456          6.600
とすれば品番  aa-123456  が見つかった位置から次の品番  dd-123456  を検索
すればよいのでデータのファイルを1回パスするだけで済みます。
あくまで仮定の話ですが、使えるようなら他の高速化技法と合わせて検討してください。


KAZE  2005-06-21 01:43:47  No: 90475

>ご回答下さった皆さん

様々なご意見ありがとうございます。
『検索を速くする』だけでは曖昧すぎたんですね。。。
特に >さささん のご意見には、なるほど、と思いました。

今回の条件は、ほとんど >ねろさんの仰るとおりで、

>80バイトの固定長データーがソートされて20,000行程度、ファイルに保存されています。
>この中から複数回文字を検索するのですが、現在ファイルの頭から一行ずつ読み込んで
>検索しているので、検索文字がファイルの最後の方に有ると5秒程度かかってしまいます。
>これを革命的に短縮する方法を。。。。。

このうち、80バイトでなく150バイトで、後は一緒です。

>ねろさん のアドバイスを参考にさせて頂き、FileStreamクラスの
Seekメソドを使用した二分木検索を採用し、最大5秒掛かっていた処理を
3秒に短縮することができました。

アドバイス頂いた皆様、特に >ねろさん 、有難う御座いました。


KAZE  2005-06-21 01:44:30  No: 90476

解決チェック忘れました。。。


ねろ  2005-06-21 17:24:42  No: 90477

ランダムファイルを二分木検索で読み込む方法は
それはそれである程度のブレーク・スルーで有ると思いますが、
一行150Byteで20,000行程度ならせいぜい3Mbyteですね。
この程度のファイルであれば、一度に読み込んでON MEMORY
で処理した方が、速くて簡単だと思います。
私の環境の中で非力そうなコンピューターで試しても、全て配列に
読み込むのに0.8秒、Instrを使った最後の方の検索で、0.02秒です。
時間がかかっているのは、読み込みではなく、文字列の処理の方では
無いのでしょうか。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加