如何一次读取一行csv文件并替换/编辑某些行?

我有一个60GB的csv文件,我需要对其进行一些修改。 客户希望对文件数据进行一些更改,但我不想重新生成该文件中的数据,因为需要4天时间才能完成。

如何逐行读取文件(不将其全部加载到内存中!),并在我去的时候对这些行进行编辑,替换某些值等等?

这个过程是这样的:

  1. StreamWriter打开到临时文件。
  2. 打开StreamReader到目标文件。
  3. 对于每一行:
    1. 根据分隔符将文本拆分为列。
    2. 检查列以查找要替换的值,然后替换它们。
    3. 使用分隔符将列值重新连接在一起。
    4. 将该行写入临时文件。
  4. 完成后,删除目标文件,并将临时文件移动到目标文件路径。

关于步骤2和3.1的注意事项:如果您对文件的结构有信心并且它很简单,那么您可以按照所描述的那样开箱即用(我稍后会包含一个示例)。 但是,CSV文件中可能需要注意一些因素(例如识别何时在列值中使用分隔符)。 您可以自己解决这个问题,或尝试现有的解决方案 。


仅使用StreamReaderStreamWriter基本示例:

 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); 

内存映射文件是.NET Framework 4中的一项新function,可用于编辑大型文件。 在这里阅读http://msdn.microsoft.com/en-us/library/dd997372.aspx或google内存映射文件

只需使用streamreader逐行读取文件,然后使用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(); } }