web-dev-qa-db-ja.com

バイト単位でバイナリistreamを読み取る

Ifstreamを使用して、バイナリファイルをバイト単位で読み取ろうとしました。以前にget()のようなistreamメソッドを使用して、問題なくバイナリファイルのチャンク全体を一度に読み取りました。しかし、私の現在のタスクは、バイト単位で実行し、ioシステムのバッファリングを利用して効率を上げることに役立っています。問題は、ファイルの終わりに到達する前に数バイト早く到達したように見えることです。そこで、次のテストプログラムを作成しました。

#include <iostream>
#include <fstream>

int main() {
    typedef unsigned char uint8;
    std::ifstream source("test.dat", std::ios_base::binary);
    while (source) {
        std::ios::pos_type before = source.tellg();
        uint8 x;
        source >> x;
        std::ios::pos_type after = source.tellg();
        std::cout << before << ' ' << static_cast<int>(x) << ' '
                  << after << std::endl;
    }
    return 0;
}

これにより、test.datの内容が1行に1バイトずつダンプされ、前後のファイル位置が示されます。

案の定、私のファイルに2バイトのシーケンス0x0D-0x0A(キャリッジリターンとラインフィードに対応)がある場合、それらのバイトはスキップされます。

  • ストリームをバイナリモードで開きました。それはそれが行セパレータを解釈することを妨げるべきではないでしょうか?
  • 抽出演算子は常にテキストモードを使用しますか?
  • バイナリistreamからバイト単位で読み取る正しい方法は何ですか?

Windows上のMSVC++ 2008。

23
Adrian McCarthy

>>抽出子はフォーマットされた入力用です。空白をスキップします(デフォルト)。単一文字のフォーマットされていない入力の場合、 istream::get() を使用できます(intを返します。EOF読み取りに失敗した場合、または[0、UCHAR_MAX]の範囲内の値)またはistream::get(char&)(引数で読み取った文字を出力し、boolに変換するものを返します。読み取りが成功した場合はtrue、成功した場合はfalse失敗します。

21
James Kanze

バイト数を指定できる read() メンバー関数があります。

5
stefaanv

.read()ではなく、なぜフォーマットされた抽出を使用しているのですか?

source.get()

シングルバイトを与えます。フォーマットされていない入力関数です。 operator >>は、空白文字をスキップすることを意味するフォーマット済み入力関数です。

4
Serge Dundich

他の人が述べたように、あなたは istream::read() を使うべきです。ただし、フォーマットされた抽出を使用する必要がある場合は、 std::noskipws

2
Robᵩ