C ファイル入出力

提供:yonewiki

C++へ戻る


本来の表記は「C ファイル入出力」です。この記事に付けられた題名はテンプレート:記事名の制約から不正確なものとなっています。

※このページではC言語にも存在していたという意味で記事タイトルがC -> ファイル入出力になっていますが、
C++でも同様です。C++だけの機能がある場合は明記します。

ファイル入出力

 ファイルに文字を読み込んだり書き込んだりする命令です。標準入出力でコンソールに文字を表示させたり、文字入力から値を読み取ったりできましたが、ファイルには全て文字として書き込みます。そして値の読み込みも文字ですが、文字の中でも数字だけで構成されている部分を数値として認識したりするのはプログラム側で工夫することになっています。ファイルの概念があるOSなら使えるようになっているはずの命令です。ファイルのパス名や特定パス名が特別なモノを意味していることもあります。そのあたりはOS独自のものとして、特別に準備がされています。


 基本的な入出力のやりかたは、他のウェブページでも紹介されているので、ここでは、まずワイド文字列の出力について触れておきます。


 ファイル出力用の命令はいくつかありますが、英文字の1バイト文字の範囲であればfprintfが便利です。printfの機能をそのまま、ファイル出力に使えて、変数の出力形式が豊富に設定できるのも良いところです。printfと違って引数が3つの区分になっているのが大きな違いです。ひとつ増えたのはファイルポインタという引数です。このポインタがファイル出力の操作を制御します。通常はなんらかのファイルオープン命令の後からファイルの出力開始位置をさししめしています。


 ファイルオープン命令は以下のようなものです。

FILE* pFILE_file;
pFILE_file = open("C:\Directory\fileName.txt", "w");


 上記のようなものです。このようにしたとき変数 pFILE_file をファイルポインタと称しています。open関数は第一引数にパス名を持ちます。日本語のような2バイト文字を含む場合はリテラル(ダブルクォーテンションで挟んだパス名の部分のような文字列)の先頭に、大文字のLをつけます。

FILE* pFILE_file;
pFILE_file = _wopen(L"C:\ディレクトリ\ファイル名.txt", L"w");


 このような文字列の使い方は文字列操作や日本語文字列の記事で触れています。記事の内容に従えば、もちろん _T も使えます。このように日本語ような2バイト文字を扱うときは、wchar_t型やL""といった決まりを常に意識する必要があります。それがファイル入出力であっても同じだということです。日本語を扱っていても日本語2バイトを意識しないでも大丈夫な命令もちょくちょく出てくるので忘れやすいのかもしれません。例えばファイルを使い終わったらファイルを閉じる必要があります。その命令が以下です。


close(pFILE_file);


 というように日本語を意識することなく閉じるときは、まったくに2バイト文字を意識する必要のない引数だけなので、1バイト文字だけのときと全く同じになります。気を付けてください。ちなみにファイルポインタと呼んでいるpFILE_fileという文字は自分で勝手に名付けたものなので、自由な変数名を付けることができます。変数の名称の制約に違反していない範囲です。


 ここで変数名の先頭にpをつけている理由とかは違う記事で説明しました。大変ですが、記事をイチカラ読み直すと良いでしょう。名前は一度決めたら全部同じにしておく必要があります。毎回違う名前の変数でオープンしたり、クローズしたりするのはファイルポインタがことなっていて一貫性のないことになってしまいます。もちろん入出力を行うときも同じ名前の変数名を使うことになります。ことなる一連のオープンクローズ処理グループであれば違う名前のファイルポインタ名を使うことは問題になりません。


 ファイルオープンのオープン関数の第二引数に使える "w" のようなものはファイルの扱いを決める記号みたいな役割です。 w は新規作成書き込みという意味です。ファイルが既に存在していても、上書きして新規作成します。もとにあったファイルは消えてしまいます。すでにあるファイルに対しての操作に注意が必要です。広く配布する場合には、ファイルを消すことになるけど大丈夫か?ユーザーに再確認するくらいの形式になっている必要があります。たまたまそこにユーザが大事にしているファイルがあったとしたら大問題に発展します。 r は読み取り専用 aは追記。のように意味がつけられています。詳しくは以下の通りです。


 そして、いよいよ本題ですが、UTF16の2バイト文字を書き込むときは fwprintf という関数を使います。たとえば、pwcStringArr という文字列配列に"テスト文字列"\0 のような設定がしてある場合以下のような命令文になります。2バイト文字といっていますが、ShiftJISは1バイト文字扱いで出力して問題ない形式です。1バイトづつ読み込んである特定の1バイトがあると次に2バイト目とあわせて日本語を書き出す仕組みです。

pwcStringArr[7] : L'テ', L'ス', L'ト', L'文', L'字', L'列', '\0'


fwprintf(pFILE_file, L"文字列 = %ls", pwcStringArr);


 いわゆるフォーマット指定子が珍しいものに感じる人もいるでしょう。%lsと指定した部分がフォーマット指定子というものです。この指定で2バイト文字が出力できます。あとは、書き出す文字コードがなにかです。ここはファイルオープンされたときのコードに変換するように書き出されます。以下のようにするとUTF-8で書き出されます。UTF-16はサロゲートペアのような大きなコードが割り当てられている特殊な範囲でなければ、一文字が常に2バイトになります。1バイト文字の範囲の文字も2バイトです。UTF-8は1バイト文字は1バイトのまま、サロゲートペアでない範囲の特定の2バイト文字は3バイトになります。


FILE* pFILE_file;
pFILE_file = _wopen(L"C:\ディレクトリ\ファイル名.txt", L"w, ccs=UTF-8");


 テキストファイルで、UTF-16を使うことは滅多にありません。


記号 意味 説明
r 読み込み ファイルを読み込み専用で開く
w 書き込み 新規作成で書き込みできる状態で開く
a 追記 末尾 ファイルが既にある場合は末尾から追記。ファイルが無い場合は作成。
r+ 読み込み、書き込み ファイルは存在していないと駄目
w+ 追記 末尾 ファイルが無い場合は作成。wと違いは無い?
a+ 読み込み、追記 EOFマーカ削除。書き込み後もEOFマーカ復元されない。


 修飾記号のテキスト、バイナリモード


記号 意味 説明
t テキストモードで開く テキスト改行復帰コードへの変換が行われる
b バイナリモードで開く テキスト改行復帰コードへの変換が行われない

 単一行フィード (LF) 文字に変換され、LF 文字は出力時に CRLF の組み合わせに変換されます。


 修飾記号のオプション


記号 意味 説明
x すでにファイルがある場合は失敗 wと組み合わせるモノ
c コミットフラグを有効 fflushが呼び出されたらファイルバッファーの内容を適用
n コミットフラグをリセット コミットなしで開く。
N ファイルが子プロセスで継承されないようにする。 fflushが呼び出されたらファイルバッファーの内容を適用
S シーケンシャル最適化 キャッシュシーケンシャルアクセスに最適化
R ランダムアクセス最適化 キャッシュのランダムアクセスに最適化
T ファイルを一時ファイルに指定 ファイルがディスクにフラッシュされない。
D ファイルを一時ファイルに指定 最後のファイルポインタ―が閉じられるとファイルは削除される。
, ccs=encoding 文字セット encodingに UTF-8、UTF-16LE、UNICODEのいずれかを適用する。