2010-07-08 39 views
51

我想讀整個流(多行)到一個字符串。如何將整個流讀入std :: string?

我使用此代碼,它的工作原理,但它的冒犯我的風格......當然有更簡單的方法嗎?也許使用stringstreams?

void Obj::loadFromStream(std::istream & stream) 
{ 
    std::string s; 

    std::streampos p = stream.tellg(); // remember where we are 

    stream.seekg(0, std::ios_base::end); // go to the end 
    std::streamoff sz = stream.tellg() - p; // work out the size 
    stream.seekg(p);  // restore the position 

    s.resize(sz);   // resize the string 
    stream.read(&s[0], sz); // and finally, read in the data. 


其實,一個 const參照字符串將做的一樣好,而且可能使事情變得更容易...

const std::string &s(... a miracle occurs here...) 

回答

79

如何

std::istreambuf_iterator<char> eos; 
std::string s(std::istreambuf_iterator<char>(stream), eos); 

(可能是一個班輪如果不是MVP)

2011後編輯,這種做法現在拼寫

std::string s(std::istreambuf_iterator<char>(stream), {}); 
+1

如果你想:它可能仍然是一個單線程:'string s = string(...)'。 – 2010-07-08 12:38:37

+1

謝謝。你能詳細說明這是幹什麼嗎?不需要初始化嗎? – Roddy 2010-07-08 12:46:19

+13

@Roddy:該字符串是istreambuf_iterator的範圍結構,它對未格式化的字符進行迭代,直到它變成默認構造的輸入迭代器,即「流的結尾」。請參閱Scott Meyers,Effective STL第29項:考慮istreambuf_iterators逐個字符輸入 – Cubbi 2010-07-08 12:56:43

14

你可以做

std::string s; 
std::ostringstream os; 
os<<stream.rdbuf(); 
s=os.str(); 

,但我不知道它是否更有效率。

替代版本:

std::string s; 
std::ostringstream os; 
stream>>os.rdbuf(); 
s=os.str(); 
+1

感謝。作爲解決方案,我覺得這非常簡單易讀,而且我正在使用它。但是,我接受了Cubbi的答案,因爲我從中學到了很多東西! – Roddy 2010-07-08 13:33:27

11

你c嘗試使用算法中的某些東西。我要做好準備工作,但這裏的事物非常快刺(我們有了一個更好的辦法):

​​
+6

請注意,'istream_iterator '將刪除所有空白和不可打印的字符。用'istreambuf_iterator ',這可以工作,但。 – Cubbi 2010-07-08 13:10:58

21

,我遲到了,但這裏是一個非常有效的解決方案:

std::string gulp(std::istream &in) 
{ 
    std::string ret; 
    char buffer[4096]; 
    while (in.read(buffer, sizeof(buffer))) 
     ret.append(buffer, sizeof(buffer)); 
    ret.append(buffer, in.gcount()); 
    return ret; 
} 

我做了一些基準測試,結果發現std::istreambuf_iterator技術(used by the accepted answer)實際上要慢得多。在gcc 4.4.5和-O3上,我的機器差異大約是4.5倍,差距隨着較低的優化設置而變寬。

+5

確實比我的回答更有效,因爲正確的分塊讀取會是。 OP想要「簡單」的方式,這通常與「快速」相反。 – Cubbi 2011-02-12 15:49:30

+6

使用string :: reserve(size_t)會使它更加高效。 – Tim 2012-12-12 12:17:34

+0

喬伊,用-O2進行優化。我記得,選項-O3不是最快的,而是緊湊的代碼。 – 2015-09-04 08:42:32

1

那麼,如果你正在尋找一個簡單的'可讀'的方式來做到這一點。我會建議在你的項目中添加/使用一些高級框架。爲此我總是在我所有的項目中使用Poco和Boost。在這種情況下,與波索:

string text; 
    FileStream fstream(TEXT_FILE_PATH); 
    StreamCopier::copyToString(fstream, text); 
0

也許這1行C++ 11溶液:

std::vector<char> s{std::istreambuf_iterator<char>{in},{}}; 
相關問題