11

いくつかの変更を加える必要がある60GBのcsvファイルがあります。お客様はファイルデータの変更を望んでいますが、4日かかったため、そのファイルのデータを再生成したくありません。

ファイルを1行ずつ読み取り(すべてをメモリにロードしないでください!)、特定の値などを置き換えながら、それらの行を編集するにはどうすればよいですか?

4

3 に答える 3

15

プロセスは次のようになります。

  1. StreamWriter一時ファイルを開きます。
  2. StreamReaderターゲット ファイルを開きます。
  3. 各行について:
    1. 区切り文字に基づいてテキストを列に分割します。
    2. 置換する値の列を確認し、それらを置換します。
    3. 区切り文字を使用して、列の値を結合して戻します。
    4. 行を一時ファイルに書き込みます。
  4. 終了したら、ターゲット ファイルを削除し、一時ファイルをターゲット ファイル パスに移動します。

ステップ 2 と 3.1 に関する注意: ファイルの構造に自信があり、それが十分に単純である場合は、説明されているように、すぐに使用できます (すぐにサンプルを含めます)。ただし、CSV ファイルには注意が必要な要素があります (区切り文字が列の値でそのまま使用されている場合の認識など)。これを自分で苦労するか、既存のソリューションを試すことができます。


StreamReaderandを使用した基本的な例StreamWriter:

var sourcePath = @"C:\data.csv";
var delimiter = ",";
var firstLineContainsHeaders = true;
var tempPath = Path.GetTempFileName();
var lineNumber = 0;

var splitExpression = new Regex(@"(" + delimiter + @")(?=(?:[^""]|""[^""]*"")*$)");

using (var writer = new StreamWriter(tempPath))
using (var reader = new StreamReader(sourcePath))
{
    string line = null;
    string[] headers = null;
    if (firstLineContainsHeaders)
    {
        line = reader.ReadLine();
        lineNumber++;

        if (string.IsNullOrEmpty(line)) return; // file is empty;

        headers = splitExpression.Split(line).Where(s => s != delimiter).ToArray();

        writer.WriteLine(line); // write the original header to the temp file.
    }

    while ((line = reader.ReadLine()) != null)
    {
        lineNumber++;

        var columns = splitExpression.Split(line).Where(s => s != delimiter).ToArray();

        // if there are no headers, do a simple sanity check to make sure you always have the same number of columns in a line
        if (headers == null) headers = new string[columns.Length];

        if (columns.Length != headers.Length) throw new InvalidOperationException(string.Format("Line {0} is missing one or more columns.", lineNumber));

        // TODO: search and replace in columns
        // example: replace 'v' in the first column with '\/': if (columns[0].Contains("v")) columns[0] = columns[0].Replace("v", @"\/");

        writer.WriteLine(string.Join(delimiter, columns));
    }

}

File.Delete(sourcePath);
File.Move(tempPath, sourcePath);
于 2012-12-21T07:15:15.260 に答える
6

メモリ マップト ファイルは、大きなファイルの編集に使用できる .NET Framework 4 の新機能です。ここを読んでください http://msdn.microsoft.com/en-us/library/dd997372.aspx または google メモリマップされたファイル

于 2012-12-21T07:18:22.167 に答える
1

streamreader を使用してファイルを 1 行ずつ読み取り、REGEX を使用するだけです。世界で最も素晴らしいツール。

using (var sr = new StreamReader(new FileStream(@"C:\temp\file.csv", FileMode.Open)))
        {
            var line = sr.ReadLine();
            while (!sr.EndOfStream)
            {
                // do stuff

                line = sr.ReadLine();
            }

        }
于 2012-12-21T07:23:28.380 に答える