6

バイナリ ファイルからバイトを読み込もうとしていますが、成功しません。私は多くの解決策を試しましたが、結果が得られません。ファイルの構造:

[offset] [type]          [value]          [description] 
0000     32 bit integer  0x00000803(2051) magic number 
0004     32 bit integer  60000            number of images 
0008     32 bit integer  28               number of rows 
0012     32 bit integer  28               number of columns 
0016     unsigned byte   ??               pixel 
0017     unsigned byte   ??               pixel 
........ 
xxxx     unsigned byte   ??               pixel

私が試した方法(動作しません):

auto myfile = fopen("t10k-images.idx3-ubyte", "r");
char buf[30];
auto x = fread(buf, 1, sizeof(int), myfile);
4

4 に答える 4

3

バイトをunsigned char次のように読み取ります。

ifstream if;

if.open("filename", ios::binary);

if (if.fail())
{
    //error
}

vector<unsigned char> bytes;

while (!if.eof())
{
    unsigned char byte;

    if >> byte;

    if (if.fail())
    {
        //error
        break;
    }

    bytes.push_back(byte);
}

if.close();

次に、複数のバイト32-bit integerをたとえばに変換するには:

uint32_t number;

number = ((static_cast<uint32_t>(byte3) << 24)
    | (static_cast<uint32_t>(byte2) << 16) 
    | (static_cast<uint32_t>(byte1) << 8) 
    | (static_cast<uint32_t>(byte0)));

これにより、エンディアンの問題がカバーされるはずです。変換はビット シフトによって処理されるため、システム上またはシステム上に表示intされるかどうかは問題ではありません。コードは、メモリ内の特定の順序を想定していません。B0B1B2B3B3B2B1B0

于 2012-10-13T19:57:12.427 に答える
2

C++ ストリーム ライブラリ関数read()は、バイナリ ファイルの I/O に使用できます。リンクのコード例を考えると、次のように始めます。

std::ifstream myfile("t10k-images.idx3-ubyte", std::ios::binary);
std::uint32_t magic, numim, numro, numco;

myfile.read(reinterpret_cast<char*>(&magic), 4);
myfile.read(reinterpret_cast<char*>(&numim), 4);
myfile.read(reinterpret_cast<char*>(&numro), 4);
myfile.read(reinterpret_cast<char*>(&numco), 4);

// Changing byte order if necessary
//endswap(&magic);
//endswap(&numim);
//endswap(&numro);
//endswap(&numco);

if (myfile) {
    std::cout << "Magic = "  << magic << std::endl
              << "Images = " << numim << std::endl
              << "Rows = "   << numro << std::endl
              << "Cols = "   << numco << std::endl;
}

バイト オーダー (エンディアン) を逆にする必要がある場合は、次のような単純な逆関数を記述できます。endswap()

于 2012-10-13T20:33:39.393 に答える
1

これは、ファイルから uint32_t を読み取る方法です。

auto f = fopen("", "rb"); // not the b, for binary files you need to specify 'b'

std::uint32_t magic = 0;
fread (&magic, sizeof(std::uint32_t), 1, f);

お役に立てれば。

于 2012-10-13T19:49:22.580 に答える
1

マルチバイト数値を読み取るファイル レイアウトのエンディアンを知ることは重要です。ビッグエンディアンが常に書き込まれた形式であると仮定し、値が実際に 32 ビットの符号なし値であると仮定します。

uint32_t magic = 0;
unsigned char[4] bytes;
if (1 == fread(bytes, sizeof(bytes), 1, f))
{
   magic = (uint32_t)((bytes[0] << 24) | 
                      (bytes[1] << 16) | 
                      (bytes[2] << 8) | 
                      bytes[3]);
}

注: これは、リーダー(プログラム) がリトル エンディアンかビッグ エンディアンかに関係なく機能します。私はそこに少なくとも1つのキャストを逃したと確信していますが、うまくいけば要点を理解していただけます. マルチバイト数値を読み取る唯一の安全でポータブルな方法は、(a) それらが書き込まれたエンディアンを知り、(b) それらをバイト単位で読み取ってアセンブルすることです。

于 2012-10-13T20:04:12.750 に答える