web-dev-qa-db-ja.com

ファイルストリームからunsignedcharを読み取る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バイトが読み込まれます。

これを機能させるにはロケールを設定する必要があるという参照がWeb上にあるようです。これを正確に行う方法は私にはわかりません。

同じコードは、「unsignedchar」の代わりに「char」データ型を使用して機能します

Unsigned charを使用した上記のコードは、Windowsでは機能するようですが、colinux Fedora2.6.22.18では実行できません。

Linuxで動作させるには何をする必要がありますか?

13
David

C++は、2つのバージョンの文字特性に明示的な特殊化を提供するためにのみ実装を必要とします。

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

ストリームと文字列は、これらの特性を使用して、EOF値、文字範囲の比較、文字のintへの拡張など、さまざまなことを把握します。

次のようなストリームをインスタンス化する場合

std::basic_ifstream<unsigned char>

ストリームが使用できる対応する文字特性の特殊化があり、この特殊化が有用なことを行うことを確認する必要があります。さらに、ストリームはファセットを使用して、実際のフォーマットと数値の読み取りを行います。同様に、それらの専門分野も手動で提供する必要があります。この標準では、実装でプライマリテンプレートを完全に定義する必要はありません。したがって、コンパイルエラーが発生する可能性もあります。

エラー:特殊化std :: char_traitsをインスタンス化できませんでした。

代わりにifstreambasic_ifstream<char>)を使用してから、vector<char>に移動して読み込みます。ベクトル内のデータを解釈する場合でも、後でそれらをunsigned charに変換できます。

特殊化が必要なため、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(counted)を呼び出さないと、ベクトルのサイズが間違ってしまいます。それを覚えておいてください。キャスティングを使用するのが一般的です。 cppReference を参照してください。

16
sfossen

はるかに簡単な方法:

#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
rlbond