2009-05-18 50 views
3

這是我的代碼,它打開一個XML文件(old.xml),過濾無效字符並寫入另一個XML文件(abc.xml)。最後,我將再次加載XML(abc.xml)。當執行followling行時,有異常說xml文件被另一個進程使用,我的代碼在哪裏泄漏?

xDoc.Load("C:\\abc.xml"); 

有沒有人有什麼想法是什麼錯?我的代碼中有任何泄漏,爲什麼(我一直在使用「使用」關鍵字,感到困惑,看到泄漏......)?

這是我的整個代碼,我在Windows Vista x64下使用C#+ VSTS 2008。

// Create an instance of StreamReader to read from a file. 
    // The using statement also closes the StreamReader. 
    Encoding encoding = Encoding.GetEncoding("utf-8", new EncoderReplacementFallback(String.Empty), new DecoderReplacementFallback(String.Empty)); 
    using (TextWriter writer = new StreamWriter(new FileStream("C:\\abc.xml", FileMode.Create), Encoding.UTF8)) 
    { 
     using (StreamReader sr = new StreamReader(
      "C:\\old.xml", 
      encoding 
      )) 
     { 
      int bufferSize = 10 * 1024 * 1024; //could be anything 
      char[] buffer = new char[bufferSize]; 
      // Read from the file until the end of the file is reached. 
      int actualsize = sr.Read(buffer, 0, bufferSize); 
      writer.Write(buffer, 0, actualsize); 
      while (actualsize > 0) 
      { 
       actualsize = sr.Read(buffer, 0, bufferSize); 
       writer.Write(buffer, 0, actualsize); 
      } 
     } 
    } 

    try 
    { 
     XmlDocument xDoc = new XmlDocument(); 
     xDoc.Load("C:\\abc.xml"); 
    } 
    catch (Exception ex) 
    { 
     Console.WriteLine(ex.Message); 
    } 

編輯1:我試圖將緩衝區的大小從10M更改爲1M,它的工作原理!我很困惑,有什麼想法?

編輯2:我發現這個問題很容易重現,當輸入的舊XML文件非常大,像100M或什麼的。我懷疑它是否是.Net已知的錯誤?我將使用ProcessExplorer/ProcessMonitor等工具來查看哪些進程鎖定了文件,以防止它被XmlDocument.Load訪問。

+0

爲什麼這麼大的緩衝區? (儘管它不應該涉及到這個問題,但知道爲什麼10Mb會很有趣)。我可能會使用10K,也許... – 2009-05-18 12:23:01

+0

我試圖將緩衝區的大小從10M更改爲1M,它的工作原理!我很困惑,有什麼想法? – George2 2009-05-18 12:24:47

+0

我在原始代碼中使用大緩衝區大小純粹是爲了測試目的,而不是故意設置的臨時值。 – George2 2009-05-18 12:25:23

回答

1

你的緩衝區不被釋放,是嗎?

+0

我認爲CLR管理所有的內存緩衝區。困惑。無論如何,你的建議是什麼?你可以顯示你的代碼嗎? – George2 2009-05-18 11:56:09

+0

沒有必要(甚至沒有機制)釋放緩衝區; GC很快就會選擇它(可能在GEN0中,非常便宜)。 – 2009-05-18 11:59:30

+0

就在這一點上,緩衝區對堆棧來說很大,所以它被打包到大對象堆上 - 只要進程正在運行,它就不會壓縮。 – 2009-05-18 12:12:02

1

代碼工作正常。剛剛檢查。

+0

奇怪,任何想法進一步檢查? – George2 2009-05-18 12:22:56

4

這對我來說很好。 純粹是猜測,但也許病毒檢查器正在掃描文件? 要進行調查,請嘗試禁用病毒檢查程序並查看它是否有效(然後重新啓用病毒檢查程序)。

順便說一句,還有一個方式,它可以離開打開文件:如果StreamReader構造函數拋出異常;但你不會達到XmlDocument東西反正...但考慮:

using (FileStream fs = new FileStream("C:\\abc.xml", FileMode.Create)) 
using (TextWriter writer = new StreamWriter(fs, Encoding.UTF8)) 
{ 
    ... 
} 

現在fs佈置在new StreamWriter(...)拋出邊緣情況。但是,我做不是認爲這是這裏的問題。

1

使用會調用Dispose,但是Dispose調用關閉寫入流嗎?如果沒有,系統可能仍然認爲該文件是可以寫入的。

我想嘗試在的末尾關閉using區塊。

編輯:我自己也嘗試過自己的代碼。編譯並運行時不會出現您所看到的問題。嘗試關閉病毒掃描程序,就像其他人提到的一樣,並確保在打開文件時沒有窗口。

1

您是否檢查過沒有其他進程試圖訪問該文件?

2

您可能在根上運行FileSystemWatcher?

您還可以使用ProcessMonitor查看誰訪問該文件。

2

問題在於你的char[]這看起來很大。如果它太大,它位於大的目標堆中,而不是在堆棧上。因此,只要軟件正在運行,大型對象堆就不會被壓縮,一次分配的空間可能不會再被使用 - 這看起來像是內存泄漏。嘗試將你的數組分割成更小的塊。

1

事實上,它適用於某些人而不適用於其他人,這讓我認爲文件沒有被關閉。在嘗試加載文件之前關閉寫入器。

2

我第二次Leppie建議使用ProcessMonitor(或同等功能)來確定誰鎖定了文件。其他任何只是猜測。

1

我敢打賭,你有一些防病毒解決方案正在運行,它在文件關閉後鎖定它。要驗證,請嘗試在加載文件之前添加一個延遲(如1秒)。如果這有效,你可能找到了原因。