簡體   English   中英

文件/ ifstream上的雙向迭代器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM