2017-12-30 88 views
5

इस प्रकार मेरे मामले जाता है:सी ++ std :: stringstream संचालन अनुकूलन

  1. मैं एक बाइनरी फ़ाइल मैं std :: fstream साथ से पढ़ रहा हूँ के रूप में (चार *)
  2. मेरा लक्ष्य है पढ़ा आपरेशन है फ़ाइल, हेक्स स्वरूपित से हर बाइट ले, और फिर एक स्ट्रिंग चर से संलग्न करने के लिए
  3. स्ट्रिंग चर प्रति आइटम 2.

उदाहरण के लिए के रूप में स्वरूपित फ़ाइल की संपूर्ण सामग्री धारण करना चाहिए, मान लें मेरे पास निम्नलिखित बिन है ary फ़ाइल सामग्री:

stringstream fin;; 

for (size_t i = 0; i < fileb_size; ++i) 
{ 
fin << hex << setfill('0') << setw(2) << static_cast<uint16_t>(fileb[i]); 
} 

// this would yield the output "D0469857A0249956A3" 

return fin.str(); 

दृष्टिकोण से ऊपर काम करता है के रूप में उम्मीद, हालांकि, यह है:

D0 46 98 57 A0 24 99 56 ए 3

तरह से मैं प्रत्येक बाइट स्वरूपण कर रहा हूँ इस प्रकार है बड़ी फ़ाइलों के लिए बेहद धीमी, जो मैं समझता हूं; स्ट्रिंगस्ट्रीम इनपुट स्वरूपण के लिए है!

मेरा सवाल है, क्या ऐसे कोड या दृष्टिकोण को अनुकूलित करने के तरीके हैं जो मैं सभी एक साथ ले रहा हूं? मेरा एकमात्र बाधा यह है कि आउटपुट ऊपर दिखाए गए अनुसार स्ट्रिंग प्रारूप में होना चाहिए।

धन्यवाद।

+3

iostreams दक्षता के लिए डिज़ाइन नहीं किया गया है। विशिष्ट उपयोग मामलों के लिए, आप मूल कार्यान्वयन-विशिष्ट फ़ाइल I/O को हरा नहीं सकते हैं। या, बदतर मामले में, सी की 'फ़ाइल *' लें, और अपना खुद का, हाथ-अनुकूलित हेक्स रूपांतरण कोड रोल करें। दक्षता के लिए इसे हरा नहीं सका। यह कोई रॉकेट साईंस नहीं है। कम से कम उन दिनों में जब मैंने सी और सी ++ सीखा, यह एक ठेठ होमवर्क असाइनमेंट था: हेक्साडेसिमल पढ़ें, और इसे परिवर्तित करें। –

+1

क्या तुलना में "बेहद धीमी" है? आउटपुट स्ट्रिंग के लिए –

+1

क्या आपने [रिजर्व आकार] (https://stackoverflow.com/q/1941064/995714) का प्रयास किया था? आप पहले से ही इनपुट के आकार को जानते हैं, इसलिए आउटपुट के आकार की गणना करना आसान है और कई बार –

उत्तर

4

std::stringstream बल्कि धीमा है। यह प्रीलोकेट नहीं करेगा और इसमें स्ट्रिंग को कॉपी करना शामिल होगा, कम से कम एक बार इसे पुनर्प्राप्त करने के लिए। हेक्स में रूपांतरण को तेजी से कोडित किया जा सकता है।

मुझे लगता है कि कुछ इस तरह अधिक performant हो सकता है:

// Quick and dirty 
char to_hex(unsigned char nibble) 
{ 
    assert(nibble < 16); 

    if(nibble < 10) 
     return char('0' + nibble); 

    return char('A' + nibble - 10); 
} 

std::string to_hex(std::string const& filename) 
{ 
    // open file at end 
    std::ifstream ifs(filename, std::ios::binary|std::ios::ate); 

    // calculate file size and move to beginning 
    auto end = ifs.tellg(); 
    ifs.seekg(0, std::ios::beg); 
    auto beg = ifs.tellg(); 

    // preallocate the string 
    std::string out; 
    out.reserve((end - beg) * 2); 

    char buf[2048]; // larger = faster (within limits) 

    while(ifs.read(buf, sizeof(buf)) || ifs.gcount()) 
    { 
     for(std::streamsize i = 0; i < ifs.gcount(); ++i) 
     { 
      out += to_hex(static_cast<unsigned char>(buf[i]) >> 4); // top nibble 
      out += to_hex(static_cast<unsigned char>(buf[i]) & 0b1111); // bottom nibble 
     } 
    } 

    return out; 
} 

यह एक पूर्व आवंटित स्ट्रिंग के लिए संलग्न कर देता है नकल को कम करने और reallocations से बचने के लिए।

+0

धन्यवाद @ गैलिक। इस दृष्टिकोण के साथ उल्लेखनीय प्रदर्शन सुधार क्या है। – Xigma

संबंधित मुद्दे