2013-07-04 3 views
2

이것을 수행하는 표준 방법은 무엇입니까?C++을 사용하여 이진 파일을 null 바이트로 읽음

나는 여기 wstring으로 읽어야하는데, 답변은 string에도 적용되어야합니다. 여기

는 지금 노력하고있는 작업은 다음과 같습니다

wifstream file(filename, ios::in | ios::binary); 
// this next line is cleverer but works the same way (i.e. null byte stops it) 
// return wstring(istreambuf_iterator<wchar_t>(file), istreambuf_iterator<wchar_t>()); 
wstring out; 
wchar_t buf[8192]; 
while (true) { 
    file.read(buf, 8192); 
    streamsize len = file.gcount();          
    cerr << len << "chars read.";           
    out.append(buf, len);             
    if (len != 8192) break;            
}                   
return out; 

어떻게 그것이 파일의 널 바이트가 발생하면 읽기 계속받을 수 있나요?

POSIX에 어떤 파일에도 null 바이트가 존재하지 않도록하는 법령이있는 경우 실제로 놀랐을 것입니다. 그러나 분명히 Vim은 모든 마술을 사용하여 모든 null을 실행 취소 파일 형식으로 작성합니다. 또한 임의의 바이트 스트림 (또는 여러 종류의 아날로그 샘플링)으로 항목을 인코딩하거나 암호화하는 경우 null이 발생해야합니다. 내 말은, 나는 계속 진행할 수있다. OS X의 파이프 (FIFO)는 널 바이트를 처리한다. 나는 고양이를 unofile하고, 파이프를 xxd로 파이프하여 읽을 수있다.

이것은 분명히 내가 걸려 넘어지고있는 일종의 간단한 일입니다. 이게 뭐야? 확실히 C++ 방법이 있습니다. 또는 <stdio.h>으로 길을 알고있을 수도 있습니다. 나는 알고 싶다.

% cat .dmp.cpp.un\~| xxd | head         
0000000: 5669 6d9f 556e 446f e500 0218 96c6 25f6 Vim.UnDo......%. 
0000010: 64bb 2301 6ed8 3578 5c50 61e0 eae5 a819 d.#.n.5x\Pa..... 
0000020: b17d 53b5 f932 dc9d 40aa 1b00 0000 8500 .}[email protected] 
0000030: 0000 5720 2020 2020 2020 2020 2020 2063 ..W   c 
0000040: 6572 7220 3c3c 2022 466f 756e 6420 616e err << "Found an 
0000050: 2075 6e70 7269 6e74 6162 6c65 2063 6861 unprintable cha 

바이트 2b는 처음 널 바이트입니다 :

예를 들어, 여기에 내가 함께 테스트하고있어 파일입니다. 프로그램은 44 바이트 (2c)를 읽음으로써 첫 번째 널 바이트를 기록하고 거기서 멈추게됩니다.

% la .dmp.cpp.un\~ 
-rw-r--r-- 1 lust staff 326836 Jul 4 01:41 .dmp.cpp.un~ 

추신 : here의 주석에 한 줄짜리 줄이 있습니다. 슬프게도이 문제로 어려움을 겪습니다.

+2

어떻게 확인하지 않았습니까? 문자열을 출력하는 것은 첫 번째'\ 0'에서 멈추지 만 데이터는 여전히 문자열에있을 수 있습니다. 'std :: string :: size()'를 확인해도 될까요? – arne

+0

음, 처음에는 vim undofile (KB 단위)에서 실행할 때 44 바이트 만 읽었습니다 (gcount가 나에게주는 것은 ...). 나는 파일을'xxd '하고, 44 번째 바이트는'\ 0'이다. –

+0

나는 문제없이 문자열을 가지고 동일하다 : while (file.read (buf, sizeof (buf)) .gcount()> 0) rep.append (buf, file.gcount()); – Alexis

답변

0

정규 문자열을 먼저 사용하여 문제를 해결했습니다.

ifstream file(filename, ios::in | ios::binary); 
wstring out; 
char buf[8192]; 
while (true) { 
    file.read(buf, 8192); 
    streamsize len = file.gcount(); 
    cerr << len << "chars read."; 
    string s(buf, len); 
    out.append(s.begin(), s.end()); 
    if (len != 8192) break; 
} 
return out; 
0

근본적인 원인은 wstring은 바이트가 아니라 넓은 문자를 보유한다는 것입니다. 분명히 바이트와 (와이드) 문자 사이에 변환이 필요합니다. 그것은 깨지는이 번역입니다.

이진 파일에서 바이트를 읽으려면 해당 컨테이너로 읽으십시오. 예 : std::vector<unsigned char>. 텍스트 파일에서 (넓은) 문자를 읽으려면 현재 코드로 진행하십시오. 그러나 그것들을 혼합하는 것은 문제입니다.

(다른 곳에서 문제를 표시 할 수도 있지만이 유익한 조언은 특히 ASCII 텍스트 파일과 바이너리 파일간에 약간의 차이점이 있지만 Windows는 유니 코드 (UTF-16)) 텍스트 파일 및 그 메모리 내 표시).

관련 문제