質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.58%

バイナリファイルの区切り文字(厳密には"どうやって複数のデータを表現するか")

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,972

BeatStar

score 1809

プログラミングにはあまり関係がありませんが... (タグは近いのが無いので...)

ゲームでインストーラ式のものがありますよね。

構成が

+ install.exe
+ setup.bin
+ readme.txt

のようになっているものです。

私のイメージではinstall.exe が setup.bin をバイナリモードで読み込み、
その生成しているイメージです。

例えば 区切り文字を '\S' ( separator ) とします。

[setup.bin]

struct
+ /data/
   + /image/
      + image1.src
      + image2.src
+ main.exe
+ readme.txt

main.exe
(ここにmain.exeのバイナリデータ)
\S

image1.src
(ここにimage1.srcのバイナリデータ)
\S

image2.src
(ここにimage2.srcのバイナリデータ)
\S

readme.txt
ゲーム名.exe\nこのゲームは...
\S

のような感じで、C言語でもなんでもいいですが、
言語のバイナリファイルを読み込むクラス,関数等で「1バイトずつ」読み込んで...

ってやっているのでしょうか?

それとも単純に、項目名(構成,それぞれのファイルのやつ) を"[]" でくくって、

[struct]
+ /data/
   + /image/
      + image1.src
      + image2.src
+ main.exe
+ readme.txt

のようにして、[struct] と 次の [] である [main.exe] までの位置を一つの文字列 (または1バイトずつ)
読み込んで書き込んでいるのでしょうか?

私はC++で組んでいますが、あまりバイナリファイルは扱っていません。
(最近扱い始めたばかりです。)

読み込み・書き込みはいいとして、使い方が単にテキストファイルのサイズが小さい版という感じです。
(本来は違うと思いますが...)

もし(表現自体はどうあれ)私がイメージした通りでしたら私の表現方法が広くなるかもしれないので...

私が使う言語はC++ ( better-C )ですが、言語自体に言及しないのであればどの言語でも構いません。

[情報]
基本的な言語: C++ ( and Qt )
頑張れば読めるかもしれない言語: Java, Python(?)
OS: Windows系 (XP,7,10) (表現がOSによって異なるかもしれないし...実行ファイルとかみたいに)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

checkベストアンサー

+7

バイナリファイルの構造は、作者が自由に決められます。ただし、データの中にどんなバイトも現れうるので、「特定のバイト」を区切り文字にするような方式はあまり使われません。

よくあるパターンとしては、

  • データ先頭部のヘッダにデータ自体の長さも入れてある
  • インデックスデータが最初に用意してあって、本体はそこからオフセットで参照される

などがあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/24 10:51

    ご回答ありがとうございます。
    やはり特定のバイトは区切り文字にしませんよね...
    私が悩んでいたのはそこでした。0 を区切り文字にしても 0 が(ファイルや"構造"等のような)データ上に現れる可能性もあるし、\S とかでもそうですし...

    データ先頭にデータ自体の長さを入れる...
    多分 514129 とあったら 長さ5 の "14129" っていうことですよね?
    でも、もう一方の"インデックスデータが最初に用意してあって..."がちょっとイメージできません。
    なんかイメージできそうな、質問でのsetup.binの内部みたいな感じで簡易的でもいいので、提示していただけませんか?

    キャンセル

+5

中身を覗かれても問題なければ、*.binと言いつつ実際にはzipファイル、などにしておけば圧縮ファイルの展開用コードを組み込むだけで済みます。

自分専用形式にしたいのであれば、まずはそういったファイルのフォーマットを調べてみるとか。

ZIP (ファイルフォーマット)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/24 11:00

    jarとかapkとかOOXMLとか、「特殊なデータ配置にしたZipファイル」形式のものもよく見かける気がします。

    キャンセル

  • 2018/10/24 12:36

    そうですね。ipaとかもですし、結構多いと思います。

    キャンセル

  • 2018/10/26 09:45

    ご回答ありがとうございます。
    なるほど。zipとかをまねて...ですか。
    ちょっと試してみます。

    キャンセル

+4

こんにちは。

どうもバイナリ・ファイルをうまくイメージできていないように見受けられます。
テキスト・ファイルは基本的に可読文字のみで構成されますが、バイナリ・ファイルには普通は全てのコードが入りますから、それをテキストとして表示すると文字化けしまくりです。

例えば、hello worldをビルドした exe をtype(後半略)すると、

> type hello.exe
MZ・         ク       @                                   ・   コ エ      ヘ!クLヘ!This program cannot be run in DOS mode.
$       PyJイ$・$・$・`キ・$・~'・$・~!・$・~ ・$・~%・$痣|%・$・%・$・!・$・ロ・$・&・$甞ich$・        

これを16進数でダンプ(後半略)すると、

00000000 4D 5A 90 00 03 00 00 00 04  00 00 00 FF FF 00 00
00000010 B8 00 00 00 00 00 00 00 40  00 00 00 00 00 00 00
00000020 00 00 00 00 00 00 00 00 00  00 00 00 00 00 00 00
00000030 00 00 00 00 00 00 00 00 00  00 00 00 F0 00 00 00
00000040 0E 1F BA 0E 00 B4 09 CD 21  B8 01 4C CD 21 54 68

このようにバイナリ・ファイルの中身をテキストとして表示すると文字化けしますので、文字列としてではなく、16進数等で表記することが多いです。
なお、型が明確なデータに関しては、その部分だけ10進数で表記したり、文字列で表記したりすることもあります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/28 10:28

    ご回答ありがとうございます。
    もうちょっと調べてみますね。

    キャンセル

+3

maisumakunさんの回答で良いと思いますが、
特定のバイトを区切り文字にするような方式はあまり使われないものの無いわけではないので補足しますと、
データ中に現れうる値を区切り文字に使う場合、データ中の当該の値を別のものに置き換える対処が一般的です。
例えばJPEGは0xFFを区切り文字に使いますが、データ中の0xFFは0xFF 0x00の2バイトに置き換えます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/28 10:29

    ご回答ありがとうございます。
    なるほど。置き換えでダブらないように工夫...ですか。

    キャンセル

+1

バイナリファイルはなんでもありです。
簡単には、

  struct hoge {
    int a;
    char b[100];
    short c;
    ....
  }
  struct hoge hoge1;
  struct hoge hoge2;

  ....
  FILE *fp1 = fopen("FileName1", "rb");
  FILE *fp2 = fopen("FileName2", "wb");

  ....
  fwrite((char *)&hoge1, sizeof(struct hoge), 1, fp1);
  ....
  fread((char *)&hoge2, sizeof(struct hoge), 1, fp2);
  ....

なんて使い方もありですね。
(hoge1 のデータをファイルに出力。hoge2 にファイルから読込み)

構造体だと、アライメントの問題とか言われますが、同じプログラムで読み書きする分には問題有りません。この方法で、内部データをファイルに保存する方法もありです。(メンテナンスが大変なので、お奨めではありませんが)

良くあるのが、

  int data1;
  fwrite(&data1, sizeof (int), 1, fp);


などとし、データを一つずつ、ファイルに出力し、読出しは、同じ順序で行うものです。(こちらもメンテナンス大変ですが、変更しないという前提ならば、簡単)

例にある install.exe がsetup.binを読み込む件は、install.exeがどうしているかなので、作った人に聞くしかないですが、daisuke7さんの書かれたように、zip形式で圧縮もありですね。頭に余分なヘッダを付けて、renameだけでは展開できないようにとか、拘るところもあるようですが。あるいは、専用の展開モジュールを付加するのもあるようです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/28 10:29

    ご回答ありがとうございます。
    なるほど。やはりzipとかで...でしょうか。

    キャンセル

0

皆様、ご協力ありがとうございました。
皆様の回答が素晴らしく、(どれをベストアンサーにすべきか)ものすごく迷いましたので
真っ先に回答してくださったmaisumakunさんをベストアンサーに選びたいと思います。
( できるなら皆様 全員にベストアンサーに選びたいところですが、機能的に... )

問題に関しましては、もうちょっと皆様のお考えをもとにして自分なりのものを考えてみようと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る