#pragma twice

KAB-studio > プログラミング > #pragma twice > 232 Version 12.09 バイナリーモードで書き込む!

#pragma twice 232 Version 12.09 バイナリーモードで書き込む!

前のページへ 表紙・目次へ 次のページへ

 Version 12.09
バイナリーモードで書き込む!

前回は、改行文字とバイナリーモードについて説明しました
バイナリーモードだと \r\n がそのまま来るんだよね
でも、バイナリーモードの本当の目的は、文字列以外のデータを読み書き
すること
そういえばそう言ってたよね、文字列以外の時に、 0x0D が消えちゃった
らまずいから、って
そう、そのためのバイナリーモード。というわけで試してみます。まずは
簡単に、 int のデータひとつを書き込みます

void WriteBinaryFile()
{
    // ファイルを開きます。
    FILE *pstFile
        = fopen( "Binary.aaa", "wb" );
    if( !pstFile )
    {
        TRACE( "ファイルが開けない!\n" );
        return;
    }

    // 0x0000ABCD を書き込みます。
    int i = 0x0000ABCD;
    fwrite( &i, sizeof( i ), 1, pstFile );

    // ファイルを閉じます。
    fclose( pstFile );
    return;
}

フツーのランタイム使ったのだね
でも fwrite() は初めてだと思うよ
あ、ホントだ
 fwrite() は、バイナリーデータを書き込むランタイム。引数をひとつず
つ見ていこうか

    fwrite
        ( &i
        , sizeof( i )
        , 1
        , pstFile 
        );

第1引数の &i は、書き込むデータのアドレス
アドレスなんだ
そう。 fwrite() は〈メモリ上のデータを何バイト書き込むか〉っていう
ランタイムだから、書き込むデータがあるアドレスを渡します
データそのものじゃないんだね
第2引数の sizeof( i ) は、データのサイズ
 sizeof でサイズそのまま渡してるわけね
そう。ここで 4 が返るから、第1引数で指定したアドレスから 4 バイト
分を書き込む、ってなります
そか、書き込むデータのサイズ、って単純に考えない方がいいんだ
それはそれでいいと思うよ。場合によるっていうか……

第3引数と一緒に考えた方がいいかも。第3引数は、データが何個並んで
いるか

たとえば i が int の配列だった場合
あ、そのときにはその数だけ第3引数に渡すんだ
そういうこと。でも、これは第2引数との関係によるかな。第2引数は
データ全体のサイズって考え方もあるから、第2引数で配列全体を渡すこと
もできます
そういう場合、第3引数は?
もう全体のサイズを渡してるから、 1 
んー、第2引数と第3引数を掛けたら全体のサイズになればいいんじゃな
いの?
結局はそういうことになるね。この辺は場合場合によるかも。第1引数で
文字列を書き込むんなら、第2引数は sizeof( char ) 、第3引数は
文字数?
っていうのが自然かな
その方がわかりやすそうだね
と、話を戻して、第4引数はファイルポインタ
いつものだね。これだけで書き込めるんだ
で、書き込んだデータは Binary.aaa に書き込まれたから、このファイル
をバイナリーモードで開いて確認してみます
何その aaa って拡張子
これは好きなようにしていいよ。バイナリーファイルの場合、そのアプリ
専用の拡張子を付けることが多いから。他では使わないからね
そういえばそういうファイル結構あるね
今回も、 VC のバイナリーエディタで開くだけだから、関連づけとか関係
ないから
あ、そうだ、開かなきゃ。ん、こんななってたよ

000000  CD AB 00 00

おー、 0x0000ABCD だから……って、逆……あ、バイトオーダー!
そういうこと。実際には int の中では逆順に並んでいるから、それをそ
のまま書き込むと
ファイルの中でも逆になっちゃうってわけね
バイトオーダーは、大まかにはOSごとに違うものだから、ウィンドウズ
でファイルを作ってウィンドウズで開くなら問題なし
でも、他のOSで作ったら……って、ウィンドウズ用のアプリなら他じゃ
動かないでしょ
それは確かに言えるんだけど、そのファイルをいろんなアプリで共有する
ようになったら問題になるでしょ。たとえば音楽ファイルとか画像ファイル
とか
 mp3 とか avi とかってこと? そか、いろんなOSで共通のファイルだ
と、バイトオーダーが違ったら読み込めなくなっちゃうんだ
だから、そういう一般に公開されたファイルは、仕様のところにちゃんと
バイトオーダーとか書いてあるから
普通はどっちなの?
特に決まってないかも。ちゃんとした組織が作ってないときには、作った
人が勝手に決めちゃうこともあるし
何も考えずに作ったら広まっちゃった、って感じね
ウィンドウズは逆順の【リトルエンディアン】だけど、これが特別とも言
い切れないし。それともうひとつ、サイズの問題もあります
サイズ?
普通に int で書き込む場合、 int も環境によって違うから
これもOSが変わると駄目なんだ
そういうことを考えて、バイナリーとしては書き込まないっていう方法も
あります
バイナリーでは書き込まない?
そう、文字列として書き込むってこと

void WriteTextFile()
{
    // ファイルを開きます。
    FILE *pstFile
        = fopen( "Text.txt", "w" );
    if( !pstFile )
    {
        TRACE( "ファイルが開けない!\n" );
        return;
    }

    // 0x0000ABCD を書き込みます。
    int i = 0x0000ABCD;
    fprintf( pstFile, "0x%08X", i );

    // ファイルを閉じます。
    fclose( pstFile );
    return;
}

さっきと…… fwrite() の代わりに fprintf() 使ってる
 fprintf() は sprintf() のファイル版
うん、使い方一緒っぽい
で、このデータを書き込んだ Text.txt を開いて
バイナリーで?
ううん、テキストモードで、というか普通にエディタで
ほい。あ

0x0000ABCD

って普通に書かれてた
そういうこと。テキストとして普通に書き込めばバイトオーダーは関係な
いから
OSが変わっても大丈夫……文字コードは?
文字列を書き込むときは、テキストもバイナリーもどっちも文字コードは
考えなきゃいけないから同じ
改行のは?
それは重要かもね。その前に、このデータをどう書き込むかっていうのも
あるし
どう書き込むか?
書き込むデータがいっぱいあった場合、1行1データにするかとか
それはわかりやすいね
そのほかには、【,】(カンマ)で区切る【CSV】(シーエスブイ)形式と

それってよく見るね
あと最近だと XML とか
それもよく聞くけど、よくわかんない……
その辺はちょっと上級になるからとりあえずいいかな。そういうふうに、
文字列として書く場合にはどういうふうに各データを区切るかが重要かも
え? それってバイナリーでも同じでしょ?
 int ……は固定じゃないにしても、 short とか long とか、 float と
か double とかは、サイズが固定だから
そか、そのサイズで見ればいいだけなんだ。でも文字列だと……桁が大き
くなったり小さくなったり
そういうこと。 0 を入れたりして固定長にすると、大きな数はデータ的
に常に大きくなっちゃうし
それは無駄だね
そういうこともあって、どう区切るかが重要かな。まぁプログラム次第か

……質問!
はい火美ちゃん
テキストにするかバイナリーにするかって、どう決めるのがいいの?
明確な決め方はないけど……まず、圧縮とかが必要な音声・画像は
バイナリーね
テキストじゃしようがないからね。次に、フォーマットを公開した方がい
いデータなら、テキストの方がいいかな
公開っていうと?
そのファイルを使うアプリを作ってください、みたいにする場合
自分以外の人が作る場合ってことね
テキストならテストデータも作りやすいし、使う側も修正しやすいしね
それ考えると、自分で作るときにもテキストの方が良さそうだね
ただ、逆に修正が掛けにくいっていうのは、バイナリーのメリットかも
修正が掛けにくい?
ユーザーが勝手にデータを修正して、それを読み込んだらうまく動かな
い、とか
……それってこっちのせいじゃないじゃん
それはそうなんだけど、クレームの数は少ないに越したことはないから
それはそうだけど……
ま、そうは言ってもテキストの方が色々な面で楽かな
やっぱそうなるよねー
でももう少しだけ、バイナリーでの読み書きについて見ていきます


/*
    Preview Next Story!
*/
難しくはないんだけど、バイナリーってなんか抵抗あるかも
難しいって感じちゃうのはそれが原因かもね
これも慣れれば大丈夫?
いろんなランタイム使っていけば大丈夫になると思うよ
やっぱそれしかないよね
というわけで次回
< Version 12.10 複数のバイナリーデータの読み書き >
につづく!
ちなみに僕もあまり慣れてないから
え”
結局あんまり使わないんだよね、バイナリーモード……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。