std::istream
是一個抽象類型–你不能直接使用它。你應該從它派生一個自定義陣列支持streambuf
:
#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爲了這個目的:
#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();
代碼imemstream
取自this answer通過Dietmar Kühl。
「*我試圖將文件映射到內存然後**然後**逐行解析*」。你能告訴我們爲什麼你想記憶地圖的文件?爲什麼不逐行解析(使用ifstream或fopen)就足夠了? –
@Rob,純粹是出於性能原因。我在(錯誤?)印象之下,它更快地映射整個文件? – user997112
@ user997112:這取決於你對數據做了什麼。如果您使用它來實現回溯的正確解析器,那麼內存映射文件無疑會更快;但如果你只是通過數據向前迭代(就像多個簡單的'std :: getline'調用一樣),我懷疑會有什麼明顯的差異。不過,除非虛擬地址空間不足(可能只是帶有GB +大小文件的32位代碼中的一個問題),否則肯定沒有使用內存映射文件的_harm_。 – ildjarn