2009-03-02 5 views
8

バイナリファイルから符号なしバイトを読み取る必要があります。 だから私は次のコードを書いた。ファイルストリームからunsigned 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() ; 
} 

この結果、カウントされる変数の値が常に0バイトになります。

ウェブ上でこの作業を行うためにロケールを設定する必要があるとの言及があるようです。これを正確に行う方法は私には分かりません。

同じコードはunsigned char型を使用して代わりに「unsigned char型」

の上記のコードをデータ型「文字」を使用して動作しますが、Windows上で動作するようですが、coLinuxのFedoraの2.6.22.18で実行して失敗しました。

Linuxで動作させるには、何が必要ですか?

+0

ない質問への答えが、関連します。C++の文字列クラスの定義は 'typedef basic_string string;'なので、unsigned char文字列クラスを常に 'typedef basic_string bytestring;にすることができます。 –

+0

trueですが、BINARYファイルを読み込みたい – David

+0

.read()と.write()はバイナリ/テキストに使用できます。ストリーム演算子<< and >>はテキストファイルのみです。コンピュータ上のすべてのデータは最終的にはバイナリであり、それをどのように解釈するか選択します。 – sfossen

答えて

15

C++のみ文字の特徴の2つのバージョンの明示的な特殊化を提供するために、実装を必要としない参照のキャストを使用するのが一般的ですEOF値、文字の範囲の比較、文字をintに広げるなどのものが含まれます。

あなたはストリームを使用することができ、対応する性格特性の専門があることを確認する必要があり、これ分業が役に立つことをするのかということ

std::basic_ifstream<unsigned char> 

のようなストリームをインスタンス化した場合。さらに、ストリームはファセットを使用して実際の書式設定や数値の読み取りを行います。同様に手作業でも専門化する必要があります。この標準では、インプリメンテーションがプライマリテンプレートの完全な定義を持つ必要はありません。 (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)を呼び出すと、ベクトルのサイズが正しくありません。それを覚えておいてください。

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

ストリームと文字列は、さまざまなを把握するために、これらの特性を使用します。 それはcppReference

+0

これは署名付き文字の読み取りです。私はこの作品が分かっています。私は具体的には、符号なしの文字 – 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

ファイルは署名された文字なので、!!!!私はそれを見たはずです。 – David

関連する問題