2009-12-09 13 views
22

これはかなり一般的なはずですが、私はそれがまっすぐな解決策を見つけることができなかったことを魅了しています。C++ stl stringstreamダイレクトバッファアクセス

基本的に私はネットワーク上のファイルを文字列ストリームに読み込みました。これは宣言です:

std::stringstream membuf(std::ios::in | std::ios::out | std::ios::binary); 

は、今私は、メモリの読み出しチャンクへの直接アクセスを望んでいるいくつかのCライブラリを持っています。それをどうやって得るのですか?読み取り専用アクセスはOKです。 Cの機能が完了した後、私はmemorystreamを処分します。それは必要ありません。

str()は、バッファをコピーします。これは不要と思われ、メモリを2倍にします。

明らかなものがありませんか?たぶん異なるstlクラスがうまくいくでしょう。

: 明らかに、stringstreamは連続して格納されているとは限りません。何ですか?

私が使用している場合vector<char>どのようにバイトバッファを取得しますか?

+0

'vector'はすべての要素を連続して格納するので、次のように" buffer "を得ることができます: –

+1

@Steve Guidi:何バイトになるのか分からない限り'ベクトル'は 'std:stringstream'よりも多くのコピーを作成することがあります。なぜなら、そのデータを追加してコピーして、ストレージを連続した状態に保つためです。 –

+0

これは役立つのですか?http://stackoverflow.com/questions/132358/how-to-read-file-content-into-istringstream/138645#138645 –

答えて

7

str()に電話してstd :: stringを返すことができます。そこから、char*を得るためにstd :: stringのc_str()と呼ぶことができます。 std::istream::read:これはおそらく、より良い解決策である

にそのc_strに注意してください()公式にこの使用はサポートされていませんが、誰もがこのようにそれを使用しています:)

編集。そのページ上の例から:

buffer = new char [length]; 

    // read data as a block: 
    is.read (buffer,length); 
+5

男、バッファーを3倍にする。 – Kugel

+1

しかし、これは動作します。私はSTLの方がいい方法がないなら、答えとしてマークします。 – Kugel

+2

'c_str()'は 'std :: basic_string'の標準インターフェースの一部です。 'const char *'(とにかく読み込み専用のアクセス権を求める質問)を返すという細部の詳細は別として、この 'c_str'の使用法はどのようにサポートされていませんか? –

11

std::stringstreamは(必ずしも)連続そのバッファを保存しませんが、それが徐々に満たされているとして、チャンクを割り当てることができます。次に、すべてのデータを連続したメモリ領域に保存する場合は、コピーする必要があります。これがstr()の処理です。

もちろん、別のストレージ戦略を持つクラスを使用したり、書き込んだりすることができますが、std::stringstreamをまったく使用する必要はありません。

+0

チャールズ、助けてもらえますか?私は、 'rdbuf()'でstringstreamで使用される基礎となるstringbufを取得できることを知っています。そして、私は、標準でstringbuf/stringstreamが非連続であると言っている言葉を見つけることはできません。私はあなたが与えることができる任意のポインタに感謝します。ありがとう。 –

+0

'stringbuf'は連続したストレージを使用しなければならないとはどこですか?標準では、文字シーケンスを格納する必要がありますが、方法は指定していません。 'streambuf'インターフェースは' overflow'と 'underflow'を持っているので、ストリームを一つの連続した範囲として利用する必要はなく、' std :: string'と 'str'からのコンストラクタだけが必要ですそれらのすべては、基礎となる文字シーケンスのコピーを扱う。私はインターフェイスがインクリメンタルな追加のために設計されているので、常に連続したストレージを使用していた実装には(少しずつ)失望していました。 –

+1

rdbufは私が実行したすべてのテストケースでうまくいきます...しかし、もし私があなただったら、使用する前にいくつかの連続テスト(ストリームのrdbuf =文字の長さ)でアサートします。あなたのテストスイートにスティックして、プラットフォームの移植などのために行くのが良いです。 –

6

まあ、あなたが真剣にストレージを心配している場合、あなたは金属に近づくことができます。 basic_stringstreamは、それが( basic_streambuf 由来する)basic_stringbufだ返すメソッド、RDBUF()を有しています。次に、eback(),egptr()およびgptr()ポインタをバッファから直接アクセスするためのポインタに使用できます。私は過去のこの機械を使って、私が望むセマンティクスを持ったカスタムバッファを実装しました。

注意してください、これは心のかすかなためではありません!数日をとりあえず、Standard C++ IOStreams and Locales、または類似のニックピックリファレンスを読み、注意してください...あなたはstringstream

stringstream membuf(std::ios::in | std::ios::out | std::ios::binary); 
membuf.rdbuf(yourVeryOwnStreamBuf); 

で自分自身をバッファ書き込み、そのバッファを使用することによって使用されるバッファの完全な制御を取ることができ

+0

'eback'、' egptr'と 'gptr'は保護されているので' stringbuf'の 'rdbuf'ポインタは取得されませんこれらにアクセスできます。たとえそれがあったとしても、 '.str()'と '.data()'というより少ないコピーで、元のシーケンスの連続したコピーを作成できるという保証はないと思います。 –

+0

私は独自の派生バッファを実装していたので、メソッドにアクセスできました。そして私はG ++がちょうど連続アクセスをしていると思います。私はまだ標準でこの制限(不連続)を見つけることができませんでした... –

12

あなた自身のバッファがbasic_streambuf由来し、適切sync()overflow()メソッドをオーバーライドする必要があります。

内部表現では、再割り当てとコピーが行われないように、vector<char>reserve()のようなものを必要なサイズに使用できます。

これは、事前に必要なスペースの上限を知ることを意味します。しかし、あらかじめサイズを知らず、最終的にバッファーが必要な場合は、もちろんコピーは避けられません。

+1

reallocは、割り当てを最初に増やそうと試みることによって、コピーせずにバッファを増やすことができます。 reallocはしばしばデータを移動しますが、100%は移動しません。私はそれが "コピー常に"よりはるかに効率的だとわかった。ベクトルから派生するのではなく、カスタムストリームクラスのベースとしてchar *とreallocを使用するだけです。 –

+0

私は怠け者だと思われますが、ここで説明した概念とまったく同じ解答として、完全なスニペットで答えるに値する質問です。私は 'basic_streambuf'を一度継承しました。もう一度やりません。申し訳ありません。 – ceztko