11

fstream から正確に 128 バイトを文字列オブジェクトに読み込むにはどうすればよいですか?

ファイルの最初の 128 バイトを読み取って出力し、次にファイルの最後の 128 バイトを読み取って出力するコードを書きました。EOF まで簡単に反復できるため、最後の部分は機能しますが、先頭から正確に 128 バイトを取得するにはどうすればよいでしょうか? ifstream イテレータに 128 を追加できないため、以下のコードは機能しません。インデックス化できず、インクリメントのみ可能です (らしい)。

確かに、イテレータと *++ を 128 回作成することはできますが、それを行うには 1 行の簡単な方法が必要ですよね?

#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char **argv)
{
    std::ifstream ifs ("input.txt",std::ifstream::in | std::ifstream::binary);

    if (ifs.good())
    {
    // read first 128 bytes into a string
        ifs.seekg(0,std::ifstream::beg);
        std::string first128((std::istreambuf_iterator<char>(ifs)),
                             (std::istreambuf_iterator<char>(ifs))+128);

        std::cout << first128 << std::endl;

    // read last 128 bytes into a string
        ifs.seekg(-128,std::ifstream::end);
        std::string last128((std::istreambuf_iterator<char>(ifs)),
                            std::istreambuf_iterator<char>());

        std::cout << last128 << std::endl;

        return 0;
    }

    return 1;
}
4

3 に答える 3

1

私の答えは中間バッファーを使用しますが、おそらくイテレーターを使用してバッファーから文字列を初期化することに満足するでしょう。

std::vector<char> buffer(128); // create a buffer
ifs.read( &buffer[0], buffer.size() ); // read to buffer
std::string first128( buffer.begin(), buffer.end() ); // copy from vector

私には、iostream の実装で少しかわいくなりすぎたように思えます。ストリーム I/O に反復子を使用しようとすると、非常に複雑になります。

ちなみに、あなたが試みていた実装は、裏で、さまざまな中間バッファリング(おそらくカーネル内のいくつか、ライブラリ内のいくつか)を行い、文字列を数回再割り当てしてコピーするのではないかと思います成長します。

もう 1 つのアイデア: 標準文字列の結果が本当に必要ですか? ベクトルから作業するだけで、文字列へのコピーの最終ステップを回避できます。または、冒険心があれば、ベクターと同じ方法で内部バッファーを公開できる独自の文字列クラスを作成できます。

于 2010-08-22T05:07:35.887 に答える
1
char buffer[129];
ifs.read (buffer,128);
buffer[128] = '\0';
first128 = buffer;

では、これはどうですか:

template <typename Itr, typename Out>
void copy_n(Itr it, size_t count, Out out)
{
    for(size_t i=0;i<count;++i)
      out = *it++;
} 

...

std::string first128; 
std::istreambuf_iterator<char> it(ifs);
copy_n( it, 128,
  std::back_inserter<std::string>(first128) );
于 2010-08-22T04:43:41.773 に答える
-1

ここでは、コンストラクターによって istream から文字列に直接読み取って、ストリームバッファーを調査しています。

class mystringbuf : public std::stringbuf
{
public:
    explicit mystringbuf(std::istream& istr, size_t n,
                        std::ios_base::openmode __mode = std::ios_base::in )
    {
        _M_string.resize(n);
        std::stringbuf::_M_stringbuf_init(__mode);
        istr.read(gptr(), n);
    }
public:
    std::stringbuf::char_type* gptr() const
    {
        return std::stringbuf::gptr();
    }
    std::string& str_ref(){
        return _M_string;
    }
};
std::ostream& operator << (std::ostream& ostr, mystringbuf& buf){
    ostr << buf.str_ref();
    return ostr;
}

使用例:

using std::cout;
using std::endl;

int main()
{
    std::stringbuf buffer;          // empty buffer
    buffer.str("abc def ABC DEF "); // not empty now
    std::istream is (&buffer);      // associate stream buffer to stream
    mystringbuf data(is, 10);       // read 10 bytes
    cout << "data=" <<  data << endl;
    return 0;
}

出力:

data=abc def AB

私がどこか間違っていたら転送してください。

于 2014-12-04T16:39:21.300 に答える