2013-03-13 7 views
3

다른 프로세스에서 계속 쓰는 (수정 할 수없는) 버퍼 파일에서 이진 데이터를 읽으려고합니다. 파일을 열 때 다음 코드를 사용하고 있습니다.다른 프로세스에서 파일을 쓰는 동안 파일 읽기

fileH = CreateFileA((LPCSTR)filename, 
        GENERIC_READ, 
        FILE_SHARE_READ | FILE_SHARE_WRITE, 
        NULL, 
        OPEN_EXISTING, 
        FILE_ATTRIBUTE_NORMAL, NULL); 

오류없이 올바르게 열립니다. 그러나 파일에서 데이터를 읽을 때 손실 데이터 이후 파일에 쓰는 다른 프로세스를 차단하는 것 같습니다.

버퍼는 원형이며 파일 크기가 고정되어 있고 새로운 데이터가 버퍼의 이전 데이터에 지속적으로 기록됩니다.

편집 : 때때로 사소한 솔루션이 작동 ... 나는 소프트웨어 회사에 연락하고 버그에 대해 그들에게, 그리고 하루 만에 그들이 수정과 새 버전을 게시 한

. 죄송합니다.이 기능을 모든 사용자에게 적용 할 수는 없습니다.

+2

동시에 파일을 읽고 쓰는 것은 좋지 않습니다. 접근을 처리하기 위해'뮤텍스 (Mutex) '또는'이벤트 (Events)'를 사용해보십시오. –

+1

@ bash.d, 정말? '꼬리 (tail)'및 이와 유사한 유틸리티에 대해 설명하십시오. 또한 프로세스를 동기화하기 위해 뮤텍스와 이벤트를 사용할 수 없습니다. 게다가 그는 다른 응용 프로그램을 수정할 수 없다고 말하고 있습니다. –

+0

@aleguna 나락, 그렇습니다! 첫 번째 줄은 [여기] (http://msdn.microsoft.com/ko-kr/library/windows/desktop/ms686927(v=vs.85)asp)입니다. –

답변

3

우수 Far Manager의 소스 코드를 살펴볼 것을 권합니다. 내부 뷰어는 멀티 기가 바이트 파일을 쉽게 처리 할 수 ​​있으며 작성중인 파일을 표시하는 데 문제가 없으며 변경된 파일 내용을 거의 실시간으로 업데이트 할 수 있습니다. 표시되는 파일에 대해 차단 문제가 발생하지 않았습니다.

질문과 관련된 소스 코드는 viewer.cpp 파일에있는 것 같습니다. 내가 여기에 중요 할 수 SYNCHRONIZE을 삭제 의심하는

ViewFile.Open(strFileName, FILE_READ_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, nullptr, OPEN_EXISTING); 

:

한 가지 흥미로운 점은 하지 사용 GENERIC_READ을 수행한다는 것이다.

Viewer::ProcessKey에, KEY_IDLE 경우는 파일 변경 감지가된다

// Smart file change check -- thanks Dzirt2005 
// 
bool changed = (
    ViewFindData.ftLastWriteTime.dwLowDateTime!=NewViewFindData.ftLastWriteTime.dwLowDateTime || 
    ViewFindData.ftLastWriteTime.dwHighDateTime!=NewViewFindData.ftLastWriteTime.dwHighDateTime || 
    ViewFindData.nFileSize != NewViewFindData.nFileSize 
); 
if (changed) 
    ViewFindData = NewViewFindData; 
else { 
    if (!ViewFile.GetSize(NewViewFindData.nFileSize) || FileSize == static_cast<__int64>(NewViewFindData.nFileSize)) 
     return TRUE; 
    changed = FileSize > static_cast<__int64>(NewViewFindData.nFileSize); // true if file shrank 
} 

캐시 파일 읽기는 cache.cpp에서 구현됩니다. 그러나 거기에는 전혀 흙이 없으며 단지 Seek()Read() (은 SetFilePointerExReadFile API 호출에 해당합니다). OVERLAPPED는 사용되지 않습니다.

+0

다른 프로세스에서 단독 모드로 열어 본 파일을 볼 수 있다면 꽤 놀랄 것입니다. –

+0

물론 독점적으로 열린 파일에서는 작동하지 않습니다. 하지만 로그 파일의 경우 일반적으로 발견되지 않았습니다. –

4

필기 프로세스가 파일을 여는 방법을 모른 채 옵션이 무엇인지 말하기는 어렵습니다. 분명히 독점 액세스를 위해 파일을 열지 않고 열어 두는 것입니다. 그렇지 않으면 전혀 읽지 못할 것입니다.

설명하는 동작은 쓰기 프로세스가 단독 액세스를 위해 파일을 열고 파일에 쓰고 파일을 닫음을 나타냅니다. 그렇다면 프로그램에서 파일을 열고 열어 둘 수 없습니다. 그럴 경우 쓰기 작업이 실패 할 때마다 쓰기 프로세스가 실패하게됩니다.

글쓰기 과정을 수정할 수없는 경우 옵션이 제한적이고별로 매력적이지 않습니다. 대부분 프로그램에서 파일을 열고 작은 덩어리를 읽은 다음 파일을 닫은 다음 다시 읽으려면 잠시 기다려야합니다. 그럼에도 불구하고, 쓰기 프로세스가 쓰기를 시도 할 때 파일을 열지 않을 것이라는 보장은 없습니다. 내가 생각하기에, 당신은 이미 발견했습니다.

파일을 열 수 없거나 파일을 실제로 버퍼링 할 수있을 때 데이터를 버퍼링하고 쓰기 만하는 경우 쓰기 프로세스에서 데이터가 손실되는지 알고 계십니까? 그렇다면 파일을 한 번에 조금씩 스테핑하는 것이 좋습니다. 그렇지 않으면 데이터가 손실됩니다.

내가 알고있는 열기 모드는 "읽기 위해 파일을 열지 만 누군가가 독점적 액세스를 원한다면 그 파일을 갖도록하십시오."

또 다른 가능성은 읽으려고 할 때마다 프로그램의 파일 이름을 변경 한 다음 이름을 변경 한 파일을 읽은 후에 삭제하는 것입니다. 이것은 물론 필기 과정이 필요하다면 새로운 파일을 만들 것이라고 가정합니다. 심지어 그때도, 일 수 있습니다. 쓰기 프로세스가 이름을 바꿀 때 쓰려고하면 문제가 될 수 있습니다. 나는 그것이 문제가 될 것이라고 생각하지 않는다. (파일 시스템에 관한 한 이름 바꾸기는 원자적일 수있다.) 그러나 연구해야 할 것이있다.

+0

데이터는 쓰기 프로세스에서 실제로 손실되므로 매우 짧은 기간 동안 파일을 열어도이 손실이 발생할 수 있습니다. 파일의 이름을 바꾸면 흥미로운 가능성이 들리 겠지만 확인해 보겠습니다. – user1447407