2009-07-06 5 views
3

다음 코드는 '프로세스가 파일에 액세스 할 수 없습니다'라는 메시지가있는 System.IO.IOException을 제공합니다.C1ZipFile을 사용한 후에이 파일을 삭제할 수없는 이유는 무엇입니까?

private void UnPackLegacyStats() 
{ 
    DirectoryInfo oDirectory; 
    XmlDocument oStatsXml; 

    //Get the directory 
    oDirectory = new DirectoryInfo(msLegacyStatZipsPath); 

    //Check if the directory exists 
    if (oDirectory.Exists) 
    { 
    //Loop files 
    foreach (FileInfo oFile in oDirectory.GetFiles()) 
    { 
     //Check if file is a zip file 
     if (C1ZipFile.IsZipFile(oFile.FullName)) 
     { 
     //Open the zip file 
     using (C1ZipFile oZipFile = new C1ZipFile(oFile.FullName, false)) 
     { 
      //Check if the zip contains the stats 
      if (oZipFile.Entries.Contains("Stats.xml")) 
      { 
      //Get the stats as a stream 
      using (Stream oStatsStream = oZipFile.Entries["Stats.xml"].OpenReader()) 
      { 
       //Load the stats as xml 
       oStatsXml = new XmlDocument(); 
       oStatsXml.Load(oStatsStream); 

       //Close the stream 
       oStatsStream.Close(); 
      } 

      //Loop hit elements 
      foreach (XmlElement oHitElement in oStatsXml.SelectNodes("/*/hits")) 
      { 
       //Do stuff 
      }     
      } 

      //Close the file 
      oZipFile.Close(); 
     } 
     } 

     //Delete the file 
     oFile.Delete(); 
    } 
    } 
} 

파일이 잠길 수있는 곳을 확인하는 중입니다. 파일 핸들을 붙잡을 수있는 모든 객체는 블록을 사용하고 명시 적으로 닫힙니다.

정적 GetFiles 메서드에서 반환 한 문자열 대신 FileInfo 개체를 사용하면 어떻게됩니까?

아이디어가 있으십니까?

+0

어디에서 예외가 발생합니까? –

+0

@Joshua - On oFile.Delete(); – stevehipwell

답변

1

oFile.Delete 호출에서 오류가 발생한다고 가정합니다. 이 오류를 재현 할 수있었습니다. 흥미롭게도 파일이 이 아니고 인 경우에만 오류가 발생합니다. 이것은 당신이보고있는 행동입니까?

ZIP 파일이 아닐 때 C1ZipFile.IsZipFile 호출이 파일을 해제하는 것처럼 보입니다. 파일 경로를 문자열로 전달하는 대신 FileStream을 사용하여이 문제를 방지 할 수있었습니다 (IsZipFile 함수도 허용 함).

그래서 코드에 다음과 같은 수정이 작동하는 것 같다 :

제목에 원래의 질문에 대한 응답으로
if (oDirectory.Exists) 
{ 
    //Loop files 
    foreach (FileInfo oFile in oDirectory.GetFiles()) 
    { 
     using (FileStream oStream = new FileStream(oFile.FullName, FileMode.Open)) 
     { 
      //Check if file is a zip file 
      if (C1ZipFile.IsZipFile(oStream)) 
      { 
      // ... 
      } 
     } 
     //Delete the file 
     oFile.Delete(); 
    } 
}  

:이 파일을 시도하지 않고 삭제 될 수 있는지 알 수 있는지 모르겠어요 삭제할 수 있습니다. 파일을 삭제하려고 시도하는 함수를 작성할 수 있으며, 실패한 경우 오류를 포착 한 다음 삭제 성공 여부를 나타내는 부울을 반환합니다.

+0

파일이 zip 파일 일 때도 오류가 발생했지만 IsZipFile 검사를 위해 스트림을 사용하면 문제가 해결 된 것으로 보입니다. 또한 zip 파일을 여는 스트림을 사용하고 있으며 XML 액세스를 사용하는 외부의 xml을 처리하고 있습니다. – stevehipwell

+0

@Stevo,이 문제를 ComponentOne에 게시해야합니다. 이것은 확실히 이상한 버그입니다. – arbiter

+0

@arbiter - ComponentOne에 게시 할 예정입니다. 내가 그것에 대해 아무 것도 할 것이라고 기대하지 않습니다. 나는 C1 구성 요소의 많은 부분에 이와 같은 재미있는 문제가 있다는 결론에 도달했습니다. 나는 DotNetZip으로 옮길 뜻을 가지고있다. – stevehipwell

1

저는 추측하고 있습니다. oZipFile.Close()로 충분하다고 확신합니까? 아마도 oZipFile.Dispose() 또는 oZipFile.Finalize()를 호출하여 리소스를 실제로 해제했는지 확인해야합니다.

+0

oZipFile은 사용중인 블록에 있으며 이러한 메소드 중 하나를 노출하지 않습니다. – stevehipwell

2

코드에 문제가 보이지 않습니다. 모든 것이 정상적으로 보입니다. 확인하려면 문제는 내가 대신 파일에서 초기화, 스트림으로부터 우편을 초기화 제안 C1ZipFile에있다, 그래서 명시 적으로 가까운 스트림 :

//Open the zip file 
using (Stream ZipStream = oFile.OpenRead()) 
using (C1ZipFile oZipFile = new C1ZipFile(ZipStream, false)) 
{ 
    // ... 

몇 가지 다른 제안 : 당신은에

  • 필요가 없습니다 Close() 메서드를 호출하고 (...)을 사용하여 제거하십시오.
  • xml 처리 (루프 히트 요소) 크기가 큰 zip 처리 (예 : zip 파일 닫기 후)가 가능하므로 파일을 가능한 한 열어 두십시오.
+0

파일 경로를 지나치지 않고 모든 것을 스트림으로 사용합니다. 이것은 Zip 파일 객체보다는 파일에 대한 잠금을 유지하고있는 IsZipFile() 호출이라고 생각하지만이 문제를 해결 한 것으로 보입니다. – stevehipwell

1

더 많은 경우 처리 된 코드가 아니기 때문에 언제든지 관리 코드 (스트림, 파일 등) 외부에있는 항목에 액세스 할 때 반드시 처리해야합니다. Asp.NET 및 Image 파일로 어려운 방법을 배웠습니다. 메모리가 가득 차거나 서버가 손상 될 수 있습니다.

1

변경 사항이 하나 이상의 출처에서 왔기 때문에 완성을 위해 작업 코드를 사용하고 있습니다. .

private void UnPackLegacyStats() 
{ 
    DirectoryInfo oDirectory; 
    XmlDocument oStatsXml; 

    //Get the directory 
    oDirectory = new DirectoryInfo(msLegacyStatZipsPath); 

    //Check if the directory exists 
    if (oDirectory.Exists) 
    { 
    //Loop files 
    foreach (FileInfo oFile in oDirectory.GetFiles()) 
    { 
     //Set empty xml 
     oStatsXml = null; 

     //Load file into a stream 
     using (Stream oFileStream = oFile.OpenRead()) 
     { 
     //Check if file is a zip file 
     if (C1ZipFile.IsZipFile(oFileStream)) 
     { 
      //Open the zip file 
      using (C1ZipFile oZipFile = new C1ZipFile(oFileStream, false)) 
      { 
      //Check if the zip contains the stats 
      if (oZipFile.Entries.Contains("Stats.xml")) 
      { 
       //Get the stats as a stream 
       using (Stream oStatsStream = oZipFile.Entries["Stats.xml"].OpenReader()) 
       { 
       //Load the stats as xml 
       oStatsXml = new XmlDocument(); 
       oStatsXml.Load(oStatsStream); 
       } 
      } 
      } 
     } 
     } 

     //Check if we have stats 
     if (oStatsXml != null) 
     { 
     //Process XML here 
     } 

     //Delete the file 
     oFile.Delete(); 
    } 
    } 
} 

나는이 배운 가장 큰 교훈은 다른 구성 요소가 자신의 파일 액세스를 관리시키는 대신 호출 코드에서 한 곳에서 파일 액세스를 관리하는 것입니다.다른 구성 요소가 작업을 마친 후에 파일을 다시 사용하려면 가장 적합합니다.

약간 더 많은 코드가 사용되지만 구성 요소가 스트림을 올바르게 폐기했음을 신뢰할 필요가있는 것과 비교하여 스트림이 폐기 된 곳 (사용 끝)을 명확하게 볼 수 있습니다.

관련 문제