注意 : このエントリの内容は今では使ってる人いるの?と思われる Borland C++ Compiler 5.5.1 for Win32 で確認しており、現在の MS のコンパイラで正しいかどうか確認していません。
Windows の C 言語環境でファイル入出力を扱う場合、複数の方法があり混乱しやすいので整理してみました。
ここでは明確に区別するため用語を定義
ファイル記述子 | ファイル記述子、ファイルディスクリプタと呼ばれる int 値。UNIX でも使われる物に相当。 |
ファイルポインタ | C 言語構造体 FILE のポインタ。fopen 関数でファイルを開いたりして取得するやつ。 |
ファイルハンドル | Windows OS 特有のハンドル。CreateFile 関数で取得したりするやつ。 |
まず最初にファイル記述子。これは UNIX でストリームを扱う際に OS により与えられる整数値。ファイルだけでなくストリーム全般を扱い低水準であるため扱いが色々面倒である部分もある。また、この概念は UNIX でない OS では無い場合もあるので移植性は基本的に無い。
ファイルポインタは C 言語標準で C 言語が使える環境なら常に使えるようになっている筈で、前述のファイル記述子は移植性に問題があったが、こちらでは移植性が高く、便利な関数がそろってたりするので扱い易い。C 言語を勉強するときは最初にコレを勉強すると思う。自分も最初はコレだった。
ファイルハンドルは Windows OS 特有のハンドルで管理される。Windows 上で上記二つを扱う場合でも内部的に最終的にはこちらを経由して扱うことになる(筈だよね?)。こちらでファイルアクセスする場合は、とにかく面倒臭い。Win32API の関数がやたら引数と引数に指定するパラメータが多いのでいちいちリファレンスを見ないと扱えない。その代わり細かい制御をしたい場合はこちらでないと出来ないことが多い。
ということでこの三つ、色々と表にまとめてみた。
種別 | ファイルポインタ | ファイル記述子 | ファイルハンドル |
型 | FILE* | int | HANDLE |
ファイル開く | fopen | _open | CreateFile |
読む | fread 等 | _read | ReadFile |
書く | fwrite 等 | _write | WriteFile |
注意点として、ファイル記述子を使う関数は最初にアンダースコアがつくこと。アンダースコアがつかない read と write も Windows には存在していてそちらは windows socket 用の関数でありファイルでは使えないこと。この辺混乱しやすい。
それから自分的に一番重要だったこれらの変換方法。それらのまとめ。
stdio.h | io.h | ||||||||
ファイルポインタ | → | _fileno | → | ファイル記述子 | → | _get_osfhandle | → | ファイルハンドル | |
ファイルポインタ | ← | _fdopen | ← | ファイル記述子 | ← | _open_osfhandle | ← | ファイルハンドル |
自分の場合、単純にファイルを開くのではなく、既に開いているパイプだったり、変な方法で開いたファイルだったり色々あってファイルハンドルで取得する場合があったりするのだが、Win32APIのファイル入出力関数がやたら面倒臭いので、手慣れたファイルポインタを使う方法を使いたかったのだが、以前やったのをド忘れしてちょっと思い出すのに苦労したのでここに記録することに。