2017-06-05 37 views
0

我需要编写应用程序来删除非常大的XML文件(大约3,5 GB)中的特定文本行。删除XML文件中的文本行C#.NET

我写了这个代码:

string directoryPath; 

    OpenFileDialog ofd = new OpenFileDialog(); 

    private void button1_Click(object sender, EventArgs e) 
    { 
     ofd.Filter = "XML|*.xml"; 
     if (ofd.ShowDialog() == DialogResult.OK) 
     { 
      directoryPath = Path.GetDirectoryName(ofd.FileName); 
      textBox2.Text = directoryPath; 
      textBox1.Text = ofd.SafeFileName; 
     } 
    } 

    private void Replace() 
    { 
     StreamReader readerFile = new StreamReader(ofd.FileName, System.Text.Encoding.UTF8); 

     while (!readerFile.EndOfStream) 
     { 
      string stringReplaced; 
      string replaceResult = textBox2.Text + "\\" + "replace_results"; 
      Directory.CreateDirectory(replaceResult); 
      StreamWriter writerFile = new StreamWriter(replaceResult + "\\" + textBox1.Text, true); 
      StringBuilder sb = new StringBuilder(); 
      char[] buff = new char[10 * 1024 * 1024]; 
      int xx = readerFile.ReadBlock(buff, 0, buff.Length); 
      sb.Append(buff); 
      stringReplaced = sb.ToString(); 
      stringReplaced = stringReplaced.Replace("line to remove", string.Empty); 
      writerFile.WriteLine(stringReplaced); 
      writerFile.Close(); 
      writerFile.Dispose(); 
      stringReplaced = null; 
      sb = null; 
     } 


     readerFile.Close(); 
     readerFile.Dispose(); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     if (!backgroundWorker1.IsBusy) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
      toolStripStatusLabel1.Text = "Replacing in progress..."; 
     } 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     try 
     { 
      Replace(); 
      toolStripStatusLabel1.Text = "Replacing complete!"; 
     } 
     catch 
     { 
      toolStripStatusLabel1.Text = "Error! Replacing aborted!"; 
     } 
    } 
} 

它的工作原理,但不是很好,因为新的文件(后删除线)比原来的文件,并在新文件的末尾添加一些垃圾更大(大量的点),截图:

https://images81.fotosik.pl/615/873833aa0e23b36f.jpg

如何解决我的代码,使新的文件一样的旧文件,只是没有具体的线路?

回答

0

一开始为什么要打开和关闭输出文件?保持开放。

第二个读取块 - 这可能导致“行删除”被拆分块 - 写入行是一个奇怪的混合。

但我希望你的问题是三折:

  1. 你不设置输出文件的编码。

  2. 当您读取缓冲区(10MB)时,可能会读取更少的字符 - 从ReadBlock返回。但你总是写完整的块。限制写入以匹配读取的数量(已更新但替换)。

  3. ReadBlock将包括行尾,但WriteLine将添加它们:或者在块或行上工作。混合只会产生问题(并避免上述第二个问题)。

这将导致代码是这样的:

using (var rdr = OpenReadFile(...)) 
using (var wtr = OpenWriteFile(...)) { 
    string line; 
    while ((line = rdr.ReadLine()) != null) { 
    line = line.Replace(x, y); 
    str.WriteLine(line); 
    } 
} 

NB处理XML文本可能导致破坏XML(也称为“无效XML”没有这样的事:要么该文件是有效的XML或它不是XML,只是看起来有点像它可能是XML)。因此,任何此类方法都需要谨慎处理。 “正确的”答案是使用流式API处理XML(XmlReaderXmlWriter),以避免将整个文档解析为一个文档。

+0

我怎么只能行做这项工作没有出内存异常?你能给我代码吗? :) – gos

+0

@gos:中央循环应该是:读取行,进程,写入行。记忆中一次只有一行。 – Richard

+0

@gos:查看扩展的答案。 – Richard

0

我试图通过XmlTextReader的做到这一点,但我有system.xml.xmlexception在读我的文件,截图:https://images82.fotosik.pl/622/d98b35587b0befa4.jpg

代码:

XmlTextReader xmlReader = new XmlTextReader(ofd.FileName); 
XmlDocument doc = new XmlDocument(); 
doc.Load(xmlReader);