今までターミナル画面上での入出力を扱ってきましたが、このページではファイル入出力を取り扱います。
ファイルを操作する手順は次の通りです。
C以外の言語でもファイル操作はだいたいこんな流れになります。
ファイルを開くにはfopen()関数を使用します
FILE* fopen(const char* ファイル名, const char* モード)
FILE*はファイルポインタと呼ばれるもので、ファイルを操作する時に使用するもので、ファイルを閉じるときまで使用します。この関数が失敗した場合、NULLが返されます。
「モード」はファイルを読み込みで開くのか、書き込みで開くのか、バイナリモードで開くのか、テキストモードで開くのかを設定します。
| モード | 説明 | 
|---|---|
| r | テキストモードで読み込み | 
| w | テキストモードで書き込み | 
| a | テキストモードで追加書き込み | 
| rb | バイナリモードで読み込み | 
| wb | バイナリモードで書き込み | 
| ab | バイナリモードで追加書き込み | 
| r+ | テキストモードで読み込み/書き込み | 
| w+ | テキストモードで書き込み/読み込み | 
| a+ | テキストモードで追加書き込み/読み込み | 
| rb+ | バイナリモードで読み込み/書き込み | 
| wb+ | バイナリモードで書き込み/読み込み | 
| ab+ | バイナリモードで追加書き込み/読み込み | 
テキストとバイナリの違いは人間が読める文字を扱うかどうかです。人間が読めるものを扱うときはテキストモード、数字データなど、人間が読めないものを扱う場合はバイナリモードにします。
読み込みモードでは、存在するファイルを開きます。ファイルが存在しなければ失敗します。書き込みモードではファイルの新規作成を行います。ファイルが既に存在する場合は新しいファイルで上書きされます。追加書き込みモードでは存在するファイルの末尾から追加書き込みができます。ファイルが存在しない場合は新規作成されます。
+記号のついた書き込み/読み込みモードは一見どれも同じように見えますが、r+はファイルが存在しないと失敗し、w+は空のファイルからのファイル操作となります。
一文字書き込みを行います。
int fputc(int 出力文字, FILE* ファイルポインタ)
出力文字はunsigned char型に変換されます。ファイルポインタはfopenで得られたものを使用します。
文字列書き込みを行います。
int fputs(const char* 出力文字列, FILE* ファイルポインタ)
フォーマットされた文字列を出力します。
int fprintf(FILE* ファイルポインタ, const char* フォーマット, ...)
size_t fwrite(const void* ポインタ, size_t 1アイテムのサイズ, size_t アイテム数, FILE* ファイルポインタ)
1アイテムのサイズ×アイテム数のバイト数を書き込みます。
一文字読み込みを行います。
int fgetc(FILE* ファイルポインタ)
読み込まれた文字は戻り値として渡されます。
文字列読み込みを行います。
char* fgets(char* 出力先文字列, size_t 読み込みサイズ, FILE* ファイルポインタ)
読み込みサイズ分か、あるいは改行するまで読み込みを行います。改行した場合は改行コードも読み込みを行います。
フォーマット読み込みを行います。自由度が高く、また、読み込みサイズ制限が無いため、使い方には注意が必要です。
int fscanf(FILE* ファイルポインタ, const char* フォーマット, ...)
size_t fread(const void* ポインタ, size_t 1アイテムのサイズ, size_t アイテム数, FILE* ファイルポインタ)
1アイテムのサイズ×アイテム数のバイト数を読み込みます。
書き込み、読み込みを終了したら、ファイルを閉じます。
int fclose(FILE* ファイルポインタ)
ファイルの読み込み/書き込みを行うと、ファイルポインタが自動的に移動しますが、特定のアドレスのデータを読み込みたい、特定のアドレスに書き込みたい場合、ファイルポインタを自分で動かす必要があります。ファイルポインタを移動させるにはfseek()関数を使用します。
int fseek(FILE* ファイルポインタ, long オフセット, int 基準位置)
基準位置からオフセット分移動させます。基準位置は次の3つから選びます。
| 位置 | 説明 | 
|---|---|
| SEEK_SET | ファイルの先頭 | 
| SEEK_CUR | 現在位置 | 
| SEEK_END | ファイルの最後 | 
成功すれば0が、失敗すれば-1が返ります。
/* メイン関数の引数をファイルに書き出すプログラム */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
        FILE *fp;
        int i;
        /* ファイルを開く */
        fp = fopen("text.txt","w"); 
        /* ファイルオープンに失敗した場合は終了する */
        if(fp == NULL){
                exit(1);
        }
        /* メイン関数の引数をファイルに出力する */
        for(i = 0; i < argc; i++){
                fprintf(fp,"%d : %s\n",i, argv[i]);
        }
        fclose(fp);
        return 0;
}
/* ファイルの内容を別のファイルにコピーするプログラム */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
        FILE *fin;     /* 入力用ファイルポインタ */
        FILE *fout;    /* 出力用ファイルポインタ */
        char c;
        /* ファイルを開く(入力用) */
        fin = fopen("text.txt","r"); 
        /* ファイルオープンに失敗した場合は終了する */
        if(fin == NULL){
                exit(1);
        }
        /* ファイルを開く(出力用) */
        fout = fopen("text2.txt","w"); 
        /* ファイルオープンに失敗した場合は終了する */
        if(fout == NULL){
                fclose(fin);
                exit(1);
        }
        /* ファイルに出力する */
        for(;;){
                c = fgetc(fin);
                /* ファイルを最後まで読み終えた時は終了する */
                if(c == EOF){
                        break;
                }
                fputc(c, fout);
        }
        fclose(fin);
        fclose(fout);
        return 0;
}
/* バイナリデータ1から100まで書き込むプログラム */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
        FILE *fp;
        int i;
        char c[100];
        /* ファイルを開く(出力用) */
        fp = fopen("test.dat","wb"); 
        /* ファイルオープンに失敗した場合は終了する */
        if(fp == NULL){
                exit(1);
        }
        /* データを配列に格納する */
        for(i = 1; i <= 100; i++){
                c[i - 1] = i;
        }
        /* 出力 */
        fwrite(c, 1, 100, fp);
        fclose(fp);
        return 0;
}