2013-03-23 359 views
1

我已经搜索了这个问题的答案。我知道为什么我收到异常,但我不能在我的代码中找到它的原因。C#PDF删除 - 正在被另一个进程使用的文件'

基本上,我的代码创建四个独立的PDF文件,将它们加入到大PDF文件中,然后删除原来的四个文件。一切都很好,除非我在尝试删除文件时收到IOException,因为它们正在被另一个进程使用。

下面是我用合并文件的代码:

private static Document MergeFiles(string[] fileNames, string finalFileName) 
{ 
    Document doc = new Document(PageSize.A4, 20, 20, 25, 25); 
    if (fileNames.Length > 0) 
    { 
     int a = 0; 
     PdfReader reader = new PdfReader(fileNames[a]); 
     int n = reader.NumberOfPages; 
     FileStream output = new FileStream("C:\\temp\\" + finalFileName, FileMode.Create); 
     PdfWriter writer = PdfWriter.GetInstance(doc, output); 
     doc.Open(); 
     PdfContentByte cb = writer.DirectContent; 
     PdfImportedPage page; 
     int rotation; 

     while (a < fileNames.Length) 
     { 
      int i = 0; 
      while (i < n) 
      { 
       i++; 
       doc.SetPageSize(reader.GetPageSizeWithRotation(i)); 
       doc.NewPage(); 
       page = writer.GetImportedPage(reader, i); 
       rotation = reader.GetPageRotation(i); 
       if (rotation == 90 || rotation == 270) 
        cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height); 
       else 
        cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0); 
      } 
      a++; 
      if (a < fileNames.Length) 
      { 
       reader = new PdfReader(fileNames[a]); 
       n = reader.NumberOfPages; 
      } 
     } 
    } 
    doc.Close(); 
    return doc; 
} 

这里是代码删除文件:

private static void DeleteFile(string[] fileNames) 
{ 
    if (fileNames != null) 
    { 
     for (int x = 0; x < fileNames.Length; x++) 
     { 
      if(!fileNames[x].Equals("")) 
       System.IO.File.Delete(fileNames[x]); 
     } 
    } 
} 

任何援助将不胜感激。当我合并文档时,我假定在某个循环的某个地方,某些东西没有被关闭(读写器),但我尝试了很多不同的组合,没有任何东西可以工作。这真的开始让我烦恼。

UPDATE 感谢您的意见,每个人。我已经修改了我的代码如下:

private static Document MergeFiles(string[] fileNames, string finalFileName) 
{ 
    Document doc = new Document(PageSize.A4, 20, 20, 25, 25); 
    if (fileNames.Length > 0) 
    { 
     while (a < fileNames.Length) 
     { 
      using (PdfReader reader = new PdfReader(fileNames[a])) 
      using (FileStream output = new FileStream("C:\\temp\\" + finalFileName, FileMode.Create)) 
      using (PdfWriter writer = PdfWriter.GetInstance(doc, output)) 
      { 
       int n = reader.NumberOfPages; 
       doc.Open(); 
       PdfContentByte cb = writer.DirectContent; 
       PdfImportedPage page; 
       int rotation; 

       int i = 0; 
       while (i < n) 
       { 
        i++; 
        doc.SetPageSize(reader.GetPageSizeWithRotation(i)); 
        doc.NewPage(); 
        page = writer.GetImportedPage(reader, i); 
        rotation = reader.GetPageRotation(i); 
        if (rotation == 90 || rotation == 270) 
         cb.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height); 
        else 
         cb.AddTemplate(page, 1f, 0, 0, 1f, 0, 0); 
       } 
       a++; 
       if (a < fileNames.Length) 
       { 
        n = reader.NumberOfPages; 
       } 
      } 
     } 
    } 
    doc.Close(); 
    return doc; 
} 

它编译,但我会在运行时错误指向到使用循环的结束括号:虽然您要关闭

System.ObjectDisposedException was unhandled 
    Message=Cannot access a closed file. 
+0

也许在using语句中实例化PdfReader(fileName [a])? – 2013-03-23 17:08:30

+0

有几点建议:不要返回一个'Document'对象,一旦关闭它就没有意义了。或者返回一个成功的布尔值,文件名(可能不是因为你将它传入)或者可能切换到一个'MemoryStream'并返回字节数组。如果你原来的四个文档足够小,我也可以创建一个'MemoryStream',然后从字节数组中取出。这样你就不必担心有时会碰到磁盘。 – 2013-03-24 15:23:41

+0

Chris,我结束了你的解决方案,并使用MemorySteam和字节数组。它最终变得更快更容易,没有任何与PdfReaders等相关的问题。 感谢您的建议! – 2013-03-25 06:22:46

回答

0

文件(doc.Close();),你没有关闭文件流,作家和读者。

doc.Close();后补充一点:

writer.Close(); 
output.Close(); 
reader.Close(); 
4

你没有配置您的任何资源

PdfReader,PdfWriterFileStream全部实施IDisposable。这些都需要Disposed或包裹在using块(最好是后者)。

我的猜测是PdfReader正在保存这些文件的实例。

P.S.仅仅在方法结尾处仅有Close是不够的,因为如果在这些调用执行之前发生任何异常,这将使它们“永久”(或只要进程运行)打开。请将您的清理放在finally区块中,或者仅使用using

+0

非常感谢,亚伦。你能提供一个我如何在这个实例中实例化using语句的快速例子吗?我是新的(截至昨天!)使用语句:) – 2013-03-24 00:30:49

+0

@ BennyO'Neill http://msdn.microsoft.com/en-ca/library/yh598w02.aspx – Aaronaught 2013-03-24 00:45:35

+0

对不起,我应该澄清。我知道使用这个语句的一般方法,但我并不完全知道如何在这个例子中使用它。 例如我已经做 “使用(PDFReader读者=新PDFReader(文件名[0])) { //代码 }” 除I“,因为它是一个无法分配给读者使用可变收到一个编译错误“在使用块内部的这条线上: 'reader = new PdfReader(fileNames [a]);' – 2013-03-24 01:01:49

相关问题