5

私はandを C++ のランダム アクセス バイナリ I/O のポリモーフィック インターフェイスとして使用std::istreamしてきましたが、多くの点で次善のようです。ostream

  • streampos/streamoff の制限により、64 ビット シークは移植性がなく、エラーが発生しやすくなります。現在はboost/iostreams/positioning.hppを回避策として使用していますが、注意が必要です
  • ファイルの切り捨てや拡張などの操作の欠落 (ala POSIX ftruncate)
  • 具体的な実装間の矛盾; たとえばstringstream、独立した get/put ポジションがありますが、そうではありfilestreamません
  • プラットフォームの実装間の不一致; たとえば、ファイルの最後をパスしようとする動作や、エラーでのfailbit/の使用badbit
  • streamのすべてのフォーマット機能や、場合によってはバッファリングさえも必要ありませんstreambuf
  • streambufエラー報告 (つまり、例外とエラー インジケーターを返すこと) は、実際には実装に依存していると考えられます。

Boost.Iostreams Device conceptによって提供される簡素化されたインターフェイスが気に入っていますが、これはポリモーフィック クラスではなく、関数テンプレートとして提供されています。( deviceclassはありますが、ポリモーフィックではなく、提供されたデバイス実装で必ずしも使用されるとは限らない単なる実装ヘルパー クラスです。) 私は主に大きなディスク ファイルを使用していますが、別の実装を簡単に置き換えることができるように、本当にポリモーフィズムが必要です (例:単体テストstringstreamの代わりに使用します) 深いテンプレートのインスタンス化の複雑さやコンパイル時の結合はありません。fstream

これに対する標準的なアプローチの推奨事項はありますか? これはよくある状況のように思えるので、不必要に独自のインターフェイスを発明したくありません。例として、java.nio.FileChannel のようなものが理想的です。

これまでの私の最善の解決策は、Boost.Iostreams デバイスの上に薄いポリモーフィック レイヤーを配置することです。例えば:

class my_istream
{
public:
    virtual std::streampos seek(stream_offset off, std::ios_base::seekdir way) = 0;
    virtual std::streamsize read(char* s, std::streamsize n) = 0;
    virtual void close() = 0;
};

template <class T>
class boost_istream : public my_istream
{
public:
    boost_istream(const T& device) : m_device(device)
    {
    }

    virtual std::streampos seek(stream_offset off, std::ios_base::seekdir way)
    {
        return boost::iostreams::seek(m_device, off, way);
    }

    virtual std::streamsize read(char* s, std::streamsize n)
    {
        return boost::iostreams::read(m_device, s, n);
    }

    virtual void close()
    {
        boost::iostreams::close(m_device);
    }

private:
    T m_device;
};
4

2 に答える 2

1

Qt の QIODevice クラスとサブクラスを見ましたか? それがあなたのニーズに合っているかどうかはよくわかりませんが、試してみる価値があるかもしれません: QIODevice

于 2010-06-15T21:32:21.663 に答える
0

質問で概説したものと同様の一連の抽象的なインターフェイスを使用することになりました。これには、軽量でポリモーフィックな標準はないようです...

于 2010-07-12T20:42:36.900 に答える