2009-03-02 149 views
8

我想從二進制文件中讀取無符號字節。 所以我寫了下面的代碼。從文件流中讀取無符號字符的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() ; 
} 

這會導致讀數始終爲0字節,如變量計數所示。

似乎有網上的參考資料,說我需要設置語言環境來完成這項工作。如何做到這一點是不明確的。

相同的代碼工作使用的數據類型,而不是「無符號的字符」

使用無符號字符似乎在Windows上運行上面的代碼「字符」,但在coLinux的Fedora的2.6.22.18失敗運行。

我需要做些什麼才能讓它適用於Linux?

+0

不是一個問題的答案,但相關的。請記住,C++中字符串類的定義是`typedef basic_string string;`,所以你總是可以使一個unsigned char字符串類成爲``typedef basic_string bytestring;`。 – 2009-03-02 23:47:11

+0

是真的,但我想讀取一個BINARY文件 – David 2009-03-03 06:29:06

+0

.read()和.write()可用於二進制/文本,流操作符<< and >>僅用於文本文件。計算機上的所有數據最終都是二進制的,這就是你如何選擇解釋它。 – sfossen 2009-03-03 15:35:11

回答

15

C++確實需要只執行爲性格特徵的兩個版本提供明確的限定:

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

的流和字符串使用這些特質找出各種的東西,比如EOF值,一系列字符的比較,一個字符擴展到一個int等等。

如果你喜歡實例

std::basic_ifstream<unsigned char> 

流你必須確保有相應的性格特徵專業化的流可以使用,並且這種專業化確實做有用的事情。另外,流使用facet來進行實際的格式設置和數字的讀取。同樣,你也必須手動提供這些專業化。該標準甚至不要求實現具有主模板的完整定義。所以,你可以得到藏漢編譯錯誤:

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

我會用ifstream,而不是(這是一個basic_ifstream<char>),然後去讀入vector<char>。在解釋向量中的數據時,您仍然可以稍後將它們轉換爲unsigned char

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; 

     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.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; 
     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(計數),矢量的大小將是錯誤的。請記住這一點。 它是一種常見的使用鑄造看cppReference

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; 
}