2012-05-31 12 views
10

मैं एक फ़ाइल को स्मृति में मैप करने की कोशिश कर रहा हूं और फिर रेखा से लाइन को पार्स कर रहा हूं- क्या मुझे इसका उपयोग करना चाहिए?आईट्रीम बनाम स्मृति एक फ़ाइल मैपिंग?

क्या आईट्रीम विंडोज़ पर स्मृति के लिए फ़ाइल मैप करने जैसा ही है? मुझे स्मृति में फ़ाइल मैप करने का पूरा उदाहरण खोजने का प्रयास करने में कठिनाई हुई है।

मैंने लोगों को एमएसडीएन से मेमोरी मैपिंग लेख लिंक किया है, लेकिन अगर कोई छोटी (~ 15 लाइन?) उदाहरण की सिफारिश कर सकता है तो मुझे सबसे ज्यादा स्वागत है।

मुझे गलत चीज़ खोजनी होगी, लेकिन Google पर "C++ मेमोरी मैपिंग उदाहरण" खोजते समय मुझे एक ऐसा उदाहरण नहीं मिला जिसमें इसके माध्यम से पुनरावृत्ति शामिल हो। http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2044.html#ClassSharedMemoryObjectExample

http://msdn.microsoft.com/en-us/library/dd997372.aspx (कोई सी ++ कोड)

http://beej.us/guide/bgipc/output/html/multipage/mmap.html (मेरा मानना ​​है कि यूनिक्स के लिए किया गया था, नहीं खिड़कियां)

+3

"* मैं एक फ़ाइल को स्मृति में मैप करने की कोशिश कर रहा हूं और ** ** ** लाइन * द्वारा लाइन पार्स *। क्या आप हमें बता सकते हैं कि आप फाइल को मेमोरी-मैप क्यों करना चाहते हैं? लाइन-बाय-लाइन का विश्लेषण क्यों नहीं कर रहा है (कहें, कहें, 'ifstream' या' fopen') पर्याप्त है? –

+3

@Rob, पूरी तरह से प्रदर्शन कारणों से। मैं (झूठी?) इंप्रेशन के तहत था कि यह पूरी फाइल को तेजी से मैप कर रहा है? – user997112

+2

@ user997112: यह इस बात पर निर्भर करता है कि आप डेटा के साथ क्या करते हैं। यदि आप इसे एक उचित पार्सर के लिए उपयोग कर रहे हैं जो बैकट्रैकिंग लागू करता है, तो स्मृति मैप की गई फ़ाइलें अनचाहे तेज़ी से होती हैं; लेकिन यदि आप डेटा के माध्यम से आगे बढ़ रहे हैं (जैसे कि कई सरल 'std :: getline' कॉल के साथ), मुझे संदेह है कि कोई ध्यान देने योग्य अंतर होगा। निश्चित रूप से मेमोरी मैप किए गए फ़ाइल का उपयोग करने में कोई _harm_ नहीं है, हालांकि, जब तक कि आप वर्चुअल एड्रेस स्पेस पर कम न हों (शायद जीबी + आकार फ़ाइलों के साथ 32-बिट कोड में केवल एक समस्या)।फ़ाइल को – ildjarn

उत्तर

11

std::istream:

ये निकटतम परिणाम (सिर्फ इसलिए लोग जो बात मैं ध्यान दिया है) थे एक सार प्रकार – है जिसे आप सीधे इसका उपयोग नहीं कर सकते हैं।

#include <cstddef> 
#include <string> 
#include <boost/interprocess/file_mapping.hpp> 
#include <boost/interprocess/mapped_region.hpp> 

namespace bip = boost::interprocess; 

//... 

std::string filename = /*...*/; 
bip::file_mapping mapping(filename.c_str(), bip::read_only); 
bip::mapped_region mapped_rgn(mapping, bip::read_only); 
char const* const mmaped_data = static_cast<char*>(mapped_rgn.get_address()); 
std::size_t const mmap_size = mapped_rgn.get_size(); 

के लिए कोड:

#include <cstddef> 
#include <string> 
#include <streambuf> 
#include <istream> 

template<typename CharT, typename TraitsT = std::char_traits<CharT>> 
struct basic_membuf : std::basic_streambuf<CharT, TraitsT> { 
    basic_membuf(CharT const* const buf, std::size_t const size) { 
     CharT* const p = const_cast<CharT*>(buf); 
     this->setg(p, p, p + size); 
    } 

    //... 
}; 

template<typename CharT, typename TraitsT = std::char_traits<CharT>> 
struct basic_imemstream 
: virtual basic_membuf<CharT, TraitsT>, std::basic_istream<CharT, TraitsT> { 
    basic_imemstream(CharT const* const buf, std::size_t const size) 
    : basic_membuf(buf, size), 
     std::basic_istream(static_cast<std::basic_streambuf<CharT, TraitsT>*>(this)) 
    { } 

    //... 
}; 

using imemstream = basic_imemstream<char>; 

char const* const mmaped_data = /*...*/; 
std::size_t const mmap_size = /*...*/; 
imemstream s(mmaped_data, mmap_size); 
// s now uses the memory mapped data as its underlying buffer. 

स्मृति-मानचित्रण खुद के लिए के रूप में, मैं इस उद्देश्य के लिए Boost.Interprocess का उपयोग करना चाहिये: आप एक कस्टम सरणी समर्थित streambuf के साथ से पाने की जानी चाहिए imemstreamthis answer से Dietmar Kühl पर लिया गया।

+2

mmaped_data से इनपुट कहां से आता है? मुझे लगता है कि फ़ाइल के संदर्भ में हमें एक संदर्भ की आवश्यकता है? – user997112

+1

@ user997112: यह इस बात पर निर्भर करता है कि आप किस प्लेटफ़ॉर्म पर हैं - मानक C++ मेमोरी मैप की गई फ़ाइलें प्रदान नहीं करता है। * निक्स पर, 'mmap' है; विंडोज़ पर, 'CreateFileMapping' है। व्यक्तिगत रूप से, मैं [बूस्ट.इंटरप्रोसेस] (http://www.boost.org/libs/interprocess/) की स्मृति मैप की गई फ़ाइलों का उपयोग करता हूं, क्योंकि वे क्रॉस-प्लेटफ़ॉर्म हैं; मैं इसके लिए एक उदाहरण में संपादित करूंगा। – ildjarn

+0

धन्यवाद, इसकी सराहना करें – user997112

1

क्या आईट्रीम विंडोज़ पर स्मृति के लिए फ़ाइल मैप करने जैसा ही है?

बिल्कुल नहीं। वे एक ही अर्थ में समान नहीं हैं "स्ट्रीम" एक "फ़ाइल" नहीं है।

एक फ़ाइल को संग्रहीत अनुक्रम के रूप में सोचें, और "चैनल" (एक stream_buffer) के लिए इंटरफ़ेस के रूप में एक स्ट्रीम के लिए जो अनुक्रम चर के प्रति अपने स्टोर से आगे बढ़ते समय प्रवाह करता है।

मेमोरी मैप की गई फ़ाइल को "फ़ाइल" के रूप में सोचें जो कि प्रोसेसिंग इकाई के बाहर संग्रहीत किया गया है- स्मृति में सिंक में संग्रहीत है। एक फ़ाइल होने के नाते कच्चे मेमोरी बफर के रूप में दिखाई देने का लाभ है। यदि आप इसे स्ट्रीम के रूप में पढ़ना चाहते हैं, तो सबसे आसान तरीका संभवतः एक आईटिंगस्ट्रीम का उपयोग कर रहा है जिसमें उस कच्चे बफर को पढ़ने के स्थान के रूप में रखा गया है।

+0

ईमानदार होने के लिए, मैं – user997112

+0

@ user997112 स्ट्रीम के विपरीत एक बार में पूरी फ़ाइल को पढ़ूंगा: यह इस बात पर निर्भर करता है कि आप इसकी सामग्री के साथ क्या करेंगे। अगर फ़ाइल एक पाठ है और आप संख्याओं को पढ़ना चाहते हैं तो आपको इसे किसी भी तरह से पार्स करना होगा। Std :: istream (और व्युत्पन्न) सिर्फ उस पार्सर हैं। –

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