2011-03-07 6 views
2

나는 제어 할 수없는 다른 프로세스에서 생성 된 파일을 처리하기 위해 Windows 서비스를 작성하고 있습니다. 이러한 파일은 잠재적으로 매우 클 수 있습니다 (수백 메가 바이트).다른 프로세스가 파일을 만드는 과정에 있는지 알 수 있습니까?

파일을 만든 후에 처리하고 삭제해야합니다.

모든 파일은 특정 디렉토리 (필자가 알고있는 한 직선 파일 복사본)로 작성되므로 주기적으로 해당 디렉토리의 파일을 반복하여 처리 한 다음 삭제할 수 있습니다.

대용량 파일을 작성하는 동안 서비스에서 디렉토리를 쿼리하면 어떻게됩니까? 파일이 내 서비스에 표시됩니까? 읽기 권한을 얻을 수 없도록 잠겨 있습니까? 파일이 복사를 완료했는지 여부를 확인하기 위해 특별한 작업을 수행해야합니까, 아니면 File.Exists()을 쿼리하거나 FileAccess.Read으로 열어 볼 수 있습니까? Windows는 복사되는 파일을 어떻게 표시합니까?

답변

2

평범한 win32 인 경우 CreateFile()이라는 파일을 열고 다른 사용자에게 쓰기 권한을 거부하는 공유 모드를 시도합니다. 파일이 이미 쓰기 권한으로 열렸을 때 쓰기 권한을 거부 할 수 없기 때문에 다른 프로그램이 파일을 계속 쓰는 경우 실패해야합니다. 성공하면 다른 프로세스가 완료되었음을 알게됩니다.

.net에서 예를 들어 FileShare 매개 변수를받는 생성자 중 하나를 사용하여 FileStream을 만들 수 있습니다. 그러면 궁극적으로 기본 CreateFile() API로 매핑됩니다.

0

임시 파일 이름으로 파일을 쓰고 파일 이름을 바꿉니다.

이름 바꾸기는 자동으로 수행되므로 파일을 처리하는 서비스가 정상적으로 처리되어야합니다. 서비스가 임시 파일 이름을 건너 뛰는 지 확인하십시오.

+0

Windows가하는 것입니까, 내가 뭘해야한다고 추천합니까? 필자는 쓰기 과정을 제어 할 수 없습니다. –

+0

"임시 파일 이름으로 파일 쓰기 및 파일 이름 바꾸기"Windows에서이 방법이 작동하도록합니까? 그 공식 문서가 있습니까? 리눅스에서 글쓰기가 끝나기 전에 이름이 바뀔 수 있습니다. – CodesInChaos

+0

이 방법으로 구현할 수 있지만 과정을 작성하는 과정에 액세스해야합니다. –

1

AFAIK 파일에 쓰기 표시가 있다는 점을 제외하고는 복사 중임을 나타내는 특별한 표시가 없습니다. 이 상황에서는 쓰기 잠금 (예 : FileShare.Read)을 사용하여 파일을 직접 열고 파일이 이미 잠겨 있기 때문에 발생하는 IOException을 잡으려고 시도하는 것이 일반적입니다. 이 경우 파일을 다시 시도하기 전에 잠시 멈추어야합니다 (Thread.Sleep). 기존 파일 잠금이 해제되지 않을 경우를 대비하여 무한 루프를 방지하기 위해 재시도 횟수를 제한 할 수 있습니다.

파일을 처리하고 삭제 하시겠습니까?

string sourcePath = @"C:\temp1\temp.txt"; 
string targetPath = @"C:\temp2\temp.txt"; 
int attempt = 0; 
const int maxAttempts = 3; 
bool moved = false; 
do 
{ 
    try 
    { 
     File.Move(sourcePath, targetPath); 
     moved = true; 
    } 
    catch (IOException) 
    { 
     if (attempt < maxAttempts) 
     { 
      System.Threading.Thread.Sleep(1000); 
      attempt++; 
     } 
    } 
} while (!moved && attempt < maxAttempts); 

if (moved) 
{ 
    ProcessFile(targetPath); 
    File.Delete(targetPath); 
} 
else 
{ 
    throw new InvalidOperationException("Unable to process '" + sourcePath + "'."); 
} 

편집 : 당신이 그것을/삭제를 처리하는 동안 동일한 파일에 다른 프로세스/스레드 쓰기와 경쟁을 피하기 위해이 같은 원자 예를 들어, 동작, 무언가로 삭제/당신의 처리를 생각한다 : 파일이 매우 커질 수 있으므로 File.ReadAllText를 사용하면 안된다고 생각합니다. 파일을 다른 디렉토리로 이동하려고 시도 할 수 있습니다. 예외가 발생하면 파일이 다른 프로세스에 의해 여전히 잠겨 있습니다. 파일을 성공적으로 이동 한 경우에만 파일을 처리합니다. 이것은 또한 입력 디렉토리에서 파일을 제거하는 이점이 있습니다.

+1

'FileAccess.Write'가 파일이 잠긴 것으로 생각하지 않습니다. 잠금을 제어하는 ​​것은'FileShare'입니다. –

+0

맞습니다. – Polyfun

관련 문제