アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

先ほどの質問 (http://oshiete.goo.ne.jp/qa/6271982.html)

out.write((char *) &testvector, sizeof(int) * testvector.size());

とすることで解決できたかなと思うのですが (コンパイルが通っただけですが) 、一方で読み込みとなると、read を使うとバイト数の指定が必要となります。しかし可変長配列なので、長さは不定であると考えると、どのように読み込んだらよろしいのでしょうか。書き出す時に vector の長さを書き出しておくとかそういう方法になるのでしょうか。

A 回答 (2件)

read()に1を指定すれば、ファイルから1byteだけ読み出せます。

ファイルの終端までループでまわせば、ファイル全体を読み込んだことになりますが、必要なバッファは1バイトで済みます。

>> 書き出す時に vector の長さを書き出しておくとかそういう方法になるのでしょうか。
この方法もありです。
readを呼び出す前にデータ長がわかれば、その分、事前にmalloc()あるいはnewすることで対応します。これなら、ループが必要なくて、プログラムも簡単になりますね。

ただし、エラーチェックは入れてね。
悪意のある人間が、例えば1テラバイトを要求するデータを捏造して、プログラムに与えたときにも対応できるように、上限チェックを入れるとか。
    • good
    • 0

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;
}
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!