fprintf は便利っちゃ便利ですが物足りない部分もあります。
なぜならファイル記述子( file descriptor )の方が便利なことが多いからです。
fprintf はあくまでもファイルストリームの指定なので、ファイル記述子をそのまま使うなら dprintf が良いです。
#include <stdio.h> int dprintf(int fd, const char *format, ...);
この関数は第一引数にファイル記述子、後はフォーマット文字列、入力変数を指定します。
printf にファイル記述子がついてるぐらいのもんです。
後はファイル記述子は exec コマンドを使って取得するより open 関数を使ったほうが良いです。
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);
open 関数には flags と mode という引数がありますね。
flags は一般的に設定に使えるフラグパラメーターです。
mode はファイルアクセス権限の設定に使えるフラグです。
以下はヘッダーファイルから得られる mode の一覧です。
表19.1 mode
定数 | 8進数値 | 権限 |
---|---|---|
S_ISUID | 04000 | ユーザーID設定 |
S_ISGID | 02000 | グループID設定 |
S_ISVTX | 01000 | スティッキー |
S_IRUSR | 0400 | ユーザー読み込み |
S_IWUSR | 0200 | ユーザー書き込み |
S_IXUSR | 0100 | ユーザー実行 |
S_IRGRP | 040 | グループ読み込み |
S_IWGRP | 020 | グループ書き込み |
S_IXGRP | 010 | グループ実行 |
S_IROTH | 04 | その他の(グループ以外の全ユーザの)読み込み |
S_IWOTH | 02 | その他の(グループ以外の全ユーザの)書き込み |
S_IXOTH | 01 | その他の(グループ以外の全ユーザの)実行 |
ここらへんは Unix 系の教科書、参考書の権限設定を見ておくと参考になるかもしれませんね。
それとファイル記述子が開いたままだと、支障が出るので、閉じるには close 関数を使います。
#include <unistd.h> int close(int fd);
dprintf を使いこなすための関数は大体こんなもんですかね。
では実装例でも見てみましょう。
main.c.
1 #include <stdio.h> 2 #include <fcntl.h> 3 #include <stdlib.h> 4 #include <unistd.h> 5 6 int main(int argc, char **argv) 7 { 8 int fd; 9 10 if(argc != 2) { 11 fprintf(stderr,"ファイル名を指定してください\n"); 12 exit(1); 13 } 14 fd = open(argv[1],O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); 15 if(fd < 0) { 16 fprintf(stderr,"ファイル記述子を開けませんでした\n"); 17 exit(1); 18 } 19 dprintf(fd,"HELLO %s!\n",argv[1]); 20 close(fd); 21 return 0; 22 }
このコードでは open 関数をフルに使ってるん、そこが理解するときにネックになると思いますが、まずは見ないようにして動かしてみましょう。
$ gcc main.c $ ./a.out abc.txt $ cat abc.txt HELLO abc.txt!
このビルドしたプログラムのやっていることをリストにしますね。
では解説してきますね。
14 fd = open(argv[1],O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR); 15 if(fd < 0) { 16 fprintf(stderr,"ファイル記述子を開けませんでした\n"); 17 exit(1); 18 }
open 関数は第一引数がファイル名、第二引数が flags です。新規ファイル作成(または上書き)、読み書き両用、既存のデータがある場合はサイズ 0 に切り捨て(truncation)します。
最後の fd 変数のチェックですが、ファイル記述子は取得に成功すると 0 以上の整数値、失敗すると -1 が返ってくるので、失敗した場合は即プログラムを終了します。
19 dprintf(fd,"HELLO %s!\n",argv[1]); 20 close(fd);
dprintf の第一引数はファイル記述子、第二引数はフォーマット文字列、第三引数以降は変数リストです。
「HELLO ファイル名!」というようにファイル記述子に出力します。
後はファイル記述子を閉じてプログラムを終了します。
最後にファイルの中身の確認は cat コマンドを使います。
$ cat abc.txt HELLO abc.txt!
このようにファイル名の情報が abc.txt に更新されてます。
Copyright 2018-2019, by Masaki Komatsu