UNIXプログラミング入門~ファイル編(1/2)~
c/c++でunix系osプログラミングを行うときに使うunistd.h
やその周辺のライブラリのお話です。
このメモでは、ファイルの入出力に関して取り上げます。
ファイルを開く-open関数-
通常c/c++でファイル操作を行うときはfopen
関数を利用しますが、今回はそれよりももっとシステムコールに近いopen
関数を利用します。
利用するにはfcntl.h
をインクルードします。
#include <fcntl.h>
open
関数のプロトタイプは以下のように宣言されています。
int open(const char* pathname, int flags[, int mode]);
第一引数pathname
には開く対象のファイルのパスを指定します。
絶対パスでも相対パスでも構いません。
第二引数flags
にはO_RDONLY
, O_RDWR
, O_WRONLY
などファイルをどのように利用するかを指定します。
それぞれfopen
関数の"r"
, "r+"
, "w"
に相当します。
O_RDONLY
ファイルを読み込み専用で開きます。
O_RDWR
ファイルを読み書き両方ができるように開きます。
O_WRONLY
ファイルを書き込み専用で開きます。
また上記に加え、O_APPEND
, O_CREAT
等をor
(|)で結合して指定することもできます。
O_APPEND
ファイルを開いてファイルポインタをファイルの最後に移動します。
ファイルに追記を行うときなどに利用します。
open("hoge/hoge", O_WRONLY | O_APPEND)
のように利用することが多いと思います。
O_CREAT
ファイルが存在していないとき新しくファイルを作成して開きます。
既にファイルが存在しているときは意味を持ちません。
open("hoge/hoge", O_WRONLY | O_CREAT)
のように利用することが多いと思います。
この場合は、第一引数で指定されたファイルを書き込み専用で開いて、ファイルが存在していなければ新しく作成して開きます。
O_TRUNC
ファイルが存在していればサイズを0にして開きます。
要は、上書きです。
open("hoge/hoge", O_WRONLY | O_CREAT | O_TRUNC)
のように利用することが多いと思います。
この場合は、第一引数で指定されたファイルを書き込み専用で開いて、ファイルが存在していなければ新しく作成し、存在していれば大きさを0にして開きます。
O_BINARY O_TEXT
それぞれ、バイナリモード、テキストモードでファイルを開きます。
バイナリモードとテキストモードでは、改行コード等の扱いが異なることがあります。
第三引数mode
は、 パーミッションの指定です。
基本的には指定しないことが多いと思います。
S_IRWXU
00700 ユーザー (ファイルの所有者) に読み込み、書き込み、 実行の許可がある。 S_IRUSR 00400 ユーザーに読み込みの許可がある。 S_IWUSR 00200 ユーザーに書き込みの許可がある。 S_IXUSR 00100 ユーザーに実行の許可がある。 S_IRWXG 00070 グループに読み込み、書き込み、実行の許可がある。 S_IRGRP 00040 グループに読み込みの許可がある。 S_IWGRP 00020 グループに書き込みの許可がある。 S_IXGRP 00010 グループに実行の許可がある。 S_IRWXO 00007 他人 (others) に読み込み、書き込み、実行の許可がある。 S_IROTH 00004 他人に読み込みの許可がある。 S_IWOTH 00002 他人に書き込みの許可がある。 S_IXOTH 00001 他人に実行の許可がある。
open
関数は、成功した場合には0
以上の整数が戻り値となります。
この時の戻り値はファイルディスクリプタ
と呼ばれ、開かれたファイルに対する操作はすべてこのファイルディスクリプタ
を指定して行います。
ファイルを閉じる-close関数-
ファイルを開いたら閉じなければなりません。fopen
で開いたファイルをfclose
で閉じるのと同様、open
で開いたファイルはclose
関数で閉じます。
利用するにはunistd.h
をインクルードします。
#include <unistd.h>
close
関数のプロトタイプは以下のように宣言されています。
int close(int fd);
引数には、open
関数で取得したファイルディスクリプタ(open
関数の戻り値)を渡します。
ファイルを閉じることに成功したら0
が、失敗した場合には-1
が返ってきます。
利用例
#include <fctrl.h>
#include <unistd.h>
#include <stdio.h>
int main(int argc, char const* argv[])
{
int fd;
if ((fd = open("hoge/hoge", O_RDONLY)) < 0) {
printf("ファイルを開けませんでした\n");
return -1;
}
/* 何かしらの処理*/
close(fd);
return 0;
}
まとめ
fcntl.h
とunistd.h
をインクルードopen()
を利用してファイルを開く- 使い終わったファイルは
close()
で閉じる - ファイルへの操作はファイルディスクリプタを指定して行う
次回は、read
、write
を行ってみようと思います。
つぶやき
ファイルを開くのとファイルを閉じるのでヘッダーファイルが別々になっているのにはなんか違和感を感じますが、何か理由があるんですかね?
知ってる人がいたら教えてください。