2017-06-05 62 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);