2012-12-06 88 views
12

的第一行我有我导入到数据库中许多大的CSV文件(每个1-10 GB)。对于每个文件,我需要替换第一行,以便可以将标题格式化为列名称。我目前的解决方案是:快速更换大文件

using (var reader = new StreamReader(file)) 
{ 
    using (var writer = new StreamWriter(fixed)) 
    { 
     var line = reader.ReadLine(); 
     var fixedLine = parseHeaders(line); 
     writer.WriteLine(fixedLine); 

     while ((line = reader.ReadLine()) != null) 
      writer.WriteLine(line); 
    } 
} 

什么是更快的方式来只替换第1行而无需遍历这些巨大的文件的每一行?

+0

我可能只是从命令行执行此操作。 'copy headerfile + csvfile newfile'你可以创建一个包含所有需要修改的文件的批处理文件。 (哦,除了看起来你不知道标题是什么,否则这不会起作用) –

+0

如果你正在使用的工具恰好通过'stdin'输入输入:而不是文件,您可以创建一个由标题和正文组成的流,并在需要时将其提供到导入工具中。例如'cat headerfile bigfile | import_tool' –

+0

这对fixedLine的长度和第一行非常敏感。 fixedLine可以更大吗? line2是否可以移动到文件的末尾? –

回答

7

如果您可以保证fixedLineline的长度相同(或更少),您可以在原地更新文件而不是复制它们。

如果没有,你都不可能通过访问StreamReaderStreamWriter.BaseStream,做块大副本(使用,比如说,一个32K字节的缓冲区)做复制得到一个小的性能提升,这将至少消除花在检查每个角色上的时间,看看它是否是现在的reader.ReadLine()现在发生的行尾字符。

+0

如果少了,你会如何处理“免费”空间?用空格填充它? – Jodrell

+0

可能,但它取决于格式。在CSV文件中,我可以引用标题元素,并在逗号后添加填充空格。 – prprcupofcoffee

+1

+1。 @Jodrell,是的,在大多数情况下空格被忽略的CSV - 所以使用它们填充将是好的(我试图建议它在我的相同答案:))。空间对于大多数编码也是安全的 - 所以可以根据需要直接写入流中。 –

6

唯一能够显着提高速度的是如果你真的可以用代替第一行。如果新的第一行不再比旧的第一行更小 - 请仔细地用第一行替换(如果需要,填充空格)。

否则 - 你必须创建新的文件,第一行后,其余的复制。您可以通过将缓冲区大小/显式副本调整为二进制/每个分配的大小来优化复制,但这不会改变您需要复制整个文件的事实。

如果您打算将CSV数据放入数据库,还有一种作弊方式:如果顺序无关紧要,您可以从头开始读取一些行,将其替换为新的标题并将删除的行添加到文件的末尾。

边注:如果这是一次性操作我会简单地复制文件,并用它做...调试将数据插入文本文件中他们有不同的编码可能不值得努力代码。