3

次の方法でバイナリファイルをロードしようとしてfstreamいます:

#include <iostream>
#include <fstream>
#include <iterator>
#include <vector>

using namespace std;

int main()
{
    basic_fstream<uint32_t> file( "somefile.dat", ios::in|ios::binary );

    vector<uint32_t> buffer;
    buffer.assign( istream_iterator<uint32_t, uint32_t>( file ), istream_iterator<uint32_t, uint32_t>() );

    cout << buffer.size() << endl;

    return 0;
}

しかし、うまくいきません。Ubuntu では、std::bad_cast例外でクラッシュしました。MSVC++ 2008 では、単に 0 を出力します。

ファイルのロードに使用できることはわかっていfile.readますが、イテレータを使用しoperator>>てファイルの一部をロードしたいと考えています。それは可能ですか?上記のコードが機能しないのはなぜですか?

4

4 に答える 4

3
  1. istream_iteratorbasic_istream引数として望んでいます。
  2. クラスoperator>>内でオーバーロードすることはできません。basic_istream
  3. globaloperator>>を定義すると、コンパイル時に class member との競合が発生しoperator>>ます。
  4. basic_istreamtype に特化できuint32_tます。しかし、特殊化のためには、クラスのすべての関数を書き直す必要がありますbasic_istream。代わりに、ダミー クラスを定義して、次のコードのようにx特殊化することができます。basic_istream
using namespace std;

struct x {};
namespace std {
template<class traits>
class basic_istream<x, traits> : public basic_ifstream<uint32_t>
{
public:
    explicit basic_istream<x, traits>(const wchar_t* _Filename, 
        ios_base::openmode _Mode, 
        int _Prot = (int)ios_base::_Openprot) : basic_ifstream<uint32_t>( _Filename, _Mode, _Prot ) {}

    basic_istream<x, traits>& operator>>(uint32_t& data)
    {
        read(&data, 1);
        return *this;
    }
};
} // namespace std 

int main() 
{
    basic_istream<x> file( "somefile.dat", ios::in|ios::binary );
    vector<uint32_t> buffer;
    buffer.assign( istream_iterator<uint32_t, x>( file ), istream_iterator<uint32_t, x>() );
    cout << buffer.size() << endl;
    return 0;
}
于 2009-07-21T09:04:27.170 に答える
0

アレクセイ・マリストフの答えと同じことをする別の方法:

#include <fstream>
#include <iterator>
#include <vector>
#include <iostream>

struct rint // this class will allow us to read binary
{
  // ctors & assignment op allows implicit construction from uint
  rint () {}
  rint (unsigned int v) : val(v) {}
  rint (rint const& r) : val(r.val) {}
  rint& operator= (rint const& r) { this->val = r.val; return *this; }
  rint& operator= (unsigned int r) { this->val = r; return *this; }

  unsigned int val;

  // implicit conversion to uint from rint
  operator unsigned int& ()
  {
    return this->val;
  }
  operator unsigned int const& () const
  {
    return this->val;
  }
};

// reads a uints worth of chars into an rint
std::istream& operator>> (std::istream& is, rint& li)
{
  is.read(reinterpret_cast<char*>(&li.val), 4);
  return is;
}

// writes a uints worth of chars out of an rint
std::ostream& operator<< (std::ostream& os, rint const& li)
{
  os.write(reinterpret_cast<const char*>(&li.val), 4);
  return os;
}

int main (int argc, char *argv[])
{
  std::vector<int> V;

  // make sure the file is opened binary & the istream-iterator is
  // instantiated with rint; then use the usual copy semantics
  std::ifstream file(argv[1], std::ios::binary | std::ios::in);
  std::istream_iterator<rint> iter(file), end;
  std::copy(iter, end, std::back_inserter(V));

  for (int i = 0; i < V.size(); ++i)
    std::cout << std::hex << "0x" << V[i] << std::endl;

  // this will reverse the binary file at the uint level (on x86 with
  // g++ this is 32-bits at a time)
  std::ofstream of(argv[2], std::ios::binary | std::ios::out);
  std::ostream_iterator<rint> oter(of);
  std::copy(V.rbegin(), V.rend(), oter);

  return 0;
}
于 2010-06-18T04:08:25.843 に答える
0

主な質問は、おそらく「バイナリファイル」の意味です。オブジェクトがプラットフォーム固有の改行を '\n' に置き換えないios::binaryことを確認するだけです。istream他には何もありません。それで十分ですか?

istream_iterator基本的に、 を呼び出すための凝った方法operator>>です。ストリームに実際のバイナリ データがある場合、それは失敗します。ファイルに実際のバイナリ データがありますか? それとも、整数は文字列として保存されていますか?

実数の 2 進整数を読み取る必要がある場合はistream.read()、ストリーム バッファ オブジェクトを直接使用するか、直接使用する必要があります。

于 2009-07-20T18:13:15.687 に答える
0

operator>> をリロードして、整数を正しく読み取ることができます。もちろん、4 バイトの read() だけです。しかし、それは他のすべてのオペレーター>> が最終的にやっていることです。

ここに例があります(エラーチェックなし、エンディアンが現在のコンパイラの使用と同じであると仮定するなど)

std::istream& operator>>(std::istream& in, uint32_t& data)
{
    in.read(&data, sizeof(data));
    return in;
}

独自の整数のフレーバーに合わせて調整し(一度に1バイトを読み取ってシフト割り当てし、バイトオーダーがわからない場合は16進エディターでファイルを確認する必要がある場合があります)、エラーチェックを追加すると、使用できるはずですあなたの既存のコード。

編集:ああ、はい、このシャドウが整数を読み取るstl演算子を提供していることを確認してください-使用しているストリームから独自のクラスを派生させ、std::istream& inの代わりにそれを使用する必要があるかもしれません。コンパイラが誰をチェックするかを知るためです最初。

于 2009-07-21T05:46:22.657 に答える