2017-12-30 249 views
5

aşağıdaki Davam gibidir: C++ std :: stringstream işlemleri optimizasyonlar

  1. I (char *)
  2. Amacım olduğu gibi bir ikili ben std :: fstream ile gelen okuyorum dosyayı okumak operasyon var dosyada, altıgen biçimli her bayt almak ve sonra değişken bir dizeye eklemek için
  3. diyelim Örneğin 2.

ürün başına biçimlendirilmiş dosyanın tüm içeriği tutmak gerekir dize değişkeni Aşağıdaki bölüme sahibim beklendiği gibi yaklaşımda Üstü

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

Ancak öyle işler: ary dosya içeriği şu şekildedir:

D0 46 98 57 A0 24 99 56 A3

Her byte biçimlendirme ediyorum yoludur Anladığım büyük dosyalar için çok yavaş; stringstream giriş formatlaması içindir!

Sorum şu: Bu kodu ya da hep birlikte aldığım yaklaşımı optimize etmenin yolları var mı? Benim tek kısıtlama, çıktının yukarıda gösterildiği gibi dize formatında olması gerektiğidir.

Teşekkür ederiz.

+3

iostreams verimlilik için tasarlanmamıştır. Belirli kullanım durumları için, yerel uygulamaya özgü dosya G/Ç'yi geçemezsiniz. Ya da, daha da kötüsü, C'nin 'FILE *' al ve kendi el ile optimize edilmiş hex dönüşüm kodunu. Verimlilik için bunu yenemedim. Bu roket bilimi değil. En azından C ve C++ öğelerini öğrendiğim günlerde, bu tipik bir ev ödevi göreviydi: onaltılık oku ve dönüştür. –

+1

Neye kıyasla “Son derece yavaş”? –

+1

Çıkış dizesi için [boyut ayırma] (https://stackoverflow.com/q/1941064/995714) denediniz mi? Girişin boyutunu zaten biliyorsunuz, bu yüzden çıktı büyüklüğünü hesaplamak ve diziyi birçok kez yeniden tahsis etmekten kaçınmak –

cevap

4

std::stringstream oldukça yavaştır. Preallocate olmayacak ve her zaman en az bir kez geri almak için dize kopyalamayı içerir. Ayrıca hex'e dönüştürme, daha hızlı olması için kodlanmış olabilir.

Böyle bir şey daha fazla ölçülebilir olabileceğini düşünüyorum:

// 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; 
} 

Bu kopyalanmasını en aza indirmek ve reallocations önlemek için bir ön tahsis dizeye ekler.

+0

Detaylı çözüm için teşekkürler @Galik. Bu yaklaşımla dikkate değer bir performans artışı. – Xigma