2011-10-18 123 views
11

我正在編寫一個C++應用程序,我需要讀取系統命令的結果。在C++中讀取popen結果

我使用popen()或多或少如下所示:

const int MAX_BUFFER = 2048; 
    string cmd="ls -l"; 
    char buffer[MAX_BUFFER]; 
    FILE *stream = popen(cmd.c_str(), "r"); 
    if (stream){ 
     while (!feof(stream)) 
     { 
      if (fgets(buffer, MAX_BUFFER, stream) != NULL) 
      { 
       //here is all my code 
      } 
     } 
     pclose(stream); 
    } 

我一直在試圖用不同的方式來重新寫這個。我看到一些非標準的解決方案,如:

FILE *myfile; 
std::fstream fileStream(myfile); 
std::string mystring; 
while(std::getline(myfile,mystring)) 
{ 
    // .... Here I do what I need 
} 

雖然我的編譯器不接受這個。

如何在C++中使用popen

+0

什麼是'我所有的代碼'?如果你的第一個解決方案是'data.append(buffer);',那麼它的工作是完美的。 – Beta

+1

您可以從崩潰中發佈調用堆棧嗎? – Arkadiy

+0

請提供一個最簡單的**完整**程序來證明你的錯誤。從你的實際程序開始,刪除所有工作的行,並向我們展示剩下的內容。 [Here](http://ideone.com/azOcT)是您的第一個代碼片段的工作實現的一個例子。有關使用此技術的更多信息,請參閱http://sscce.org。 –

回答

15

你舉的例子:

FILE *myfile; 
std::fstream fileStream(myfile); 
std::string mystring; 
while(std::getline(myfile,mystring)) 

簡化版,工作,因爲雖然你是非常接近的標準庫不提供可以從FILE*構建一個fstream。然而,Boost iostreams確實提供了一個iostream,它可以從一個文件描述符構建,你可以通過調用filenoFILE*得到一個。

例如爲:

typedef boost::iostreams::stream<boost::iostreams::file_descriptor_sink> 
     boost_stream; 

FILE *myfile; 
// make sure to popen and it succeeds 
boost_stream stream(fileno(myfile)); 
stream.set_auto_close(false); // https://svn.boost.org/trac/boost/ticket/3517 
std::string mystring; 
while(std::getline(stream,mystring)) 

不要忘了pclose以後還是。

注意:較新版本的boost已棄用構造函數,該構造函數只需要一個fd。相反,您需要將boost::iostreams::never_close_handleboost::iostreams::close_handle之一作爲構造函數的強制性第二個參數。

+0

一些編譯器提供標準C++庫的非標準擴展。採用FILE *的fstream構造函數是一種流行的構造函數。這解釋了爲什麼它在一些編譯器上而不是在其他編譯器上工作。 – Sjoerd

+0

@Sjoerd - 是的,這是有道理的。我想知道爲什麼會這樣寫。仍然可以使用typedef在配置時在構建工具中選擇非標準擴展和增強庫。 – Flexo

+1

我嘗試了fstream的標準構造函數,但在我的情況下沒有被接受。我現在嘗試以這種方式... – Stefano

-5

這是我寫回來的東西,可以幫助你。它可能有一些錯誤。

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

bool my_popen (const std::string& cmd,std::vector<std::string>& out) { 
    bool   ret_boolValue = true; 
    FILE*   fp; 
    const int  SIZEBUF = 1234; 
    char   buf [SIZEBUF]; 
    out = std::vector<std::string>(); 
    if ((fp = popen(cmd.c_str(), "r")) == NULL) { 
     return false; 
    } 
    std::string cur_string = ""; 
    while (fgets(buf, sizeof (buf), fp)) { 
     cur_string += buf; 
    } 
    out.push_back (cur_string.substr (0, cur_string.size() - 1)); 
    pclose(fp); 
    return true; 
} 
int main (int argc, char **argv) { 
     std::vector<std::string> output; 
     my_popen("ls -l > /dev/null ", output); 
     for (std::vector<std::string>::iterator itr = output.begin(); 
               itr != output.end(); 
               ++itr) { 
       std::cout << *itr << std::endl; 
     } 

}