いつもお世話になっております。
たくさんのCSVファイルを順にオープンして中身を取得するプログラムを作成したいです。
1つのCSVファイルは10行30列程度の小さなものです。
ただし、ファイル数はだいたい3000程度となります。
現在デバッグで下のサンプルコードの4行目のusing (StreamReader readCsvObject = new StreamReader(openFileDialog.FileName))
を実行するだけで8ms程度かかってしまいます。そのため8×3000でこれだけで24秒程度かかってしまいます。
ファイルオープン後の処理の時間に関しては特に問題ありません。
何かほかに早くオープンできる方法はないでしょうか?
よろしくお願いいたします。
for(int i=0;i<3000;i++){ FileName=List[i]; using (OpenFileDialog openFileDialog = new OpenFileDialog()) { openFileDialog.FileName =FileName; using (StreamReader readCsvObject = new StreamReader(openFileDialog.FileName))//この行の時間がかかる { while (!readCsvObject.EndOfStream) { var readCsvLine = readCsvObject.ReadLine(); } } } }
> using (StreamReader readCsvObject = new StreamReader(openFileDialog.FileName))
> を実行するだけで8ms程度かかってしまいます。そのため8×3000でこれだけで24秒程度かかってしまいます。
そこを3000回もループするコードじゃないけども。
(ループしてるのはEndOfStreamとReadLine)
どうやって計測したの?
すみません。このコードは一部抜粋で
ファイル名の部分が変数でそこを変えながら実行してます。
計測自体はUsingの前後でDatetimeで時間を計測してます。
また、VisualStudioでデバッグモードでの各行の実行時間を確認しながら行いました。
片っ端からTaskに放り込んでしまえばいいような
実際に一行のファイルを 3000 作ってやってみましたが、1 秒もかかりません。
問題が回答者の手元で実際に再現するコードを作成してください。
もちろん、メディアがネットワークドライブとかフロッピーディスクとかいうことはないでしょうね?
ちなみにOpenFileDialogは必要なんでしょうか?
必要だとしてもDispose必要ない子なんでusing外したほうがいいと思うんですが。
実際に内容を読み込んで処理する時間で8ms以上かかりそうな気がしますが、そちらが無視できるならStreamReaderの作成含めて無視できる時間になるような気がします。
Zuishinさん
現在のテスト環境は普通にデスクトップ上でやってます。
実際は、ネットワーク上のフォルダへのアクセスをするので、もっと遅くなると思います。
Zuishinさん
下の方のコメントにもありましたが、不必要でした。こちらは省きます。
> ネットワーク上のフォルダへのアクセスをする
速度に思いきり影響ある部分じゃないですか。そういう重要な情報は質問に必ず記載してください。
radianさん
最終的にはそうなるので、それが原因での速度低下は許容するつもりでした。
現在のデスクトップ上での実験でも遅いので、何か原因がわかればと思っています。
この参照先のCSVファイル読み込みという部分はどうしても変えられないため今の形で行いたいです。
gentaroさんの回答のReadAllLinesでやった場合、変化はありましたか?回答に対してきちんとコメント付けて下さい。ディスクIOの影響も当然あるので、そういったデータも出した方が良いかと思われます。
速度改善は細かい最適化の積み重ねなので、ボトルネックの調査が最重要です。
radianさんn
本人の方が追記をしてくれたので、そちらはやってません。
中身の読み込み速度ではなく、オープン部分の速度が現状問題です。
ネットワーク越しなら、単純にファイルはネットワーク側で開いて、必要なデータだけをネットワーク越しにやり取りすればいいと思います。
それができない理由がありますか?
あるなら、そもそもどのような環境で何をしているのか、状況を詳しく説明してください。
どのみち、デスクトップ上で行って 24 秒というのは、このコード以外の条件をこちらで普通に補う限りあり得ません。何か特殊なことをしているか、コードが違うはずです。
コードが違うというのは、これが実際に計測するコードから不要な部分を取り除いたものであるなら、その取り除いた部分に問題がある可能性があるということです。なので、問題の再現する最小限のコードを作り、それで再現することを確認した上で掲載してください。
そもそも「この行」で時間がかかっていることはどのようにして確かめたのかも書いてください。
それが間違っている場合、本当は読み込み部分で時間がかかっている可能性もあります。
試しにデスクトップのフォルダに10行30列のCSVを3000個作ってforループで1個ずつ開く→中身を読む→閉じるを繰り返したけど3秒も掛かってないですね。開くだけで24秒はプログラムがどうとか以前の話だというのは完全に同意です。
みなさんご意見ありがとうございます。
自分も試しに全く別で、ファイルをオープンするだけのプログラムをデスクトップ上に作ってみましたが、
確かに20秒とかかからないですね…
実際に使用しているプログラムでスレッド処理などしてはいないのですが…
ちなみにHDDに置いても時間はあまり変化なしでした。意図的にCPU負荷をかけて使用率100%を維持したら流石に伸びましたけどそれでも20秒はいってないですね。
問題を解決したいはずの人になぜか全部スルーされてるけど、質問のコードはそもそもループの中で無駄に OpenFileDialog を操作しているので、なぜこんな意味不明なことをしているかわからない。
「実際はしてない」というのであれば、もう一度書くけど、質問者と回答者がコードを共有できるよう、問題の再現する最小のコードを作って掲載すべき。
と書けば他のを忘れてここだけに反応しそうな気がするが。
そもそも質問文の論点が間違っている(要旨に沿った最小コードで再現しない)のであれば、この質問は無意味なんですけども、これ以上どうしたいんでしょう。