【发布时间】:2014-08-04 15:40:41
【问题描述】:
我正在尝试学习 C++ 中的 boost 和一些模板编程,但我真的很难实现一个使用 mapped_file_source 迭代 Gzip 文件的简单类。我基本上有一个 TSV 格式的边缘列表,因此 gzip 文件中的每一行都是以下格式:<src:int><tab><dst:int>。我想要的是实现一个 gz_file 类,该类公开一个开始和结束迭代器,每次查询迭代器时,我都可以获得一个边缘 (std::pair<int,int>)。
问题是复制构造函数损坏了,因为我不知道我在 gzip 文件中的位置。
这是我目前的代码:
class gz_graph {
public:
gz_graph(const char * filename)
{
m_file.open(filename);
if (!m_file.is_open()) {
throw std::runtime_error("Error opening file");
}
m_data = m_file.data();
m_data_size = m_file.size() / sizeof(m_data[0]);
auto ret = posix_madvise((void*)m_data, m_data_size, POSIX_MADV_SEQUENTIAL);
}
class iterator;
iterator begin() const
{
return iterator(this, false);
}
iterator end() const
{
return iterator(this, true);
}
class iterator : public std::iterator<std::forward_iterator_tag, Edge> {
public:
iterator(gz_graph const * ref, bool consumed)
: m_ref(ref),
m_cur_edge(-1, -1),
m_consumed(consumed)
{
if (!consumed) {
initialize();
advance();
}
}
iterator(const iterator& x)
: m_ref(x.m_ref),
m_cur_edge(x.m_cur_edge)
{
if (!x.m_consumed) {
initialize();
advance();
}
std::cout << "Copy constructor" << std::endl;
}
value_type const& operator*() const
{
return m_cur_edge;
}
value_type const* operator->() const
{
return &m_cur_edge;
}
iterator& operator++()
{
advance();
return *this;
}
bool operator==(iterator const& other) const
{
assert(m_ref == other.m_ref);
return m_cur_edge == other.m_cur_edge;
}
bool operator!=(iterator const& other) const
{
return !(*this == other);
}
private:
void initialize()
{
boost::iostreams::array_source source(m_ref->m_data, m_ref->m_data_size);
m_in.push(boost::iostreams::gzip_decompressor());
m_in.push(source);
}
void advance()
{
std::string line_str;
if (!getline(m_in, line_str)) {
m_consumed = true;
m_cur_edge = Edge(-1, -1);
return;
}
std::vector<std::string> strs;
boost::split(strs, line_str, boost::is_any_of("\t"));
if (strs.size() != 2)
throw std::runtime_error("Required 2 fields per line");
int src = boost::lexical_cast<int>(strs.at(0));
int dst = boost::lexical_cast<int>(strs.at(1));
m_cur_edge = Edge(src, dst);
// std::cout << "Read line " << line_str << std::endl;
}
gz_graph const * m_ref;
Edge m_cur_edge;
boost::iostreams::filtering_istream m_in;
bool m_consumed;
};
private:
boost::iostreams::mapped_file_source m_file;
char const* m_data;
size_t m_data_size;
};
【问题讨论】:
-
不清楚你在问什么。
-
嗨@BrandonKohn,我在这里遇到的问题是复制构造函数显然被破坏了,因为我无法将 m_in (filtering_istream) 的状态复制到迭代器的新实例上(此类的复制构造函数是不是由 boost 提供的)。
-
您似乎正在尝试优化速度。我怀疑这会对压缩流产生任何影响。你分析了吗?