2013-03-01 41 views
1

可以說我在下面有這段代碼,我用它來運行一個簡單的命令,如ls,並假設輸出爲100行。當運行命令以及如何逐行捕獲輸出時,popen會經歷什麼時間間隔?

當我們在下面的代碼中做cout << buff時,輸出是逐字節地,逐位地或逐行地進行流傳輸還是逐行傳輸?

可以說我們要打印new_line!因爲我們正在流式傳輸,所以每一個新行的字符串結束cout<<buff。我們該怎麼做?

我想在這while循環中,我們應該有一些應該檢查,它只是流(或即將流)\n到我們的stringstream output,它決定之後(或之前)做一些它流進輸出。

最初,我只作爲數據結構它來存儲,所以我只需要知道如何檢查\n因爲我們bufferring並往哪裏放,增加了new_line!或任何我想做的功能。

下面的代碼:

#include <iostream> 
#include <stdio.h> 

using namespace std; 
// imaginary 
// stringstream output; 


int main() { 
    FILE *in; 
    char buff[512]; 

    if(!(in = popen("ls -sail", "r"))){ 
     return 1; 
    } 

    while(fgets(buff, sizeof(buff), in)!=NULL){ 
      // output << buff; 
      // if there is a new line 
      // output << "new_line!"; 

     cout << buff; 
    } 
    pclose(in); 

    return 0; 
} 

回答

1

如果使用GNU libc的,那麼你可以使用getline(),而不是fgets。有關更詳細的解釋,請參閱here

否則,請使用系統提供的任何設施讀取FILE*中的一行。如果你真的找不到這樣的設施(這將是非常令人驚訝的),那麼最糟糕的是,你總是可以使用this approachfgets也是一個很好的解決方案,只要你考慮緩衝區大小的限制,如果需要的話可以自己做更多的緩衝(檢查the doc,一切都被解釋了)。

你必須記住的事情是,popen只是返回FILE*所以任何可以在標準文件上工作的東西也適用於你的情況。網絡上有很多例子。


現在對於你的問題的「時間間隔」部分,恐怕沒有多大意義。首先,它取決於外部命令向標準輸出打印新數據的時間間隔。無論如何,只要外部命令寫入它,您就可以在程序中讀取它。

+0

謝謝,我不確定'getline()'是否可以工作,謝謝你的清除! – Logan 2013-03-01 22:59:53

1

就像fget與stdio。它會一直等到EOF(程序關閉)或緩衝區被填滿。

因此,while循環的每次迭代將獲得512字節的數據,或者程序終止或stdio關閉後的剩餘部分。

你可以用這樣的小程序測試:

#include <thread> 
#include <chrono> 
#include <iostream> 

int main() { 
    std::cout << "hello" << std::endl; 
    std::this_thread::sleep_for(std::chrono::seconds(5)); 
    std::cout << " world" << std::endl; 
} 

,你會不顧長時間休眠狀態它仍然會嘗試讀取512個字節和結束時的stdout做平倉通知。

要以符合標準的方式管理實際的分塊,您可以使用std::fgetc並構建自己的緩衝區。

http://en.cppreference.com/w/cpp/io/c/fgetc

你自己的函數getline可能是這樣的:

std::string get_line(FILE* f) { 
    char c; 
    std::string out; 
    while(c=std::fgetc(f)!='\n' && c!=EOF) { 
     out+=c; 
    } 
    out+='\n'; 
    return out; 
} 


//... 

//usage 
while(!std::feof(in)) { 
    cout << get_line(in); 
} 
+0

謝謝你的例子,它真的幫助:) – Logan 2013-03-01 23:12:42

1

管,因爲它涉及的(直到它到達一些實施限制,可能無法輕易找到將緩存中的數據 - 但它是「充足的」 - 在這個點上,當ls寫入它時,管道將「阻塞」,因此ls將停止),除非您更快地讀出它,在這種情況下,您的線程將被阻塞。如果您輸出到屏幕上,則很可能您的輸出會限制速度。

這樣的管道不是「塊狀」或「線路緩衝」的 - 它只是一根管道 - 任何一端放在另一端。當然,如果「文件管理」的內部請求4000字節,則在讀取操作完成之前可能需要等到4000字節通過另一端。但最有可能的是fgets的內部是理智的,不會一次要求大量的數據。