2011-08-02 15 views
0

私はCSVファイルにデータベーステーブルを書き込むアプリケーションを書いています。多くのテーブルは100万レコードを超えているので、大きなテーブルをそれぞれ25,000行のファイルに書き込むことができます。 SaveFileDialogに初期ファイル名を指定して、新しいファイルを書き込むたびに "-part1"、 "-part2"などを追加します。すべてのデータが書き込まれるまで、どのようにして複数のファイルをプログラムで書き込むことができますか? 25,000行のファイルを書き込む必要がある現在のコードを以下に示します。programatically複数のCSVファイルを書く

public void ExportPartition(SaveFileDialog saveFile, DataTable table) 
    { 
     TextWriter writer = new StreamWriter(saveFile.FileName, true, System.Text.Encoding.ASCII, 1048576); 

     for (int i = 0; i <= 25000; i++) 
     { 
      for (int j = 0; j < table.Columns.Count; j++) 
      { 
       writer.Write(table.Rows[i][j].ToString() + ","); 
      } 
      writer.Write("\r\n"); 
     } 
     writer.Flush(); 
     DisposeObjects(saveFile, writer); 
    } 
+0

ます。また、インポート操作が失敗しないように、すでにそれらの中にコンマを持つフィールドを扱う検討する必要があります。 –

+0

すべての行の最後にカンマがあるはずですか? – alun

+0

私はこれをすばやく書きましたが、私はその行の最後にカンマを気付かなかったのです。ありがとうございました。フィールドにカンマを含むデータはありませんが、再利用性のためにこの問題に対処する必要があります。 – Andrew

答えて

0
bool ExportPartition(string fileName, DataTable table, int batchSize, int batchNum) 
    { 
     string fn = string.Format("{0}-{1}{2}",          
            Path.GetFileNameWithoutExtension(fileName), 
            batchNum, 
            Path.GetExtension(fileName)); 

     fn = Path.Combine(Path.GetDirectoryName(fileName), fn); 

     using (TextWriter writer = new StreamWriter(fn)) 
     { 
      int start = batchNum * batchSize; 
      int end = start + batchSize; 

      for (int i = start; i < end; i++) 
      { 
       if (i >= table.Rows.Count) 
        break; 

       for (int j = 0; j < table.Columns.Count; j++) 
       { 
        writer.Write(table.Rows[i][j] + ","); 
       } 
       writer.Write("\r\n"); 
      } 

      return table.Rows.Count <= end; 
     } 
    } 

使用法:

void WriteFiles(DataTable table, String fileName, int batchSize) 
    { 
     int batchNum = 0;   
     bool done = false; 
     while (!done) 
     { 
      done = ExportPartition(fileName, table, batchSize, batchNum++); 
     } 
    } 

    void Main() 
    { 
     DataTable dt = GetData(); 
     string fileName = GetFileNameWithSaveDialog(); 
     int batchSize = 25000; 
     WriteFiles(dt, fileName, batchSize); 
    } 
+0

これを実装しましたが、TextWriterコンストラクターでIO例外がスローされます。 プロセスは、別のプロセスによって使用されているため、 'C:¥Users¥afannin1¥Equipment¥HBSSensorDataClient¥HBSDataClient¥HBSDataClient¥bin¥Debug¥Partitions - 0..csv'ファイルにアクセスできません。 – Andrew

+0

ファイル名(..csv)に2つのドットが表示されていますか?拡張子にはおそらくドットが含まれているので、フォーマット文字列を更新します。使用中のファイルが奇妙に感じられました。別のアプリケーション(テキストエディタやプログラムの前実行インスタンスなど)で開いていましたか? –

+0

私はその問題と拡張機能の問題を修正することができました。アプリケーションは現在ファイルを書き込んでいますが、実装で使用されているwhileループは終了していません。 – Andrew

0

代替ソリューション:

class Program 
{ 
    static void Main(string[] args) 
    { 
     DataTable dt = new DataTable(); 
     dt.Columns.Add("Col1"); 
     dt.Columns.Add("Col2"); 
     for (int i = 0; i < 103; ++i) 
     { 
      var r = dt.NewRow(); 
      r[0] = Guid.NewGuid().ToString(); 
      r[1] = i.ToString(); 
      dt.Rows.Add(r); 
     } 
     WriteCsvFile(dt, 25, @"C:\temp\test.txt"); 
    } 

    public static string[] ToStringArray(DataRow row) 
    { 
     var arr = new string[row.Table.Columns.Count]; 
     for (int j = 0; j < arr.Length; j++) 
     { 
      arr[j] = row[j].ToString(); 
      if((arr[j]??"").Contains(",")) 
       throw new Exception("This will end badly..."); 
     } 
     return arr; 
    } 

    public static void WriteCsvFile(DataTable table, int maxCount, string fileName) 
    { 
     if (table.Rows.Count <= maxCount) 
      WriteCsvFile(table, maxCount, fileName, 0); 
     else 
      for (int i = 0; i < (table.Rows.Count/maxCount + 1); ++i) 
      { 
       var partFileName = Path.Combine(Path.GetDirectoryName(fileName), string.Format("{0}-part{1}{2}", Path.GetFileNameWithoutExtension(fileName), i+1, Path.GetExtension(fileName))); 
       WriteCsvFile(table, maxCount, partFileName, i * maxCount); 
      } 
    } 

    public static void WriteCsvFile(DataTable table, int maxCount, string fileName, int startIndex) 
    { 
     using(var fs = File.Create(fileName)) 
     using(var w = new StreamWriter(fs, Encoding.ASCII)) 
     { 
      for (int i = startIndex; i < Math.Min(table.Rows.Count, startIndex + maxCount); i++) 
       w.WriteLine(String.Join(",", ToStringArray(table.Rows[i]))); 
      w.Flush(); 
     } 
    } 
} 
関連する問題