1

ヘッダーとデータを含むバイナリ ファイルを (一度に) 読み取る必要があります。C++ でファイルを読み取るにはさまざまな方法がありますが、どの方法が最も高速で信頼性が高いかを知りたいです。reintrerpret_castまた、生データを構造体に変換する最良の方法 かどうかもわかりません。

編集: ヘッダー構造には機能がなく、データのみがあります。

ifstream File(Filename, ios::binary);    // Opens file

if (!File)    // Stops if an error occured
{
    /* ... */
}

File.seekg(0, ios::end);
size_t Size = File.tellg();    // Get size
File.seekg(0, ios::beg);

これは istreambuf_iterator なしの ifstream です

char* Data = new char[Size];

File.read(Data, Size);
File.close();

HeaderType *header = reinterpret_cast<HeaderType*>(Data);

/* ... */

delete[] Data;

これは ifstream WITH istreambuf_iterator です

std::string Data;    // Is it better to use another container type?

Data.reserve(Size);
std::copy((std::istreambuf_iterator<char>(File)), std::istreambuf_iterator<char>(),
          std::back_inserter(Data));

File.close();

const HeaderType *header = reinterpret_cast<HeaderType*>(Data.data());

これもネットで発見

std::ostringstream Data;
Data << File.rdbuf();
File.close();
std::string String = Data.str();

const HeaderType *header = reinterpret_cast<HeaderType*>(String.data());
4

3 に答える 3

1

これは「意見に基づく」ものになるため、SO にとって厳密にはオントポイックではありません。

read()ただし、この場合、関数がより簡潔であるため、イテレータを使用する意味がわかりません。

ただし、より重要なことは、これを行っている方法は厳密なエイリアシング規則に違反していることです。これは、メモリ内のアライメントが配列と一致するstructことが保証されていないためcharです。

structのアドレスを aにキャストするのが常に最善でありchar*、その逆ではありません。

HeaderType header;

File.read(reinterpret_cast<char*>(&header), sizeof(header));
File.close();

このようなバイナリでのデータの読み取りは移植性がなく、複雑なユーザー定義型 ( などstd::string) では機能しないため、すべてのデータ メンバーを書式設定された文字列としてシリアル化することをお勧めします。

注:タイプのエイリアシングについては、reinterpret_cast のドキュメントを参照してください。

于 2015-03-12T17:04:00.897 に答える
0

まず、あなたが説明したソリューションはどれも実際には機能しません。はそれ reinterpret_castを教えてくれるはずです。ある時点で、バッファ内のバイトを解析し、抽出されたデータ フィールドごとに内部データ構造に挿入する必要があります。

できるだけ早くバイトをバッファに入れることに関しては、余分な作業が少ないほど良いです。open最速の方法は、低レベル IO を使用するか ( readUnix で)、ファイルをメモリにマップする ( mmapUnix で) ことです。もちろん、これはシステムに依存します。ifstreamシステムの独立性を達成するためにを使用したい場合は、使用するistream::readのが確かに最速です (そして、すべてのことを考慮すると、最も論理的です)。ストリームが"C"バイナリモードで開かれているだけでなく、ロケールが埋め込まれていることを確認してください。

記録のために: システム レベルの関数を使用すると、データが OS からバッファに直接転送されます。 istream::readの内部バッファーからバッファーにコピーfilebufします (そして、システム レベル関数を使用してデータをバッファーに取得します)。std::string他の 2 つはオブジェクトをバイト単位で構築し、必要に応じてメモリを割り当てます。これは、最終的な長さが分からないためです。

最後に、 ではなくnew char[size]を使用しstd::vector<char>ます。

于 2015-03-12T18:50:36.987 に答える