1

バイナリ ファイルがあるとします。正の 2 進数が含まれていますが、32 ビット整数としてビッグ エンディアンで記述されています。

このファイルの読み方を教えてください。私は今これを持っています。

int main() {
    FILE * fp;
    char buffer[4];
    int num = 0;
    fp=fopen("file.bin","rb");
    while ( fread(&buffer, 1, 4,fp) != 0) {

        // I think buffer should be 32 bit integer I read,
        // how can I let num equal to 32 bit big endian integer?
    }
    return 0;
}
4

3 に答える 3

8

バッファを次のように宣言します。

unsigned char buffer[4];

これを使用してエンディアンを変換できます。

int num = (int)buffer[0] | (int)buffer[1]<<8 | (int)buffer[2]<<16 | (int)buffer[3]<<24;

ところで

もちろん、これはリトル エンディアンの x86 アーキテクチャに適用されます。それ以外の場合、プラットフォームのエンディアンがファイルのエンディアンと一致する可能性があるため、変換は必要ありません。このようにして、変換なしで int に直接読み取ることができます。

于 2013-11-03T08:33:24.563 に答える
4

最初にエンディアンを見つける必要があります。

C を使用してプログラムで PC のエンディアンを見つけるにはどうすればよいですか?

次に、それに応じて行動する必要があります。ファイルと同じ場合は、値をそのまま読み取ることができます。エンディアンが異なる場合は、バイトを並べ替える必要があります。

union Num 
{
    char buffer[4];
    int num;
} num ;

void swapChars(char* pChar1, char* pChar2)
{
    char temp = *pChar1;
    *pChar1 = *pChar2;
    *pChar2 = temp;
}

int swapOrder(Num num)
{
    swapChar( &num.buffer[0], &num.buffer[3]);
    swapChar( &num.buffer[1], &num.buffer[2]);

    return num.num; 
}

while ( fread(&num.buffer, 1, 4,fp) != 0)
{
    int convertedNum;
    if (1 == amIBigEndian) 
    {
        convertedNum = num.num
    } 
    else
    {
        convertedNum = swapOrder(num);
    }
    // Do what ever you want with convertedNum here...
}
于 2013-11-03T09:13:41.137 に答える
3

これは、オペレーティング システムとプロセッサ アーキテクチャ固有のものです。

おそらくhtonl(3)などのルーチンを使用するかもしれませんntohl...

ただし、明確に定義された形式でシリアル化する必要があります。

現在のマシン (I/O が非常に遅く、CPU 速度に関して) では、 JSON 、 YAML などのテキスト シリアライゼーション形式を使用すること好みますASN.1またはs11nライブラリ....

可能であれば、プロデューサー コード (ファイルを書き込むfile.binコード) を改善し、それに応じてコンシューマー コードを改善します。

バイナリ データは、システムとアーキテクチャに固有であるため、本質的に脆弱です。少なくとも、その形式を非常によく文書化し、できればテキスト形式との間で変換するためのツールを提供してください。

jsoncpprapidjsonなどの C++ 用の JSON ライブラリと、 janssonなどのC 用の JSON ライブラリがいくつかあります。

于 2013-11-03T08:32:37.010 に答える