2011-11-04 1 views
1

당신이 C++로 다음과 같은 한 상상 쓰는 동안 :올리기 C에서 신뢰할 수없는 디스크 ++

ofstream myfile; 
myfile.open (argv[1]); 

if (myfile.is_open()){ 
for(int n=0;n<=10;n++){ 
    myfile << "index="<<n<<endl; 
    sleep(1); 
} 
}else{ 
cerr << "Unable to open file"; 
} 

myfile.close(); 

를 그리고 쓰는 동안, 디스크 나 매체가 당신이 사용할 수 없게되지만를 위해 다시 온다 작성 close()를 사용하면 중간에 데이터가 누락 될 수 있습니다. 또는 USB 플래시 드라이브에 쓰고 장치가 쓰여지고 쓰는 동안 다시 삽입되었다고 상상해보십시오. 어떻게 감지 할 수 있습니까? try {} catch, flags(), rdstate()에 쓰기를 넣었는지 확인해 보았습니다. 이름을 지정했지만 아무 것도 작동하지 않는 것 같습니다.

답변

1

나는 당신이 stdio 레벨에서 감지 할 수있는 것이라고 생각하지 않습니다. 일반적으로 하드 드라이브가 일시적으로 응답을 멈 추면 운영 체제는 명령이 성공하거나 제한 시간에 도달 할 때까지 시스템 호출이 오류를 수신 할 때까지 명령을 자동으로 다시 시도합니다. (데이터가 메모리 내 파일 시스템 캐시에 기록되고 명령이 실제 디스크로 보내지기 전에 호출이 이미 반환되었을 수 있으므로 OTOH가 아닐 수도 있습니다.)

flakey 하드 드라이브 , 당신은 아마 더 낮은 수준으로 코딩해야 할 것이다. 자신의 하드웨어 드라이버를 작성하십시오.

+0

USB 플래시 드라이브에 쓰고 장치를 쓰는 동안 어떨까요? – madreblu

+0

그런 다음 I/O 오류/예외가 발생하거나 그렇지 않을 수 있습니다. –

0

내가이 시나리오 (USB 드라이브 중반 쓰기 제거)를 다룰 것입니다 있는지 확실하지 않습니다,하지만 당신은 스트림에 예외를 가능하게 시도 할 수 있습니다 : 내 경험에

myfile.exceptions(ios::failbit | ios::badbit); 

, IOSTREAMS은을 " 오류 및 오류 유형을 감지하는 것을 어렵게 만드는 "훌륭한"작업입니다.

+0

그는 rdstate를 검사하고 있다고 말합니다. rdstate는 이러한 예외와 동일한 작업을 트리거하므로 예외가 실행되지 않습니다. –

+0

코드가 지금도 그렇지만 여전히 rdstate가 goodbit라고 말합니다 : myfile.exceptions (ofstream :: failbit | ofstream :: badbit); myfile.open (argv [1]); if (myfile.(int n = 0; n <= 10; n ++) { \t cout << "index ="<< n << endl; \t { \t \t cout << "index ="<< n << endl; \t \t myfile << "index ="<< n << endl; \t} catch (예외 e) { \t \t cerr << "작성 실패"<< e.what(); \t \t return 1; \t} \t myfile << flush; \t sleep (1); \t} } else { \t cerr << "파일을 열 수 없습니다."; \t return 1; } cout << (myfile.rdstate() == ios :: goodbit) << endl; – madreblu

1

당신이 시도 할 수 있습니다 IMHO :

  1. 사용 ios:exceptions
  2. 를 사용하여 낮은 수준의 OS 상호 작용
  3. (1, 2 작동하지 않는 경우) IO가 성공했는지 확인
+0

1 : 시도해 보았습니다. 에릭의 대답에 대한 내 의견을 참조하십시오. 2-3 : 예를 들면? – madreblu

+0

@madreblu, 2는 OS에 따라 다르므로 설명서를 읽어야합니다. 3 - 작성한 내용을 읽고 해당 내용이 맞는지 확인하십시오. MD5, SHA 또는 CRC와 같은 일부 체크섬 또는 해시 알고리즘을 사용할 수 있습니다. –

0
for(int n=0;n<=10;n++){ 
    if (!(myfile << "index="<<n<<endl)) 
     throw std::runtime_error("WRITE FAILED") 
    sleep(1); 
} 

어떤 이유로 든 std::ostream이 실패하면 상태 비트를 설정하고을 확인합니다.은 부울 문맥에 있습니다. 이는 std::istream이 변수에 대한 데이터를 올바르게 읽었을 때 확인하는 것과 같은 방법입니다.

그러나 이것은 시도한 것이라고 말하는 rdstate()과 동일합니다. 이 경우 쓰기가 버퍼로 전달됩니다. 프로그램 버퍼를 플러시하는 endl은 운영 체제의 버퍼에 있음을 보여줍니다. 거기에서 OS 특정 호출을 사용하여 강제로 버퍼를 플러시해야합니다.

[편집] http://msdn.microsoft.com/en-us/library/17618685(v=VS.100).aspx에 따르면 파일 설명자가있는 경우 _commit을 사용하여 강제로 플러시 할 수 있습니다. std::ostream에 대한 보증을 찾을 수 없습니다.

+0

작성했지만 아무 것도 제기되지 않았습니다. \t if (! (myfile << "index ="<< n << endl)) { \t \t cerr << "작성 실패"<< endl ;; \t \t return 1; \t} \t myfile << flush; – madreblu

+0

@madreblu : 즉, 파일이 프로그램의 외부에있는 OS 메모리에 있음을 의미합니다. 나는 아직도 RAM을 채우는 것 이외에 강제로 강제로 내리는 법을 알아 내려하고있다. 타겟 OS는 무엇입니까? 아니면 휴대용을 목표로하고 있습니까? –

+0

"myfile << flush;"라고 썼습니다. 여전히 작동하지 않는다. 나는 리눅스와 함께 모든 방법을 사용하고있다 :-) – madreblu