●ファイルの入出力 その0

サンプルプログラムは,サンプルファイル bat.mid をバイナリデータ
のファイルとして読み込んで表示している例です。

 ●バイナリファイルとは?

  ファイルの中身にはどんな種類のデータも記録できますが,
  その内容(用途)によって2種類に分かれます。

   1.テキストファイル
      人間が読める文字データが詰まったファイル。
      改行を表す特殊な文字(改行文字)によって
      行単位に分かれている。1行当たりの文字数
      は行によって違って良い。

   2.バイナリファイル
      人間の読めないデータばかり入ったファイル。
      画像や音声データ,圧縮されたデータ,MIDI
      ファイルなどがこれにあたる。

添付したファイルは,C言語の機能だけを使ってファイルをバイ
ナリデータとして1バイトずつ読み込んで表示するものです。

使用している関数など(「Cリファレンスマニュアル第5版」P.P.388-445)。

 「Cリファレンスマニュアル第5版」の参照箇所
 ・fopne(), fclose() → 15.2節
 ・frintf() → 15.11節
 ・fread() → 15.13節
 ・feof() → 15.14節

その他,ポインタについて概要を知っておく必要があります。

また

 ・size_t 型
   0以上を表す大きい整数型。たいてい unsigned long と同じ型。

 ・exit()関数 → 16.5節
   プログラムを自発的に終了する関数。返値は
    整数値0  :正常終了
    0以外の整数:異常終了
   としてオペレーティングシステムに通知されます。
   (exit()が返す値の意味は,main()関数のreturnで返す値と同じ。)

・perror()関数
   エラーメッセージを表示する専用関数。この関数に文字列
   を渡すと,エラーメッセージ専用の出力先(標準エラー出力)に
   内容が表示される。何もしなければ,標準エラー出力は
   通常の出力先と同じコマンドプロンプト・ウィンドウになる。

・errno
   C言語の標準ライブラリで用意されているint型のグロー
   バル変数。C言語標準ライブラリ関数のいくつかは,
   エラーが起こるとそのエラーの種類を表す値をこの
   変数にセットする。
   
を知っておくと良いでしょう。

※実際に,VisualStudio 2008 で実行してみて下さい。

※サンプルとして使用しているMIDIファイル "bat.mid"は, vgmusic.com から拝借した FF7の
 戦闘シーンのBGMです。再生してみて下さい。WindowsやMacOSではダブルクリックで再生できるはずです。
※バイナリエディタ(例えば http://www.vector.co.jp/soft/win95/util/se161737.html )
 で中身をみて,このプログラムで表示される内容と
 比較してみて下さい。同じ内容が表示されているはずです。
※「バイナリエディタ」とは,ファイルの中身のデータをバイナリデータとして読み書きするソフトで,
 たいてい16進数で中身を表示します。



main00.cpp

/* ファイルをバイナリデータとして読み込むサンプル */
/* ファイル "bat.mid" を読み込み、1バイトずつ16進数で表示する(1行で16バイトずつ表示)。 */
 
// Microsoftは、C言語標準の関数のいくつかを安全でないと考えており、警告を出す。次行の指定をするとその警告を出さなくなる。
#define _CRT_SECURE_NO_WARNINGS
 
// これ以降は、C言語の標準ライブラリだけを使用し、Windows API や DXライブラリ は使用していない。
#include <stdlib.h> // exit()関数を利用するため
#include <stdio.h>  // ファイル入出力を含め、入出力一般の機能を利用するときには stdio.h をインクルードする
 
// ポイント:stdio.h の中で、FILEという構造体型が宣言されている。ファイル1個につき、FILE型構造体1個を使ってファイルの入出力を管理する。
 
int main( void ) {
    
    FILE * fp1 = NULL;      // FILE型構造体へのポインタ値を格納するポインタ型変数fp1を宣言する。
    unsigned char buff[16]; // ファイルから読み込む16バイト分を格納する配列
    size_t readn = 0;       // size_t型整数(たいていは unsigned long と同じ型)の変数readn
    size_t i;               // 繰り返し用の変数
    
    // fopen()関数を使って、ファイル"bat.mid"を、読み込みオンリーモード("r")で開く。
    // オープンが成功するとfopen()関数はそのファイルを管理するFILE構造体へのポインタ値を返す。
    // オープンに失敗すると、fopen()関数は空ポインタ(NULL)を返し、C言語の標準ライブラリに用意されている変数errnoにエラーコードを返す。
    fp1 = fopen( "bat.mid", "r" ); 
    if( NULL == fp1 ) {
        perror( "ファイルオープンに失敗しました。" );
        exit( errno );
    }
 
    // fread()関数を使ってファイルを16バイトずつ読み込んで表示する。
    // fread()関数でfp1で管理しているファイルから、配列buffに、1バイト分を16個だけ読み込む。(つまり第3引数が「個数」)
    // fread()関数は、読み込んだ個数を返す。下の使用例では1バイトを16個読めたら、16を返す。
    // もしエラーが起こったり、ちょうどファイルの終端まで達して1個も読み込めなかった場合は0を返す。
    // fread()の実行中に本当にエラーが起こっているかどうかは、下例のように feof() 関数で判別できる。
 
    while( readn = fread( buff, 1, 16, fp1 ) ) { // readnに代入された読み込み「個数」が0でない間繰り返す。
        for( i = 0; i < readn; i++ ) printf( "%02X ", buff[i] );
        printf( "\n" );
    }
 
    if( feof( fp1 ) ) { // 本当にファイルの終端に達した状態には、feof()関数(end of file関数)は真の値を返す。
        printf( "-ファイルの終端(EOF: End Of File)-\n" );
    }
    else { // feof()関数が真でない場合、なんらかの読み込みエラーが起こったことになる。
        perror( "ファイルの読み込み中にエラーが起きました。" );
    }
 
    // もう使用しないファイルについては必ず fclose()関数で閉じる(クローズ)する事!
    // オペレーティングシステムによっては同時に開けるファイル数に制限があるため。
    // また、ファイルをクローズすることによって、ファイルの読み書きに利用される補助的な
    // メモリ領域などが解放されるので、プログラムの動作環境が健全に保たれる。
    fclose( fp1 );
 
    // コマンドプロンプトウインドウがいきなり終了しないための getchar() 呼び出し。
    getchar();
    getchar();
 
    return 0;
}