2009-03-02 6 views
8

2 진 파일에서 부호없는 바이트를 읽으려고합니다. 그래서 다음 코드를 작성했습니다.파일 스트림에서 서명되지 않은 char을 읽는 C++

#include <iostream> 
#include <fstream> 
#include <vector> 
#include <istream> 

std::string filename("file"); 
size_t bytesAvailable = 128; 
size_t toRead = 128; 

std::basic_ifstream<unsigned char> inf(filename.c_str(), std::ios_base::in | std::ios_base::binary) ; 
if (inF.good()) 
{ 
    std::vector<unsigned char> mDataBuffer; 
    mDataBuffer.resize(bytesAvailable) ; 
    inF.read(&mDataBuffer[0], toRead) ; 
    size_t counted = inF.gcount() ; 
} 

결과적으로 counted 변수에 표시된대로 항상 0 바이트로 읽습니다.

이 작업을 수행하기 위해 로캘을 설정해야한다는 웹 참조가있는 것 같습니다. 이 작업을 정확하게 수행하는 방법은 분명하지 않습니다.

같은 코드는 데이터 유형 대신 '서명 숯불'

서명 숯불 Windows에서 작동하는 것 같다 사용하여 위의 코드의 '문자'를 사용하여 작동하지만 colinux 페도라 2.6.22.18에서 실행되지 않습니다.

Linux 용으로 작동 시키려면 어떻게해야합니까?

+0

가 아닌 경우 질문에 대한 대답,하지만 관련.C++에서 문자열 클래스의 정의는'typedef basic_string string;'입니다. 따라서 unsigned char 문자열 클래스를 항상'typedef basic_string bytestring; '으로 만들 수 있습니다. –

+0

사실, 이진 파일을 읽으려는 경우 – David

+0

.read() 및 .write()를 이진/텍스트에 사용할 수있는 경우 스트림 연산자 << and >>은 텍스트 파일 전용입니다. 컴퓨터의 모든 데이터는 궁극적으로 바이너리이며 해석 방법은 사용자가 선택하는 방식입니다. – sfossen

답변

15

C++은 캐릭터 특성의 두 가지 버전에 대한 명시 적 특수화를 제공하기 위해 구현을 필요로하지 :

std::char_traits<char> 
std::char_traits<wchar_t> 

스트림의 문자열은 다양한 알아 내기 위해 이러한 특성을 사용 EOF 값, 문자 범위 비교, 문자를 int로 확대하는 것과 같은 것들을 포함합니다.

당신이 스트림이 사용할 수있는 해당 문자의 특성 전문화가 있는지 확인해야하고이 특성화 유용한 일을한다는 것을

std::basic_ifstream<unsigned char> 

같은 스트림을 인스턴스화합니다. 또한 스트림은 패싯을 사용하여 실제 서식을 지정하고 숫자를 읽습니다. 마찬가지로 수동으로도 전문 분야를 제공해야합니다. 표준에서는 구현시 기본 템플릿의 완전한 정의가 필요하지 않습니다. (A basic_ifstream<char> 인) 대신

error: specialization std::char_traits could not be instantiated.

내가 사용하는 것이 ifstream 다음 vector<char>에 가서 읽어 : 그래서 당신은 aswell 컴파일 오류를 얻을 수 있습니다. 벡터의 데이터를 해석 할 때는 나중에 unsigned char으로 변환 할 수 있습니다.

+3

나는 컴파일러 오류가 발생하지 않았으며, 문서에 아무런 힌트도, 아무 것도 없지만 조용한 실패와 낭비되는 날을 보지 못했습니다. Bjarne Stroustrup과 Dennis Ritchie에게 감사드립니다. – user1358

13

basic_ifstream을 특수화가 필요하므로 사용하지 마십시오. 예약을 사용하여

linux ~ $ cat test_read.cpp 

#include <fstream> 
#include <iostream> 
#include <vector> 
#include <string> 


using namespace std; 

int main(void) 
{ 
     string filename("file"); 
     size_t bytesAvailable = 128; 
     size_t toRead = 128; 

     ifstream inf(filename.c_str()); 
     if(inf) 
     { 

       vector<unsigned char> mDataBuffer; 
       mDataBuffer.resize(bytesAvailable) ; 

       inf.read((char*)(&mDataBuffer[0]), toRead) ; 
       size_t counted = inf.gcount(); 
       cout << counted << " size=" << mDataBuffer.size() << endl; 
       mDataBuffer.resize(counted) ; 
       cout << counted << " size=" << mDataBuffer.size() << endl; 

     } 

     return 0; 
} 
linux ~ $ g++ test_read.cpp -Wall -o test_read 
linux ~ $ ./test_read 
7 size=128 
7 size=7 

대신 첫 번째 호출에서 크기를 조정 : : 벡터를 사용하여

linux ~ $ cat test_read.cpp 
#include <fstream> 
#include <iostream> 
#include <vector> 
#include <string> 


using namespace std; 

int main(void) 
{ 
     string filename("file"); 
     size_t bytesAvailable = 128; 

     ifstream inf(filename.c_str()); 
     if(inf) 
     { 
       unsigned char mDataBuffer[ bytesAvailable ]; 
       inf.read((char*)(&mDataBuffer[0]), bytesAvailable) ; 
       size_t counted = inf.gcount(); 
       cout << counted << endl; 
     } 

     return 0; 
} 
linux ~ $ g++ test_read.cpp 
linux ~ $ echo "123456" > file 
linux ~ $ ./a.out 
7 

:

linux ~ $ cat test_read.cpp 

#include <fstream> 
#include <iostream> 
#include <vector> 
#include <string> 


using namespace std; 

int main(void) 
{ 
     string filename("file"); 
     size_t bytesAvailable = 128; 
     size_t toRead = 128; 

     ifstream inf(filename.c_str()); 
     if(inf) 
     { 

       vector<unsigned char> mDataBuffer; 
       mDataBuffer.reserve(bytesAvailable) ; 

       inf.read((char*)(&mDataBuffer[0]), toRead) ; 
       size_t counted = inf.gcount(); 
       cout << counted << " size=" << mDataBuffer.size() << endl; 
       mDataBuffer.resize(counted) ; 
       cout << counted << " size=" << mDataBuffer.size() << endl; 

     } 

     return 0; 
} 
linux ~ $ g++ test_read.cpp -Wall -o test_read 
linux ~ $ ./test_read 
7 size=0 
7 size=7 

당신이 볼 수 있듯이,이없는 정적 버퍼를 사용

.resize (counted)를 호출하면 벡터 크기가 잘못됩니다. 그 점을 명심하십시오. 이 주조보고 사용하는 일반적인 cppReference

+0

의 전체 구현을가집니다. 서명 된 문자를 읽는 중입니다. 나는이 작품을 알아. 나는 특별히 unsigned chars를 읽길 원한다. – David

+0

그냥 char []을 unsigned char []로 바꾼다. – sfossen

+0

그리고 캐스트를 추가하십시오 : P – sfossen

0

훨씬 쉬운 방법 :

#include <fstream> 
#include <vector> 

using namespace std; 


int main() 
{ 
    vector<unsigned char> bytes; 
    ifstream file1("main1.cpp", ios_base::in | ios_base::binary); 
    unsigned char ch = file1.get(); 
    while (file1.good()) 
    { 
     bytes.push_back(ch); 
     ch = file1.get(); 
    } 
    size_t size = bytes.size(); 
    return 0; 
} 
+0

이것은 매우 비효율적입니다. 1GB 파일로 벤치 마크를 실행하면 통화 오버 헤드가 큰 차이를 보입니다. – sfossen

+0

이 작동하지만 읽기 호출이 실패하는 이유는 무엇입니까? – David

+0

파일이 서명 된 char 하나이므로 !!!! 나는 그것을보아야 만했다. – David

관련 문제