2010-07-08 19 views
51

मैं एक स्ट्रिंग में एक संपूर्ण धारा (एकाधिक लाइनों) को पढ़ने की कोशिश कर रहा हूं।संपूर्ण स्ट्रीम को std :: स्ट्रिंग में कैसे पढ़ा जाए?

मैं इस कोड का उपयोग कर रहा हूं, और यह काम करता है, लेकिन यह मेरी शैली की भावना को अपमानित कर रहा है ... निश्चित रूप से एक आसान तरीका है? शायद स्ट्रिंगस्ट्रीम का उपयोग कर?

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

(एक एक लाइनर हो सकता है अगर एमवीपी के लिए नहीं)

पोस्ट-2011 संपादित करें, इस दृष्टिकोण अब वर्तनी है

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

यदि आप चाहें तो यह अभी भी एक-लाइनर हो सकता है: 'स्ट्रिंग एस = स्ट्रिंग (...) '। –

+1

धन्यवाद। क्या आप यह बता सकते हैं कि यह क्या कर रहा है? क्या किसी को भी शुरू करने की जरूरत नहीं है? – Roddy

+13

@Roddy: स्ट्रिंग istreambuf_iterator से रेंज-कन्स्ट्रक्टेड है, जो अनफॉर्म किए गए वर्णों को तब तक सक्रिय करता है जब तक यह डिफ़ॉल्ट-निर्मित इनपुट इटरेटर, उर्फ ​​"स्ट्रीम का अंत" के बराबर न हो जाए। स्कॉट मेयर्स, प्रभावी एसटीएल आइटम 29 देखें: चरित्र-दर-चरित्र इनपुट – Cubbi

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

धन्यवाद। एक समाधान के रूप में, मुझे यह वास्तव में सरल और पठनीय लगता है, और मैं इसका उपयोग कर रहा हूं। हालांकि, मैंने कब्बी के जवाब को स्वीकार कर लिया क्योंकि मैंने इससे बहुत कुछ सीखा! – Roddy

11

आप सी एल्गोरिदम से कुछ का उपयोग करने का प्रयास करें। मैं काम करने के लिए तैयार हो जाओ करने के लिए है, लेकिन यहाँ चीजों को एक बहुत ही त्वरित चाकू है (वहाँ एक बेहतर तरीका हो गया है):

copy(istreambuf_iterator<char>(stream), istreambuf_iterator<char>(), back_inserter(s)); 
+6

ध्यान दें कि 'istream_iterator ' सभी व्हाइटस्पेस और गैर-प्रिंट करने योग्य पात्रों को छोड़ देगा। 'Istreambuf_iterator 'के साथ, यह काम करेगा, यद्यपि। – Cubbi

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) वास्तव में बहुत धीमी है। -O3 के साथ जीसीसी 4.4.5 पर, यह मेरी मशीन पर लगभग 4.5x अंतर है, और अंतर कम अनुकूलन सेटिंग्स के साथ व्यापक हो जाता है।

+5

वास्तव में मेरे उत्तर से अधिक कुशल, एक उचित ब्लॉक-वार पढ़ने के रूप में होगा। ओपी हालांकि "आसान" तरीका चाहता था, जो अक्सर "तेज़" के विपरीत होता है। – Cubbi

+6

स्ट्रिंग :: रिजर्व (size_t) का उपयोग करके इसे और भी अधिक कुशल बना दिया जाएगा। – Tim

+0

जॉय, -ओ 2 के साथ अनुकूलित करें। विकल्प-ओ 3 सबसे तेज़ नहीं है लेकिन कॉम्पैक्ट कोड के लिए मुझे याद है। –

1

ठीक है, अगर आप इसे करने के लिए एक सरल और 'पठनीय' तरीका ढूंढ रहे हैं। मैं आपकी परियोजना पर कुछ उच्च स्तरीय ढांचे को जोड़ने/उपयोग करने की सिफारिश करता हूं। इसके लिए मैं हमेशा अपनी सभी परियोजनाओं पर पोको और बूस्ट का उपयोग करता हूं। इस मामले में, पोको साथ में:

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

शायद यह 1 लाइन सी ++ 11 समाधान:

std::vector<char> s{std::istreambuf_iterator<char>{in},{}}; 
संबंधित मुद्दे