2013-03-23 4 views
1

나는이 질문에 대한 답변을 광범위하게 검색했습니다. 내가 예외를 받았는지는 알지만 내 코드에서 그 원인을 발견 할 수는 없습니다.C# PDF 삭제 - 다른 프로세스에서 사용중인 파일

기본적으로 내 코드는 4 개의 개별 PDF 파일을 만들고 큰 PDF 파일에 결합한 다음 원래 4 개의 파일을 삭제합니다. 나는 '다른 프로세스에 의해 사용되고 있기 때문에 파일을 삭제하려고 할 때 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]); 
     } 
    } 
} 

어떤 도움을 크게 감상 할 수있다. 나는 문서를 병합 할 때 루프의 어딘가에있는 것을 추정한다. 무언가 (리더/라이터)가 닫히지 않고 있지만 다른 콤보를 많이 시도했지만 아무 것도 작동하지 않는 것 같다. 정말 저를 괴롭히기 시작했습니다.

업데이트 여러분 모두 의견을 보내 주셔서 감사합니다. 나는이 내 코드를 수정했습니다

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])를 인스턴스화할까요? –

+0

몇 가지 제안 :'Document' 객체를 반환하지 마십시오. 일단 닫은 후에는 실제로 이해가 가지 않습니다. 성공을위한 boolean을 반환하거나, 파일 이름을 전달하거나 (아마 여러분이 전달하고있는 것이 아니기 때문에) 또는 아마도'MemoryStream'으로 전환하여 바이트 배열을 반환하십시오. 원래 네 개의 문서가 충분히 작 으면 각각을 'MemoryStream'으로 만들고 바이트 배열을 처리하십시오. 이렇게하면 디스크를 때리는 것에 대해 걱정할 필요가 없습니다. –

+0

Chris, 솔루션과 함께 가고 MemorySteam과 바이트 배열을 사용했습니다. PdfReaders와 관련된 문제들 중 아무 것도없이 훨씬 더 빠르고 훨씬 쉬워졌습니다. 제안 해 주셔서 감사합니다. –

답변

0

을 문서 (doc.Close();)이면 파일 스트림, 작가 및 독자가 닫히지 않습니다.

doc.Close(); 후이 추가 : 당신은 당신의 자원 어떤을 폐기하지 않을

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

.

PdfReader, PdfWriterFileStream은 모두 IDisposable을 구현합니다. 이들은 모두 Dispose d이거나 using 블록 (바람직하게는 후자)으로 싸여 있어야합니다.

제 생각 엔 파일을 열어 두는 것은 PdfReader 인스턴스입니다.

P. 메소드가 끝날 때 Close으로 끝나는 것만으로는 충분하지 않습니다. 호출이 실행되기 전에 예외가 발생하면 "영구적으로"(또는 프로세스가 실행되는 동안) 열어두기 때문입니다. finally 블록에 클린업을하거나 using을 사용하십시오.

+0

아론 덕분에. 이 인스턴스에서 using 문을 인스턴스화하는 방법에 대한 간단한 예제를 제공 할 수 있습니까? 나는 어제처럼 (어제!) Using 문에 :) –

+0

@ BennyO'Neill http://msdn.microsoft.com/en-ca/library/yh598w02.aspx – Aaronaught

+0

죄송합니다, 분명히해야합니다. 내가 진술을 사용하는 일반적인 방법을 알고 있지만, 나는이 인스턴스에서 그것을 사용하는 방법을 완전히 모르겠다. 예. 내가 했던 '사용 (PDFReader 리더 = 새로운 PDFReader을 (파일 이름 [0])) { // 코드 }' '그것이 있기 때문에 독자에게 할당 할 수 없습니다'변수 사용하여 내가 컴파일 오류가 제외 ' Using 블록 안에있는이 행에 : 'reader = new PdfReader (fileNames [a]);' –