Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何一次读取一行csv文件,并在运行时替换/编辑某些行?_C#_.net_Parsing_Csv - Fatal编程技术网

C# 如何一次读取一行csv文件,并在运行时替换/编辑某些行?

C# 如何一次读取一行csv文件,并在运行时替换/编辑某些行?,c#,.net,parsing,csv,C#,.net,Parsing,Csv,我有一个60GB的csv文件,我需要做一些修改。客户希望对文件数据进行一些更改,但我不想重新生成该文件中的数据,因为这需要4天的时间 如何逐行读取文件(而不是将其全部加载到内存中!),并在执行过程中对这些行进行编辑,替换某些值等?过程如下: 打开一个StreamWriter到一个临时文件 打开目标文件的StreamReader 对于每一行: 根据分隔符将文本拆分为列 检查要替换的值的列,然后替换它们 使用分隔符将列值重新连接在一起 将该行写入临时文件 完成后,删除目标文件,并将临时文件移动到目

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


如何逐行读取文件(而不是将其全部加载到内存中!),并在执行过程中对这些行进行编辑,替换某些值等?

过程如下:

  • 打开一个
    StreamWriter
    到一个临时文件
  • 打开目标文件的
    StreamReader
  • 对于每一行:
  • 根据分隔符将文本拆分为列
  • 检查要替换的值的列,然后替换它们
  • 使用分隔符将列值重新连接在一起
  • 将该行写入临时文件
  • 完成后,删除目标文件,并将临时文件移动到目标文件路径
  • 关于步骤2和3.1的注意事项:如果您对文件的结构很有信心,并且文件足够简单,那么您可以按照前面所述的开箱即用(稍后我将提供一个示例)。但是,CSV文件中有一些因素可能需要注意(例如,识别何时在列值中字面上使用分隔符)。你可以自己苦干,也可以尝试一种新的方法


    仅使用
    StreamReader
    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);
    

    内存映射文件是.NET Framework 4中的一项新功能,可用于编辑大型文件。 读这里
    或者谷歌内存映射文件

    只需使用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();
                }
    
            }
    

    在这种情况下,为什么不尝试使用Hadoop Map reduce…只有当修改的行的长度不超过原始行的长度时,您才能进行修改,而不仅仅是写入新文件?所以:1。阅读2。修改3.写入以复制。这是你不想做的事情,还是你只是在寻找一种“优雅”的方式来做到这一点?嗯…空间是一个考虑因素…那将占用我120 GB的硬盘…@Karthikeyanarumgam:什么?这只是一个一次性的csv文件,在hadoop实例中我不需要它!我喜欢!我去看看。谢谢。这绝对是最简单最直接的方法。有一件事,我没有想到尺寸。最终的
    文件.Move
    可能会非常慢。因此,您可以在与源文件相同的文件夹中创建临时文件,然后删除源文件并重命名临时文件(而不是使用
    GetTempFileName
    file.Move
    )。这就是我最后所做的。这是快速和伟大的。谢谢