Index

HOME > プログラムTOP > C++



C++の壺・ファイル篇2

 C++の基本テクニックのTipsです。ファイル篇2では、オブジェクトを使ったファイルの読み込みと書き出しの方法を扱います。C言語のファイル入出力はファイル篇1で扱っています。
ページ項 目内 容
ファイル篇1 Cのファイル処理: FILE構造体、fopen関数、fclose関数
入出力関数: fgets関数、fputs関数、fprintf関数、fscanf関数
更新モード: rewind関数
バイナリモード: テキストモードとバイナリモード
ファイル篇2 C++のファイル処理: ifstreamクラス、ofstreamクラス、openメンバ、closeメンバ
入出力処理: putメンバ、getメンバ、is_openメンバ、getlineメンバ
モードフラグ: オープンモードフラグ
ファイル篇3 バイナリ・アクセス: fwriteとfread関数 / writeとreadメンバ
ランダム・アクセス: fseekとftell / fgetposとfsetpos / seekp,seekg,tellp,tellg
エラー/EOF検知: feofとferror関数 / perrorとclearerr関数 / iostateフラグ

sasaraan programming

Exposition

●C++のファイル処理

 C++では、C言語のファイル処理の他、オブジェクトを利用したファイル処理の方法が用意されています。書き出し用には ofstreamオブジェクト(クラス)、読み込み用には ifstream オブジェクト(クラス)が利用できます。それぞれ、宣言時には下記のようにコンストラクタを用います。なお、これらを使用するには、fstream.h のインクルードが必要です。(コンパイラによっては <fstream>)
ofstream class
・機能: ファイルへの出力
・コンストラクタ : ofstream: 既定のコンストラクタ
: ofstream(const char *file): ファイル名を指定
: ofstream(const char *file, int mode): ファイル名とモードフラグを指定
・要件: fstream.h のインクルード
ifstream class
・機能: ファイルからの入力
・コンストラクタ: ifstream: 既定のコンストラクタ
: ifstream(const char *file): ファイル名を指定
: ifstream(const char *file, int mode): ファイル名とモードフラグを指定
・要件: fstream.h のインクルード
 これらのオブジェクトを使用する時は、コンストラクタか open メンバ関数を使用してファイル名を指定します。使い終わったら、通常は close メンバを使ってファイルを閉じます。ただし、コンストラクタか open メンバを使って開いたファイルであれば、プログラム終了時にデストラクタが呼び出されて自動的に閉じられます。
open member
・書式void open(const char *file [ , int mode] )
・機能: 入出力ストリームを開く
・引数: file...ファイル名, mode...モードフラグ
・戻り値: なし
close member
・書式void close()
・機能: 入出力ストリームを閉じる
・引数: なし
・戻り値: なし
#include <fstream.h>
/* または、
    #include <fstream>
    using namespace std; */

void main()
{
    char fname[] = "sample.txt";
    ofstream stream(fname);  // 開く
    /* または、
        ofstream stream;
        stream.open(fname); */
    ...                     // 書き出し処理
    stream.close();  // 閉じる
}	
#include <fstream.h>
/* または、
    #include <fstream>
    using namespace std; */

void main()
{
    char fname[] = "sample.txt";
    ifstream stream(fname);  // 開く
    /* または、
        ifstream stream;
        stream.open(fname); */
    ...                     // 読み込み処理
    stream.close();  // 閉じる
}	

●入出力処理

 入出力オブジェクトに(クラス)では put (ofstream) と get (ifstream) の各入出力メンバが利用できます。いずれも、一文字分(通常は1バイト)の読み書きを行うための関数です。
put member
・書式stream& put(int c)
・機能: 出力ストリームに一文字出力
・引数: c...出力する文字
・戻り値: ストリームへの参照
get member
・書式stream& get(int& c)
・機能: 入力ストリームから一文字格納
・引数: c...参照する文字
・戻り値: ストリームへの参照
 また、is_open メンバ (ifstream / ofstream) を使うと、ストリームが開いているかどうかをチェックすることができます。ストリームを開いたら、is_openメンバをエラー処理に利用することで、より高い安全性を確保することができます。
is_open member
・書式bool is_open()
・機能: 入出力ストリームが開いているかを確認する
・引数: なし
・戻り値: 入出力ストリームが開いていればtrue(0以外)、開いていなければfalse(0)
// 入出力の例
#include <stdio.h>     // printf使用
#include <conio.h>    // getch使用
#include <fstream.h>
/* または #include <fstream>
     using namespace std; */

// main 関数
int main() 
{
    char fname[] = "sample.txt";
    char *s = "Hello World !\n";
	
    ofstream fout;   /* 出力ストリーム */
    fout.open(fname);  // 開く
    while (*s) {
        fout.put(*s++);  // 書き出し
    }
    fout.close();          // 閉じる

    ifstream fin;     /* 入力ストリーム */
    fin.open(fname);    // 開く
    char c;
    while (fin.get(c)) {  /* 読み込み */
        printf("%c", c);
    }
    fin.close();            // 閉じる

    if (getch()) return 0;
}  
// エラー処理の例

...

// main 関数
int main() 
{
    ... 
    ofstream fout;
    fout.open(fname);
    if (!fout.is_open()) { /* チェック!*/
        exit(1);             // エラー時は終了
    }
    while (*s) {
        fout.put(*s++);
    }
    fout.close();

    ifstream fin;
    fin.open(fname);
    if (!fin.is_open()) {  /* チェック! */
        exit(1);            // エラー時は終了
    }
    char c;
    while (fin.get(c)) {
        printf("%c", c);
    }
    fin.close();
    ...
} 
 上記サンプルは一文字づつ読み書きする例です。読み込みには getline メンバを利用することもできます。この関数は、ファイルの終端に達するか、n-1 文字分読み込むか、区切り文字に達するまで文字を読み込みます。文字列の最後には NULL 文字が付加されますが、区切り文字に達して読み込みが停止した時は、区切り文字は破棄されますので注意してください。
getline member
・書式stream& getline(char* str, int n, [char delim='\n'])
・機能: 文字列の読み込み
・引数: str...文字列へのポインタ, n...最大文字数, delim...区切り文字(省略時は '\n')
・戻り値: ストリームへの参照
 他にも、出力用には write関数や <<演算子、入力用には read関数、>>演算子などが利用でき、様々なパターンで入出力を行うことができます。

●モードフラグ

 オープンモードフラグを使ってファイルへのアクセスを制限することができます。これらのフラグは、演算子 " | " を使って、複数の指定をすることが可能です。
 オープンモードフラグは、コンストラクタまたは openメンバを使用する時に指定します。指定しない時(省略時)は次のように自動設定されます。
デフォルトの状態
ofstream → ios::out | ios::trunc
ifstream → ios::in
フラグ 機 能
ios::app: ファイルの終わりに移動。書き出し時、常にファイルの末尾に追加。
ios::ate: 開いた時にファイルの末尾に移動。
ios::in: ファイルからの読み込みを許可。
ios::out: ファイルへの書き出しを許可。
ios::trunc: 同名のファイルが存在する時は破棄。
ios::binary: バイナリモードで開く。(指定がなければテキストモード)
void main()
{
    char fname[] = "sample.txt";
    ofstream f;
    f.open(fname, ios::out | ios::app);
    ... 
    f.close();
}	
void main()
{
    char fname[] = "sample.txt";
    ifstream f;
    f.open(fname, ios::in | ios::binary);
    ...  
    f.close();
}	
 上記中、テキストモードとバイナリモードとの違いは改行コードの扱いにあります。ファイルの改行表現は cr (キャリッジリターン) + lf (ラインフィード) ですので、Cの改行表現である '\n' との整合性を持たせるために、テキストモードでは読み書き時にこれらの自動変換を行います。一方、バイナリモードでは変換を行いません。
・テキストモード '\n' ⇔ cr + lf の変換を行う
・バイナリモード '\n' をそのまま処理

*参考 : Cのアクセスモードとの比較
-CC++CC++
書き出し"w": ios::out | ios::trunc "w+": ios::in | ios::out | ios::trunc
読み込み"r": ios::in "r+": ios::in | ios::out
追加書き出し"a": ios::out | ios::app "a+": ios::in | ios::out | ios::app

www.sasaraan.net

(c) morijoh