2009年10月11日日曜日

[.NET]CSVデータを操作する(OleDb)(その2 ソートしてファイルへ出力)

CSVファイルのある列でソートしたい。といった場合、DBにいったん保存したり、何かしらコマンドを使ったり。方法はいろいろありますが、どれもしっくりきません。以前GDD Blog: [.NET]CSVデータを操作する(OleDb)で、単純にCSVファイルのCRUDを試しましたが、SELECTするときにORDER BYつけれないかなぁということでやってみました。

適当なデータが無かったので、郵便番号データ(全国版)をつかってちょっとした実験をしてみました。
このデータは12万件ありますが、郵便番号順に並んでいないようなので、これでソートしてみました。
コードはこんな感じ。

private void button1_Click(object sender, EventArgs e)
{
    //using System.Data.OleDb;
    string csvDir = @"d:\temp";
    string csvFileName = "KEN_ALL.CSV";

    //接続文字列 
    string conString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + csvDir +
                       ";Extended Properties=\"text;HDR=No;FMT=Delimited\"";

    System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
    sw.Start();
   

    using (OleDbConnection con = new OleDbConnection(conString))
    {
        con.Open();

        // HDR=Noだと、Fxというフィールド名になるらしい。↓は3つめのフィールド名でソート
        string strSQL = "SELECT * FROM " + csvFileName + " ORDER BY F3";
        using (OleDbCommand cmd = new OleDbCommand(strSQL, con))
        using (OleDbDataReader rd = cmd.ExecuteReader())
        using (StreamWriter w = new StreamWriter(new FileStream(csvDir + @"\test.txt", FileMode.Create)))
        {
            StringBuilder sb = new StringBuilder();
            //カラム名を取得し、カンマ区切りで編集します
            for (int col = 0; col < rd.FieldCount; col++)
            {
                sb.Append(rd.GetName(col)).Append(",");
            }
            sb.Remove(sb.Length - 11);
            w.WriteLine(sb);

             //データを取得しカンマ区切りで編集します
            while (rd.Read())
            {
                sb.Length = 0;
                for (int col = 0; col < rd.FieldCount; col++)
                {
                    sb.Append(rd.GetValue(col)).Append(",");
                }
                sb.Remove(sb.Length - 11);
                w.WriteLine(sb);
            }
        }
    }
    sw.Stop();
    label1.Text=  String.Format("完了{0:#,##0}ms", sw.ElapsedMilliseconds);
}


パフォーマンスを測ってみました。結果こんな感じ(5回平均)。
ソートなし:4.21秒
ソートあり:10.09秒

・・・12万件を10秒とすると、1件あたり0.08msとなります。
一般的なDBと比較するとアレですが、テキストファイルで且、ファイルへの出力も含む。と考えた場合、以外といい数字のような気がします。

ちなみに、うちのマシンは1年半ほど前に購入したC2D 2GHzのノートPCです。

0 件のコメント: