2

.bmp 画像を開き、それを 2D 配列に入れることができる C++ プログラムを作成しています。今、私は次のようなコードを持っています:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "Image.h"
using namespace std;

struct colour{
    int red;
    int green;
    int blue;
};

Image::Image(string location){

    fstream stream;
    string tempStr;

    stringstream strstr;
    stream.open(location);

    string completeStr;

    while(!stream.eof()){
        getline(stream, tempStr);
        completeStr.append(tempStr);
    }
    cout << endl << completeStr;

    Image::length = completeStr[0x13]*256 + completeStr[0x12];
    Image::width = completeStr[0x17]*256 + completeStr[0x16];
    cout << Image::length;
    cout << Image::width;
    cout << completeStr.length();

    int hexInt;
    int x = 0x36;
    while(x < completeStr.length()){
        strstr << noskipws << completeStr[x];
        cout << x << ": ";
        hexInt = strstr.get();
        cout << hex << hexInt << " ";
        if((x + 1)%3 == 0){
            cout << endl;
        }
        x++;
    }
}

256x256 のテスト ファイルでこれを実行すると、0x36E に到達してエラーが発生し、それ以上進まなくなるまで正常に印刷されます。これは、completeStr文字列が bmp ファイル内のすべてのデータを受信して​​いないために発生します。bmp ファイルのすべての行を読み取れないのはなぜですか?

4

2 に答える 2

9

コードには多くの問題があります。主なもの (そしておそらく問題の原因) は、ファイルをテキスト モードで開いていることです。技術的には、これは、ファイルに印刷可能な文字といくつかの特定の制御文字 (「\t」など) 以外が含まれている場合、未定義の動作が発生することを意味します。実際には、Windows では、これは 0x0D、0x0A のシーケンスが単一の に変換され'\n'、0x1A がファイルの終わりとして解釈されることを意味します。バイナリデータを読み取るときに実際に必要なものではありません。バイナリ モードでストリームを開く必要があります ( std::ios_base::binary)。

重大なエラーではありませんがfstream 、ファイルを読み取るだけの場合は実際には使用しないでください。実際、 を使用する fstreamことは非常にまれです。 または のいずれかを使用する必要がありifstream ますofstream。同じことが当てはまります(ただし、バイナリファイルを読み取るときのstringstream役割はわかりません)。stringstream

また (これは実際のエラーです)、 getline成功したかどうかを確認せずに の結果を使用しています。行を読むための通常のイディオムは次のようになります。

while ( std::getline( source, ling ) ) ...

しかし、のようstringstreamに、バイナリ ストリームでは使用したくありません。(既に CRLF からマップされている)getlineすべてを削除します。'\n'

メモリ内のすべてのデータが必要な場合、最も簡単な解決策は次のようなものです。

std::ifstream source( location.c_str(), std::ios_base::binary );
if ( !source.is_open() ) {
    //  error handling...
}
std::vector<char> image( (std::istreambuf_iterator<char>( source ) ),
                         (std::istreambuf_iterator<char>()) );
于 2013-04-05T18:16:21.567 に答える
2

std::getlineテキストの行を読み取ります。

バイナリ ファイルには役に立ちません。

ファイルをバイナリ モードで開き、フォーマットされていない入力操作 ( などread) を使用します。

于 2013-04-05T17:40:26.713 に答える