ファイルの中を検索するには?


神無月  2008-01-10 09:58:52  No: 138577  IP: 192.*.*.*

指定したファイルを一行ずつ文字列を読み込み、読み込んだ文字列の中に調べたい文字が入っているかどうかというのを行いたいのですが、行うことが出来るのでしょうか?

例えば・・・
一行読み込んだ・・・おはよう
調べたい文字・・・おは
一致していればファイル名を表示
一致していなければ、次の行を読み込み同じ事を繰り返す

というようなプログラムです。

編集 削除
魔界の仮面弁士  2008-01-10 10:20:36  No: 138578  IP: 192.*.*.*

どこまで出来ていて、どこで躓いているのかを明確にした方が、
適切な回答がつくかと思いますよ。

(1) 開発環境はどうなっていますか?
  (VB2008、VB2005、VB6、VBScript、Access VBA など)

(2) 読み込むファイルとは、どのような形式のものですか?
  (Shift_JISテキスト、UTF-8テキスト、Excelファイルなど)

(3) そのファイルを読み込む方法は、調査済みですか?

(4) ファイルの内容を、行単位に読み込む(または、全部読みこんでから
  行単位に切り分ける)ことはできていますか?

(5) 読み込んだ行から、特定の文字列を検索する方法は分かりますか?


> 指定したファイルを一行ずつ文字列を読み込み、
>(中略)
> 一致していればファイル名を表示
行の内容や行番号ではなく、ファイル名を表示させるということは、
もしかして、複数のファイルを読み込もうとしているのでしょうか?

編集 削除
神無月  2008-01-10 10:36:35  No: 138579  IP: 192.*.*.*

回答ありがとうございます。

(1)VB2005
  
(2) Shift_JISのファイルやExcelファイル、パワーポイントやPDFのファイルなどほぼ全てのファイルを考えています。

(3) はい。
Dim Reader As IO.StreamReader
Reader = New IO.StreamReader(FileName, Encode)
TextBox2.Text = Reader.ReadLine
これを使用する予定です。

(4) 行単位に読み込むのはReadLineで出来ると思います。
    全部読み込んだのを行単位にすることはできていません。

(5) if文とLikeを使用する予定です。
if TextBox2.Text Like TextBox1.Text Then
で出来ないでしょうか?

出来ればですが、表示形式として、
ファイル名:行番号
という感じに表示できればよいと思っています。

編集 削除
魔界の仮面弁士  2008-01-10 11:17:30  No: 138580  IP: 192.*.*.*

> Shift_JISのファイルやExcelファイル、パワーポイントやPDFのファイルなどほぼ全てのファイルを考えています。
「ほぼ全て」ではなく、きちんと列挙してみましょう。
ファイル形式によって、データの処理方法は異なりますから、
それぞれのファイルごとに、読み取り方法を切り替えねばなりませんので。

> Reader = New IO.StreamReader(FileName, Encode)
> TextBox2.Text = Reader.ReadLine
この方法が使えるのは、テキストファイルだけです。
Excel, PowerPoint, 圧縮済PDF 等には使えません。

とりあえず、テキストファイルの行検索から実装を始めてみては如何でしょう。

> 行単位に読み込むのはReadLineで出来ると思います。
行単位に読み込むという事は、複数の行を繰り返し処理するための
ループ処理を実装する必要があるわけですが、それについては
大丈夫だということですね。

> if TextBox2.Text Like TextBox1.Text Then
> で出来ないでしょうか?
TextBox1.Text = "*おは*" などのように、ワイルドカードの
指定までユーザにやらせるつもりなら、確かに Like でもできますが、
Like 演算子は、検索式の構文を間違えるとエラーになりますし、
ワイルドカードのエスケープ処理の手間などを考えると、この場合は、
String.IndexOf メソッドか、InStr 関数を使った方が扱いやすいかと。


で…肝心の「わからない部分」はどこなのでしょうか?

編集 削除
神無月  2008-01-10 11:22:24  No: 138581  IP: 192.*.*.*

すみません。
複数の行を繰り返し処理するためのループ処理ができないのです。
StringIndexOfメソッドとInStr関数はどのようにしようするのでしょうか?

それぞれのファイルごとに処理が違うということは、ExcelやPDFでも同じような処理を行うことができるということでしょうか?

編集 削除
魔界の仮面弁士  2008-01-10 12:11:24  No: 138582  IP: 192.*.*.*

そもそも、読み込んだデータを TextBox2 に表示させているのは何故でしょうか?
検索だけが目的なら、String 型変数に受け取るだけで十分な気がしますよ。

> 複数の行を繰り返し処理するためのループ処理ができないのです。
質問は具体的にお願いします。

(1) ループ処理を行うための命令がわからないのでしょうか?
  → Do 〜 Loop ステートメントについて調べてみてください。

(2) 使うべき命令は分かっているのに、自分で書いたコードでは
  期待通りの結果にならないのでしょうか?
  → どのようなコードを書いているのか、提示してみてください。


なお、
> ファイル名:行番号 という感じに表示できれば
のような行単位の処理ではなく、
> 一致していればファイル名を表示
のように、ファイル全体からの検索であれば、ループ処理せず、
My.Computer.FileSystem.ReadAllText 等を使って、ファイル全体を
一度に読み込んだ方が、処理の手間が省けるかと。


> StringIndexOfメソッドとInStr関数は
StringIndexOf メソッドではなく、
String.IndexOf メソッドです。

> どのようにしようするのでしょうか?
それはヘルプを見て、実際に試してみてください。

ヘルプの記述の中で分かりにくい部分があれば、その箇所を
具体的に提示してもらえれば、解説しますよ。

> ExcelやPDFでも同じような処理を行うことができるということでしょうか?
「ファイルの内容を読み込む」までの処理方法は全く異なりますが、
データを String 変数に読み込んだ後の、「検索」の処理方法は
同じコードにすることができるかと思いますよ。

たとえば、Excel ファイルの場合は、こんな感じ。
読み込みと書き込みの両方のサンプルです。
http://support.microsoft.com/kb/302094/ja

なお、上記はオブジェクトの解放が抜けているので、下記の記事も追加参照。
http://www.microsoft.com/japan/msdn/vbasic/migration/tips/office.aspx


PDF の場合、非圧縮形式の場合は、単なるテキストファイルなので、
一応、そのまま読み込めるでしょう。実際にはタグの切り出し処理が面倒ですが。
http://web.archive.org/web/20040219153805/http://www.kobu.com/docs/pdf/pdfxhand.htm


なお、条件が多少限定されますが、インデックス サービスのフルテキスト検索を行う方法もあります。
この場合、ファイル形式を問わず、同じ処理方法が使えますよ。

下記は ASP.NET の例です。
http://support.microsoft.com/kb/820105

# あとは、Google Desktop Search API を使うとか。

編集 削除
神無月  2008-01-10 12:18:34  No: 138583  IP: 192.*.*.*

Do Loopは一応わかります。
Do Loopで繰り返す時に条件をファイルの最後まで繰り返すという場合に最後まで繰り返すという条件をどのように書くのかわかりません。

Do ファイルの最後まで
    TextBox2.Text = Reader.ReadLine
Loop

と実行するとReader.ReadLineは1行目、2行目と次々読み込むのでしょうか?

編集 削除
神無月  2008-01-10 12:22:32  No: 138584  IP: 192.*.*.*

ちなみに、全文読み込んでから一致している行数を取得するときはどのようにしたらよいのでしょうか?

編集 削除
魔界の仮面弁士  2008-01-10 13:11:49  No: 138585  IP: 192.*.*.*

> 最後まで繰り返すという条件
StreamReader クラスのメンバを、ヘルプで調べなおしてみてください。
「末尾に到達したら True を返す」プロパティが見つかるかと思います。

> 全文読み込んでから一致している行数を取得するときは
たとえば、改行コードが CrLf なら、
  Dim lines() As String = Split(全文, vbCrLf)
とすれば、行ごとの配列にできるので、これを列挙して捜索するとか。

編集 削除
神無月  2008-01-10 13:52:28  No: 138586  IP: 192.*.*.*

末尾に到達したら True を返すプロパティとはEndOfStreamでしょうか??
これを使用してみようとしたのですが、EndOfStreamがないようなんですが・・・

列挙して検索するというのはどういうことでしょうか?
lines分繰り返すとよいということでしょうか?
for i = 0 to lines.Length
のように。

編集 削除
神無月  2008-01-10 13:52:29  No: 138587  IP: 192.*.*.*

末尾に到達したら True を返すプロパティとはEndOfStreamでしょうか??
これを使用してみようとしたのですが、EndOfStreamがないようなんですが・・・

列挙して検索するというのはどういうことでしょうか?
lines分繰り返すとよいということでしょうか?
for i = 0 to lines.Length
のように。

編集 削除
魔界の仮面弁士  2008-01-10 14:12:45  No: 138588  IP: 192.*.*.*

> 末尾に到達したら True を返すプロパティとはEndOfStreamでしょうか??
その通りです。

> これを使用してみようとしたのですが、EndOfStreamがないようなんですが・・・
スペルミスか、あるいは別のオブジェクトのプロパティを参照していませんか?
どのような記述になっているか、実際のコードを提示してみてください。

> lines分繰り返すとよいということでしょうか?
その通りです。

> for i = 0 to lines.Length
惜しいっ。「To lines.Length」ではなく、「To lines.Length - 1」ですね。

編集 削除
YuO  2008-01-10 15:18:32  No: 138589  IP: 192.*.*.*

> 最後まで繰り返すという条件
私はStreamReader.ReadLineが末端でNothingを返すことを利用して判断することを好みますね。
まぁ,基本的には嗜好の違い程度だとは思いますが。
# 根がCな人はこっちの方の記述になるのかも。

編集 削除