• 締切済み

STLで、vectorのファイルへの読み込み。

STLで、vectorのファイルへの読み込み。 先ほどの質問 (http://okwave.jp/qa/q6271982.html) は out.write((char *) &testvector, sizeof(int) * testvector.size()); とすることで解決できたかなと思うのですが (コンパイルが通っただけですが) 、一方で読み込みとなると、read を使うとバイト数の指定が必要となります。しかし可変長配列なので、長さは不定であると考えると、どのように読み込んだらよろしいのでしょうか。書き出す時に vector の長さを書き出しておくとかそういう方法になるのでしょうか。

みんなの回答

回答No.2

read()に1を指定すれば、ファイルから1byteだけ読み出せます。ファイルの終端までループでまわせば、ファイル全体を読み込んだことになりますが、必要なバッファは1バイトで済みます。 >> 書き出す時に vector の長さを書き出しておくとかそういう方法になるのでしょうか。 この方法もありです。 readを呼び出す前にデータ長がわかれば、その分、事前にmalloc()あるいはnewすることで対応します。これなら、ループが必要なくて、プログラムも簡単になりますね。 ただし、エラーチェックは入れてね。 悪意のある人間が、例えば1テラバイトを要求するデータを捏造して、プログラムに与えたときにも対応できるように、上限チェックを入れるとか。

  • sygh
  • ベストアンサー率76% (42/55)
回答No.1

VC++ 2010でテストしています。 出力されたバイナリファイルが、「vector<int>のシリアライズされたものである」、ということが常に保証されているのであれば、まずシークによりファイルサイズを取得して、先頭位置に戻し、再度読み込むようにします。 なお、通例としてバイナリファイルは、ファイルの先頭にファイルヘッダ(たとえばヘッダ情報構造体をシリアライズしたもの)を書き込んでおき、どういうフォーマットで記述されているかを記録しておくのがベターです。 #include <fstream> #include <cstdio> #include <vector> #include <conio.h> using namespace std; bool SaveToFile(const char* fileName) { vector<int> testVec; for (int i = 0; i < 10; i++) { testVec.push_back(i); } ofstream ofs(fileName, ios::binary); if (ofs.fail()) { puts("Failed to save the binary file!"); return false; } ofs.write(reinterpret_cast<const char*>(&testVec[0]), sizeof(int) * testVec.size()); ofs.flush(); if (ofs.fail()) { puts("Failed to save the binary file!"); return false; } else { puts("Succeeded to save the binary file."); return true; } // ofstream はデストラクタで close() を自動的に呼び出してくれます。 } bool LoadFromFile(const char* fileName) { ifstream ifs(fileName, ios::binary); if (ifs.fail()) { puts("Failed to open the binary file!"); return false; } else { puts("Succeeded to open the binary file."); } const size_t fileSize = static_cast<size_t>(ifs.seekg(0, ios::end).tellg()); ifs.seekg(0, ios::beg); // 先頭に戻す。 if (fileSize > 0 && fileSize % sizeof(int) == 0) { // ファイルサイズがゼロでなく、かつ sizeof(int) の倍数である場合。 vector<int> testVec(fileSize / sizeof(int)); ifs.read(reinterpret_cast<char*>(&testVec[0]), fileSize); for (size_t i = 0; i < testVec.size(); i++) { printf("Vec[%03u] = %d\n", static_cast<unsigned>(i), testVec[i]); } } else { // ファイルサイズがゼロであるか、または sizeof(int) の倍数でない場合。 puts("The binary file is invalid format!"); return false; } // ifstream はデストラクタで close() を自動的に呼び出してくれます。 return true; } int main() { const char* fileName = "serialized_vector_int.bin"; if (::SaveToFile(fileName)) { ::LoadFromFile(fileName); } puts("Press any key to exit..."); _getch(); return 0; }

関連するQ&A