2010-07-09 148 views
0

我讀了freopen將所有printf重定向到一個文件,但我希望輸出也打印在屏幕上。有沒有簡單的方法將printfs重定向到文件並獲取cmd行輸出?輸出到文件和命令行

謝謝!

+0

這是轉發:http://stackoverflow.com/questions/418896/how-to-redirect-output-to-a-file-and-stdout – MasterHD 2013-10-09 00:23:10

+0

@MasterHD,你是對的。可能當時我沒有足夠的搜索。 – Framester 2013-10-09 08:01:22

回答

0

從程序外,使用「三通」:

# 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()或類似的東西,但相反更加棘手。它可能涉及推送一個模塊(常見的例子是「connld」到一個流),雖然老實說,我從來沒有見過這種模式,所以我很樂意看到自己的工作代碼示例。

我可以給出的最佳參考是史蒂文斯的「UNIX環境下的高級編程」。

更新:

要說話,下面的r評論,上述方案是隻叉/ EXEC-ING和重定向孩子的手柄別的地方一個稍重的版本。兩者都能解決問題,但我更喜歡上述內容,因爲清理起來更容易,但老實說,這兩種解決方案都相當重要。 Fork()不是輕量級的功能。如果問題的精神是沒有fork/exec的話,那麼我不確定,我也很想知道。如果fork/exec沒問題,那麼直接使用它或使用popen()會破解它。

+0

使用'popen'和fork你自己的模仿'tee'的子進程,並寫入舊的stdout和選定的文件。不要執行外部二進制文件;只需在自己的程序中實現「tee」功能即可。 – 2010-07-09 17:00:32

+0

@r:你也可以這樣做,但是你必須等待pid並清理它,而不是關閉流。我承認這是非常沉重的 - 叉/執行器也是如此。我認爲這個問題的精神在於沒有分叉複製數據,所以這對我來說不是一個完全令人滿意的答案。你有沒有機會知道流模塊?這是我之前沒有調查過的unix編程的一個蜘蛛網包圍的角落。 :-) – eruciform 2010-07-09 17:04:09

+1

Linux 2.6.17引入了tee(2)和splice(2),可以用來有效地實現tee(1)。 – ninjalj 2010-07-09 17:42:54

0

freopen不是重定向stdout的好主意。它不一定會重用相同的文件描述符號碼,所以子進程可能不會繼承新的stdout(或者可能最終沒有標準輸出)。最好使用open,然後使用dup2close(0),然後使用open爲標準輸出創建新的目標。

1

另一種替代方法是編寫一個類似於printf的函數,但將輸出指向兩個不同的位置。例如:

#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"); 

這種方法不使用子進程或管道,並且如果需要,它可以推廣到多個文件指針。

+0

+1:很好!我忘了這件事。是的,這可能是最簡單的。 – eruciform 2010-07-09 17:53:39

+0

嗨,謝謝你的回答,但最終我發現使用'tee'更容易。 – Framester 2010-08-18 16:03:11