2013-11-21 7 views
5

This answer इस तथ्य को इंगित करता है कि सी ++ बाइनरी फ़ाइल पर पुनरावृत्ति के लिए उपयुक्त नहीं है, लेकिन मुझे अभी यह चाहिए कि मुझे "बाइनरी" तरीके से फ़ाइलों पर काम करने की ज़रूरत है, हां सभी फाइलें बाइनरी हैं यहां तक ​​कि .txt वाले, लेकिन मैं कुछ ऐसी चीजें लिख रहा हूं जो छवि फ़ाइलों पर चलती हैं, इसलिए मुझे अच्छी तरह से संरचित फाइलें पढ़ने की ज़रूरत है, क्या डेटा को एक विशिष्ट तरीके से व्यवस्थित किया गया था।सी ++ बाइनरी फाइलें और इटरेटर: ifstreambuf_iterator का उपयोग कर 1: 1 से दूर हो रहे हैं?

मैं पूरी फ़ाइल को डेटा संरचना में std::vector<T> में पढ़ना चाहूंगा ताकि मैं लगभग फ़ाइल को बंद कर सकूं और डिस्क I/O की देखभाल किए बिना स्मृति में सामग्री के साथ काम कर सकूं।

अभी, मानक पुस्तकालय के अनुसार एक फ़ाइल पर एक पूरी यात्रा प्रदर्शन करने के लिए सबसे अच्छा तरीका है

std::ifstream ifs(filename, std::ios::binary); 
    for (std::istreambuf_iterator<char, std::char_traits<char> > it(ifs.rdbuf()); 
     it != std::istreambuf_iterator<char, std::char_traits<char> >(); it++) { 
    // do something with *it; 
    } 
ifs.close(); 

या std::copy का उपयोग की तर्ज पर कुछ है, लेकिन फिर भी std::copy साथ आप हमेशा istreambuf iterators का उपयोग कर रहे (इसलिए यदि मैं सी ++ दस्तावेज को सही ढंग से समझता हूं, तो आप मूल कोड को पिछले कोड के साथ प्रत्येक कॉल पर 1 बाइट पढ़ रहे हैं)।

तो सवाल यह है कि: मैं एक कस्टम इटरेटर कैसे लिखूं? जहां से मुझे उत्तराधिकारी होना चाहिए?

मुझे लगता है कि डिस्क पर फ़ाइल लिखते समय यह भी महत्वपूर्ण है, और मुझे लगता है कि मैं लिखने के लिए एक ही इटरेटर वर्ग का उपयोग कर सकता हूं, अगर मैं गलत हूं तो कृपया मुझे सही करने के लिए स्वतंत्र महसूस करें।

+0

क्या इनबाउंड डेटा का * आकार * आपको केवल ['ifs.read'] (http://en.cppreference.com/w/cpp/io/basic_istream/read) से अलग करता है-डेटा को सीधे ऊपर ले जाना एक 'std :: वेक्टर 'में और उस पर फिर से चल रहा है? – WhozCraig

+0

@WhozCraig अब मुझे नहीं लगता कि फ़ाइल मेमोरी में रखने के लिए बहुत बड़ी है (यदि आप यही कह रहे हैं), मैं 'रीड' या किसी अन्य तरीके से ठीक हूं, यहां तक ​​कि कन्स्ट्रक्टर 'वेक्टर' वर्ग इटरेटर्स का समर्थन करता है, इसलिए मैं उस तरफ ठीक हूं, "समस्या" स्वयं ही इटरेटर हैं, मैं डेटा को अलग-अलग ब्राउज़ करने का प्रयास करने के लिए एक लिखना चाहता हूं। संपादित करें: मैं किसी भी सी-आईश तरीके से बचना चाहता हूं, मैं इटरेटर के साथ रहूंगा। – user2485710

+1

* आप मूल रूप से प्रत्येक कॉल पर 1 बाइट पढ़ रहे हैं * - 'ifstream' के इन-मेमोरी बफर से, फ़ाइल से नहीं। वास्तविक पढ़ने (2) कॉल अभी भी प्रत्येक 4k या 16k के लिए हैं या जो भी आपके लिए डिफ़ॉल्ट बफर है। – Cubbi

उत्तर

1

std::istreambuf_iterator<char> का उपयोग करके अनुकूलित करना संभव है लेकिन शायद ही कोई कार्यान्वयन करता है। बस कुछ से प्राप्त करने से वास्तव में चाल नहीं होगी क्योंकि यह नहीं है कि यह कैसे काम करता है।

सबसे प्रभावी में निर्मित दृष्टिकोण शायद बस एक std::ostringstream में फ़ाइल डंप करने के लिए और प्राप्त है एक std::string वहाँ से:

std::ostringstream out; 
out << file.rdbuf(); 
std::string content = out.str(); 

आप एक std::string आप एक धारा लिख ​​सकता है के माध्यम से यात्रा से बचना चाहते हैं बफर सीधे मेमोरी एरिया या std::vector<unsigned char> में सामग्री को डंप कर रहा है और उपरोक्त आउटपुट ऑपरेशन का भी उपयोग कर रहा है।

std::istreambuf_iterator<char> एस, सैद्धांतिक रूप से धारा बफर के लिए एक पिछवाड़े है और चरित्र के संचालन को बाईपास कर सकता है। उस पिछवाड़े के बिना आप इन इटरेटर का उपयोग करके कुछ भी तेज नहीं कर पाएंगे। आप समान बफर से निपटने के लिए स्ट्रीम बफर के sgetn() का उपयोग करके स्ट्रीम बफर के शीर्ष पर एक इटरेटर बना सकते हैं। उस स्थिति में आपको std::copy() के संस्करणों से निपटने के लिए बहुत अधिक आवश्यकता होगी (यानी, प्रत्येक बफर भरें) कुशलतापूर्वक। इनमें से कम से कम मैं स्ट्रीम बफर का उपयोग करके फ़ाइल को बफर में पढ़ता हूं और उस पर पुनरावृत्ति करता हूं।

+0

तो आप मूल रूप से मेरे पहले कार्यान्वयन के साथ चिपकने का सुझाव दे रहे हैं? संभावित त्रुटियां क्या हैं? फ़ाइल दूषित होने पर क्या होता है? – user2485710

1

मेरा सुझाव कस्टम स्ट्रीम, स्ट्रीम-बफर या स्ट्रीम-इटरेटर का उपयोग नहीं करना है।

#include <fstream> 

struct Data { 
    short a; 
    short b; 
    int c; 
}; 

std::istream& operator >> (std::istream& stream, Data& data) { 
    static_assert(sizeof(Data) == 2*sizeof(short) + sizeof(int), "Invalid Alignment"); 
    if(stream.read(reinterpret_cast<char*>(&data), sizeof(Data))) { 
     // Consider endian 
    } 
    else { 
     // Error 
    } 
    return stream; 
} 

int main(int argc, char* argv[]) 
{ 
    std::ifstream stream; 
    Data data; 
    while(stream >> data) { 
     // Process 
    } 
    if(stream.fail()) { 
     // Error (EOF is good) 
    } 
    return 0; 
} 

आप एक धारा बफर इटरेटर पढ़ने तत्वों underlaying char_type से बड़ी आकार होने बनाने के लिए की हिम्मत कर सकता है: डेटा अवैध स्वरूप है

  • क्या होगा अगर?
  • क्या होगा यदि डेटा अपूर्ण है और ईओएफ पर है?

स्ट्रीम की स्थिति बफर या पुनरावर्तक द्वारा नहीं रखी जाती है।

+0

मैं पूरी फाइल को बफर कर सकता हूं? – user2485710

+0

@ user2485710 वह अंडरलेइंग स्ट्रीम बफर पर निर्भर करेगा (इसलिए यह संभव है) –

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