2009-05-18 66 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秒)。如果这有效,你可能找到了原因。