c# - 写入文件 C# 的性能

标签 c# performance file io

我的情况概述:

我的任务是从文件中读取字符串,并将它们重新格式化为更有用的格式。重新格式化输入后,我必须将其写入输出文件。

这是必须完成的示例。 文件行示例:

ANO=2010;CPF=17834368168;YEARS=2010;2009;2008;2007;2006 <?xml version='1.0' encoding='ISO-8859-1'?><QUERY><RESTITUICAO><CPF>17834368168</CPF><ANO>2010</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><RESTITUICAO><CPF>17834368168</CPF><ANO>2009</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><RESTITUICAO><CPF>17834368168</CPF><ANO>2008</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><RESTITUICAO><CPF>17834368168</CPF><ANO>2007</ANO><SITUACAODECLARACAO>Sua declaração consta como Pedido de Regularização(PR), na base de dados da Secretaria da Receita Federal do Brasil</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><RESTITUICAO><CPF>17834368168</CPF><ANO>2006</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><STATUS><RESULT>TRUE</RESULT><MESSAGE></MESSAGE></STATUS></QUERY>

此输入文件的每一行都有两个重要信息:CPF,这是我将使用的文档编号,以及 XML 文件(代表查询的返回用于数据库中的文档)。

我必须达到的目标:

旧格式 中的每个文档都有一个XML,其中包含所有年份(2006 年至2010 年)的查询返回值。重新格式化后,每条输入线转换为 5 条输出线:

CPF=17834368168;YEARS=2010; <?xml version='1.0' encoding='ISO-8859-1'?><QUERY><RESTITUICAO><CPF>17834368168</CPF><ANO>2010</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><STATUS><RESULT>TRUE</RESULT><MESSAGE></MESSAGE></STATUS></QUERY>
CPF=17834368168;YEARS=2009; <?xml version='1.0' encoding='ISO-8859-1'?><QUERY><RESTITUICAO><CPF>17834368168</CPF><ANO>2009</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><STATUS><RESULT>TRUE</RESULT><MESSAGE></MESSAGE></STATUS></QUERY>
CPF=17834368168;YEARS=2008; <?xml version='1.0' encoding='ISO-8859-1'?><QUERY><RESTITUICAO><CPF>17834368168</CPF><ANO>2008</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><STATUS><RESULT>TRUE</RESULT><MESSAGE></MESSAGE></STATUS></QUERY>
CPF=17834368168;YEARS=2007; <?xml version='1.0' encoding='ISO-8859-1'?><QUERY><RESTITUICAO><CPF>17834368168</CPF><ANO>2007</ANO><SITUACAODECLARACAO>Sua declaração consta como Pedido de Regularização(PR), na base de dados da Secretaria da Receita Federal do Brasil</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><STATUS><RESULT>TRUE</RESULT><MESSAGE></MESSAGE></STATUS></QUERY>
CPF=17834368168;YEARS=2006; <?xml version='1.0' encoding='ISO-8859-1'?><QUERY><RESTITUICAO><CPF>17834368168</CPF><ANO>2006</ANO><SITUACAODECLARACAO>Sua declaração não consta na base de dados da Receita Federal</SITUACAODECLARACAO><DATACONSULTA>05/01/2012</DATACONSULTA></RESTITUICAO><STATUS><RESULT>TRUE</RESULT><MESSAGE></MESSAGE></STATUS></QUERY>

一行,包含有关该文档的每年信息。所以基本上,输出文件的长度是输入文件的 5 倍

性能问题:

每个文件有 400,000 行,我有 133 个文件要处理。

目前,这是我的应用程序的流程:

  1. 打开一个文件
  2. 读一行
  3. 将其解析为新格式
  4. 将行写入输出文件
  5. 转到 2 直到没有左边的行
  6. Goto1 直到没有剩下的文件

每个输入文件大约 700MB,读取文件并将转换后的版本写入另一个文件需要很长时间。一个 400KB 的文件需要大约 30 秒才能完成该过程。

额外信息:

我的机器运行在 Intel i5 处理器上,内存为 8GB。

我没有实例化大量对象来避免内存。泄漏,我在输入文件打开时使用 using 子句。

我该怎么做才能让它运行得更快?

最佳答案

我不知道您的代码是什么样的,但这是我的盒子上的一个示例(诚然带有 SSD 和 i7,但是......)在大约 50 毫秒内处理一个 400K 的文件。

我什至没有考虑过优化它 - 我已经用我能做到的最简洁的方式编写了它。 (请注意,它都是延迟计算的;File.ReadLinesFile.WriteAllLines 负责打开和关闭文件。)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

class Test
{
    public static void Main()
    {
        Stopwatch stopwatch = Stopwatch.StartNew();
        var lines = from line in File.ReadLines("input.txt")
                    let cpf = ParseCpf(line)
                    let xml = ParseXml(line)
                    from year in ParseYears(line)
                    select cpf + year + xml;

        File.WriteAllLines("output.txt", lines);
        stopwatch.Stop();
        Console.WriteLine("Completed in {0}ms", stopwatch.ElapsedMilliseconds);
    }

    // Returns the CPF, in the form "CPF=xxxxxx;"
    static string ParseCpf(string line)
    {
        int start = line.IndexOf("CPF=");
        int end = line.IndexOf(";", start);
        // TODO: Validation
        return line.Substring(start, end + 1 - start);
    }

    // Returns a sequence of year values, in the form "YEAR=2010;"
    static IEnumerable<string> ParseYears(string line)
    {
        // First year.
        int start = line.IndexOf("YEARS=") + 6;
        int end = line.IndexOf(" ", start);
        // TODO: Validation
        string years = line.Substring(start, end - start);
        foreach (string year in years.Split(';'))
        {
            yield return "YEARS=" + year + ";";
        }
    }

    // Returns all the XML from the leading space onwards
    static string ParseXml(string line)
    {
        int start = line.IndexOf(" <?xml");
        // TODO: Validation
        return line.Substring(start);
    }
}

关于c# - 写入文件 C# 的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9437265/

相关文章:

c# - 如何使用 LINQ 获取列表中属性的平均值?

c# - 使用 Linq 创建对象列表与创建字典的性能比较?

mysql - SELECT COUNT with JOIN optimization for tables with > 100M rows

c - 在 C 中首先读取文件的最后一行

c# - 获取当前 Windows 系统输入语言和语言更改时的通知

c# - 使用对象实例从 long 到 int 的泛型转换

python - 为什么 scipy.distance.cdist 在使用 float32 (较慢)和 float64 (较快)之间有很大的性能差异?

c - 日期打印和扫描

perl - 取消链接究竟是如何工作的?

c# - 对于非 OK 响应,使用 IHttpActionResult 返回内容