[英]bidirectional iterator over file/ifstream
我需要一個具有雙向迭代器/適配器的輸入文件流。
不幸的是std::ifstream
(和類似的東西)只能與std::istream_iterator
一起使用, std::istream_iterator
是一種向前的迭代器,不能向后移動。 (或者我在這里弄錯了嗎?)
我可以簡單地將整個文件加載到內存中,然后在數組上使用功能更強大的隨機訪問迭代器。 但是我想避免這種情況,只閱讀我真正需要的內容。 可能我確實只需要文件的一小部分。
我可以使用C stdio.h
函數手動完成該操作,但這會很痛苦。 我基本上需要手工實現一個雙向迭代器,同時牢記所有規范。
我正在考慮研究boost iostream庫,但是手冊有些讓人不知所措,我希望有人可以幫我實現這一特定目標? 也許還有另一個已經存在的庫可以完全滿足我的需要?
我需要boost xpressive庫的迭代器來解析我的文件,該文件期望迭代器可以遞增也可以遞減。 如果我正在讀取的文件被緩沖,則可以,盡管這不是必需的。
有任何想法嗎? 謝謝!
如果我以錯誤的方向遍歷文件,我將開始質疑我的要求。 這似乎是做事的一種精心設計的方式,很可能某處的某處有些混亂。
一旦確認這確實是必要條件,我就會意識到我們肯定是在這里談論文件,而不是例如命名管道或套接字。 也就是說,內存映射可能至少是文件的一部分。 我將使用它來創建一個遍歷內存的迭代器。 由於顯然需要迭代器,因此不需要涉及流。 如果還需要流,我仍然會在自定義流緩沖區中內存映射文件並從后面反向緩沖區。
當實際從頭開始讀取並且僅需要在必要時可以向后移動時,它可能比這更簡單:保留已讀取數據的緩沖區,並在移出末尾時擴展該數據,如果結束則可能讀取整個文件迭代器用於向后移動應解決此問題。 這是肯定可以向前和向后讀取文件但未經過全面測試的代碼:
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <limits>
#include <vector>
class bidirectional_stream
{
public:
class iterator;
typedef iterator const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
bidirectional_stream(std::istream& in):
in_(in)
{
}
iterator begin();
iterator end();
reverse_iterator rbegin();
reverse_iterator rend();
bool expand()
{
char buffer[1024];
this->in_.read(buffer, sizeof(buffer));
this->buffer_.insert(this->buffer_.end(), buffer, buffer + this->in_.gcount());
return 0 < this->in_.gcount();
}
long read_all()
{
this->buffer_.insert(this->buffer_.end(),
std::istreambuf_iterator<char>(this->in_),
std::istreambuf_iterator<char>());
return this->buffer_.size();
}
char get(long index) { return this->buffer_[index]; }
long current_size() const { return this->buffer_.size(); }
private:
std::istream& in_;
std::vector<char> buffer_;
};
class bidirectional_stream::iterator
{
public:
typedef char value_type;
typedef char const* pointer;
typedef char const& reference;
typedef long difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
iterator(bidirectional_stream* context, size_t pos):
context_(context),
pos_(pos)
{
}
bool operator== (iterator const& other) const
{
return this->pos_ == other.pos_
|| (this->pos_ == this->context_->current_size()
&& !this->context_->expand()
&& other.pos_ == std::numeric_limits<long>::max());
}
bool operator!= (iterator const& other) const { return !(*this == other); }
char operator*() const { return this->context_->get(this->pos_); }
iterator& operator++() { ++this->pos_; return *this; }
iterator operator++(int) { iterator rc(*this); this->operator++(); return rc; }
iterator& operator--()
{
if (this->pos_ == std::numeric_limits<long>::max())
{
this->pos_ = this->context_->read_all();
}
--this->pos_;
return *this;
}
iterator operator--(int) { iterator rc(*this); this->operator--(); return rc; }
private:
bidirectional_stream* context_;
long pos_;
};
bidirectional_stream::iterator bidirectional_stream::begin()
{
return iterator(this, 0);
}
bidirectional_stream::iterator bidirectional_stream::end()
{
return iterator(this, std::numeric_limits<long>::max());
}
bidirectional_stream::reverse_iterator bidirectional_stream::rbegin()
{
return reverse_iterator(this->end());
}
bidirectional_stream::reverse_iterator bidirectional_stream::rend()
{
return reverse_iterator(this->begin());
}
只需使用要讀取的流創建一個bidirectional_stream
作為參數,然后使用begin()
和end()
方法實際訪問它。
由於您已經在使用Boost,因此請看一下boost::iostreams::mapped_file_source
http://www.boost.org/doc/libs/release/libs/iostreams/doc/classes/mapped_file.html#mapped_file_source
您可以使用file.data()作為開始迭代器,而file.data()+ file.size()作為結束迭代器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.