freopen
すべてをファイルにリダイレクトすることについて読みましprintf
たが、出力も画面に出力したいと思います。printfs をファイルにリダイレクトしてコマンドライン出力を取得する簡単な方法はありますか?
ありがとう!
もう1つの方法は、のように機能するprintf
が、出力を2つの異なる場所に送る関数を作成することです。例えば:
#include <stdio.h>
#include <stdarg.h>
void printf2(FILE *fp, char *format, ...)
{
va_list ap;
va_list ap2;
va_start(ap, format);
va_copy(ap2, ap);
vfprintf(fp, format, ap);
va_end(ap);
vprintf(format, ap2);
va_end(ap2);
}
次に、呼び出すprintf2
のと同じ方法で呼び出すことができfprintf
、出力は渡されたFILE
ポインタとstdoutの両方に送られます。
FILE *fp = fopen("/tmp/foo", "w");
printf2(fp, "This is a test.\n");
このアプローチはサブプロセスやパイプを使用せず、必要に応じて複数のファイルポインターに一般化できます。
freopen
stdoutをリダイレクトするのは良い考えではありません。必ずしも同じファイル記述子番号を再利用するわけではないため、子プロセスは新しいstdoutを継承しない可能性があります(またはstdoutがまったくなくなる可能性があります)。stdoutの新しいターゲットを使用open
してから、dup2
またはclose(0)
それから作成することをお勧めします。open
プログラムの外部からは、"tee" を使用します。
# echo foo | tee foo.txt
foo
# cat foo.txt
foo
実際、ファイルを書き込むティーにチャネルを popen() することもできますが、これはシステム負荷が高くなります。この趣旨の何か:
FILE *stream_to_write_to = popen( "tee filename.txt" );
fprintf( stream_to_write_to, "goes to filename.txt and stdout\n" );
あるレベルでは、これにはデータのコピーが含まれるため、これを行うC言語からの簡単な方法があるかどうかを知りたいです。dup() などを使用して 2 つのファイルハンドルを同じ場所に書き込むのは簡単ですが、その逆はよりトリッキーです。モジュールをプッシュする必要があるかもしれません (一般的な例は "connld" をストリームに) ですが、正直なところ、これが使用されているのを見たことがありません。
私が提供できる最良の参考文献は、Stevens による「UNIX 環境での高度なプログラミング」です。
アップデート:
以下のRのコメントについて言えば、上記の解決策は、子のハンドルを別の場所にフォーク/実行してリダイレクトするだけの、少し重いバージョンです。どちらも問題を解決しますが、クリーンアップが簡単なので上記の方が好みですが、正直なところ、どちらのソリューションもかなり重いです。Fork() は軽量関数ではありません。質問の精神が fork/exec なしで行うことである場合、私にはわかりません。私も知りたいです。fork/exec が問題ない場合は、それを直接使用するか、popen() を使用してハッキングします。