2017-06-05 13 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

?開いたままにしておきます。ブロックにまたがって分割されている「削除する行」につながる可能性がある - -

は、第二のブロックを読み取り、ラインを書くことは奇妙なミックスです。

しかし、私はあなたの問題は3倍である期待:

  1. あなたは、出力ファイルのエンコーディングを設定しないでください。 ReadBlockからの復帰を -

  2. あなたはバッファ(10メガバイト)あなたは少ない文字が読み得ることを読ん

    。しかし、あなたは常に完全なブロックを書く。 (更新としてではなく置き換え)読ん量に一致するように、書き込みを制限します。

  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の(XmlReaderXmlWriter)をXMLとして処理することです。

+0

メモリの例外?コードを教えてもらえますか? :) – gos

+0

@gos中央ループがなければならない:読み取りライン、プロセス、書き込み線。一度に1行しかメモリにはありません。 – 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); 
関連する問題