3

うまくいけば、ここの誰かが助けてくれるでしょう。私の問題は次のとおりです。

バイナリ データを含むファイルを作成しています。各ファイルの先頭には、ファイルの内容に関する情報を含むバイナリ ヘッダーがあります。ファイル ヘッダーは 52 バイトの固定サイズです。ヘッダーには、ヘッダー内の特定のバイト オフセットに特定の情報がありますが、一部の情報はバイトの一部、たとえば 3 ビットしかカバーしていません。

例えば:

バイト 1 ~ 4 = ファイル長

バイト 5 ~ 8 = ヘッダー長

バイト 8 ~ 9 = バージョン情報

バイト 10 ~ 13 = ファイル作成のタイムスタンプ

ビット 1 ~ 4 = 月 (1 ~ 12)

ビット 5 ~ 9 = 日 (1 ~ 31)

ビット 10 ~ 14 = 時間 (0 ~ 23)

ビット 15 ~ 20 = 分 (0 ~ 59)

ビット 21 = UTC オフセット方向

ビット 22 ~ 26 = UTC オフセット時間

ビット 27 ~ 32 = UTC オフセットの分

等...

一部の値は静的に定義され、一部は実行時に決定されます。私が試みたのは、ヘッダーの「マップ」を作成し、属性が消費する必要があるビット数と、ビットで表される値を定義することです。これらは int ペアのベクトルに格納されます。int_pair.first は値、int_pair.second はビット数です。次に、指定された値 (すべて整数) をバイナリ形式に変換し、バイナリ表記を文字列ストリームに挿入します。次に、バイナリ値の文字列表現からビットセットを作成し、それをファイルに書き込みます。私の問題は、バイトが出力ファイルに適切な順序で表示されないことです。

この例では、値を取得する方法を省略し、整数のみを指定します。簡潔にするために、ヘッダー内の情報の一部を切り捨てます (したがって、この例では、ヘッダーは 52 バイトではなく 14 バイトです)。おおよそ私がやっていること:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <bitset>
#include <vector>
#include <algorithm>

int main ()
{
    vector<pair<int,int>> header_vec;

    header_vec.push_back(make_pair(9882719,32)); // file length
    header_vec.push_back(make_pair(52,32)); // header length
    header_vec.push_back(make_pair(6,3)); // high release identifier
    header_vec.push_back(make_pair(4,5)); // high version identifier
    header_vec.push_back(make_pair(6,3)); // low release identifier
    header_vec.push_back(make_pair(4,5)); // low version identifier

    // file open timestamp
    header_vec.push_back(make_pair(9,4));  // month
    header_vec.push_back(make_pair(6,5));  // day
    header_vec.push_back(make_pair(19,5)); // hour
    header_vec.push_back(make_pair(47,6)); // min
    header_vec.push_back(make_pair(0,1));  // utc direction
    header_vec.push_back(make_pair(0,5));  // utc offset hours
    header_vec.push_back(make_pair(0,6));  // utc offset minutes

    ostringstream oss;

    // convert each integer to binary representation
    for ( auto i : header_vec )
    {
        for (unsigned int j(i.second-1); j != -1; --j)
        {
            oss << ((i.first &(1 << j)) ? 1 : 0);
        }
    }

    // copy oss
    string str = oss.str();

    // create bitset
    bitset<112> header_bits(string(str.c_str()));

    // write bitset to file
    ofstream output("header.out", ios::out | ios::binary );
    output.write( reinterpret_cast<char *>(&header_bits), 14);
    output.close();

    return 0;

}

現在、ビットが逆になっていることを除いて、ほとんどの場合、この方法は機能しているようです。fm で出力ファイルを見ると、次のようになると思います。

File: header.out    (0x0e bytes)
Byte: 0x0

00    00 96 cc 5f 00 00 00 34 c4 c4 93 4e f0 00           ..._...4...N...O

      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f      0123456789abcdef

実際に私がこれを見たとき:

File: header.out    (0x0e bytes)
Byte: 0x0

00    00 f0 4e 93 c4 c4 34 00 00 00 5f cc 96 00           @O...N...4..._..

      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f      0123456789abcdef

ビットセットを作成する前に str を逆にしようとしましたが、目的の出力も得られません。

なぜこれが起こっているのかを理解するには、ビットセットについて十分に理解していないと思います。あらゆるご意見をお待ちしております。また、これを達成するための別の方法がある場合は、共有してください!

よろしくお願いします... -J

4

2 に答える 2

1

bitset<>をメモリ ダンプとして直接書き込むと、確かに移植性がなくなりreinterpret_cast<>ます。つまり、データがナイス ブロックに配置されていても、それがどのように行われるかはわかりません。

もし私があなたなら、ビットセットから 8 ビットのチャンクを抽出し、通常のアクセス演算子 [] を使用してそれらをバイトとしてファイルに書き込むための愚かな関数を作成します。

別のアプローチとして、バイナリファイルを読み書きしたいときに通常行うことは、ファイルのレイアウトに直接マップする構造または構造のセットを定義することです。

例えば:

struct Timestamp
{
    int month:4;
    int day:5;
    int hour:5;
    int minute:6;
    int utcOffsetDirection:1;
    int utcOffsetHour:5;
    int utcOffsetMinute:5;

};
于 2012-09-07T04:50:37.557 に答える
1

なぜstruct bitfieldを使用しないので、「ビット解析」を行うことを心配せずに、構造体を読み書きするだけです。メモリの配置には注意してください。ボンダリーという単語に合うようにパディングを追加してください

struct timestamp{
       unsigned mont:4;
       unsigned day:5;
       unsigned hour:5;
       unsigned minute:6;
       unsigned utc:1;
       unsigned utc_hour:5;
       unsigned utc_min:6   
};


struct header{
   int32_t file_length;
   int32_t header_lenght;
   int16_t version;
   timestamp tmsp;
};
于 2012-09-07T04:55:33.413 に答える