none
CSVファイルのレコードを指定して読込む RRS feed

  • 質問

  • CSVファイルから任意のレコードを取得するために下記の処理を組んでいます。

    =ソース============================================

            Dim Read As String          '読込んだレコードのデータ
            Dim Get As String           '任意のレコードのデータ
            Dim Record As Integer = 0   '読込み中のレコード
            Dim Target As Integer = 100 '任意のレコード'

            Dim sr As New StreamReader("読込み対象のCSVファイル.csv", System.Text.Encoding.GetEncoding(932))
            Do
                Record = Record + 1
                If sr.EndOfStream = True Then
                    Exit Do
                End If
                Read = sr.ReadLine                  '' 現在のストリームから1行文字を取得
                If Record = Target Then             '' 任意のレコードのデータを読込んだ場合
                    Get = Read                      '' レコードのデータを保持
                    Exit Do                         '' データを保持したのでループを抜ける
                End If
            Loop
            sr.Close()

            ' Getに任意のデータが格納される

    ===============================================

    上記のソースでは、対象のCSVファイルに1万レコード以上データがあり、9000レコード目のデータを取得するとなると1レコード目から9000レコード目までの9000回レコードを読込む必要があります。結果として、データは取得できるのですが取得するまである程度時間が掛かってしまいます。

    CSVファイルの任意のレコードをループ処理なしで取得できれば時間短縮できると思うのですが、よい方法がわかりません。

    どうにかして処理時間を短縮できる方法ないでしょうか?よろしくお願いします。

    【環境】WindowsXP SP2、 VB2005

    2006年8月25日 7:49

すべての返信

  • 全体を一度に読んでしまって、行ごとに配列にでも入れて(Splitで一発かな)、配列の何番目の要素をとりだす、としたほうが個々の処理は早い(ように見える)かもしれませんね。
    2006年8月25日 8:00
  • ODBC を使って、SQL で抽出したらどうでしょうか?
                Dim connection As System.Data.Odbc.OdbcConnectionStringBuilder = New System.Data.Odbc.OdbcConnectionStringBuilder()
                connection.Driver = "Microsoft Text Driver (*.txt; *.csv)"
                connection("DBQ") = "C:\"
                Dim query As String = "SELECT * FROM XXXX.csv WHERE yyyy > 9000"

    ちょいと設定の INI ファイルが必要かもしれませんが、ノリはこんな感じ。
    2006年8月25日 9:16
  •  どっとねっとふぁんさん、おがわみつぎさん返信ありがとうございます。
    両方を実験するのに時間がかかり返事が遅くなりました。
    (ODBCの実装方法には特に苦戦しました。。。)

    どっとねっとふぁんさんの


    全体を一度に読んでしまって、行ごとに配列にでも入れて(Splitで一発かな)、配列の何番目の要素をとりだす~


    では、若干ではありますが処理が速くなりました。
    ファイルの内容を1度に読込むのと、回数を分けて読込むのとでは速度に差がでるのは当然ですよね。。。

     

     おがわみつぎさんの


    ODBC を使って、SQL で抽出~


    では、レコードを指定して抽出させることはできました。
    しかし、SQL文で
        SELECT * FROM CSVファイル.csv WHERE ~
    と指定した場合にCSVファイルには最大で650カラムあるのに対し255カラムしか取得できませんでした。
    ODBCで問合せる場合の1クエリ当たりの最大カラム数が255なのでしょうか?(ここまでは調べきれませんでした。)
    複数個のSQL文に分けてデータを取得してレコードを繋げることはできたのですが、そうした場合に処理速度が元々の方法よりも遅くなってしまいました。

    ODBCに関しては「こんな方法もあるのか!」と参考になりました。貴重な情報ありがとうございました。

     

    今のところ、どっとねっとふぁんさんの方法が最も速いのでそちらで実装しようと思います。

    2006年8月28日 8:11
  •  別な方法としてはSQL SERVER の掲示板にも書き込みましたが
       VBにこだわらなければ Access 2003 でインポートして、クエリでSelect することも可能です。

        もうひとつは SSIS(SQL Server Business Intelligence Development Studio) で 
     テキストファイルに出力またはMDB もしくは    SQL SERVER 2005 の DB に 
     出力(インポートして)しまう方法です。
       
      SSIS で作成したパッケージは CMD.exe のプロンプトからも実行可能ですので
      VBの SHELL からも起動できるはずです。
     SSISはこういうCSV関連はお家芸ですのでまさにぴったりです。
     フラットファイルコンテナでの抽出も可能です。

     実際にまだVBでは作成したことはないので 実験してみるほかないですが こんな方法はいかがでしょうか?
    一度取り込んだテーブルデータは ADO.NET のデータセットとして取り扱うことができます。

    2006年8月29日 3:39