バイナリ入出力をする方法.
テキスト入出力するよりバイナリ入出力したほうがファイルサイズが小さくなるので使った.
ROOT を使っている限りは気にする必要がないが, emulsion とのデータをやり取りするために必要だった.
このとき,vector のような可変長配列は要素数を保持しておく必要がある.
したがって,ReadMyClassHeader/WriteMyClassHeader
という関数を作成し,
単なるメンバ変数とともに vector の要素数を追加で読み書きできるようにしておくことがポイントだと思う.
たとえば以下のようなクラスを考える.
#ifndef MYCLASS_HPP #define MYCLASS_HPP #include <vector> class MyClass { public : int var1; double var2; std::vector<double> vec; }; #endif
読み取りは以下のように行う.
#include <fstream> #include <string> #include <vector> #include <iomanip> #include "MyClass.hpp" bool ReadMyClassHeader(std::ifstream &ifs, MyClass myclass, int &vec_size) { if (!ifs.read((char*)& myclass.var1, sizeof(int))) return false; if (!ifs.read((char*)& myclass.var2, sizeof(double))) return false; if (!ifs.read((char*)& vec_size, sizeof(int))) return false; return true; } int main() { std::string filename = "test.bin"; std::ifstream ifs(filename, std::ios::binary); std::vector<MyClass> vec_myclass; MyClass myclass; int vec_size = 0; while ( ReadMyClassHeader(ifs, myclass, vec_size) ) { // ここで vector 以外の読み取りが終わっている myclass.vec.clear(); myclass.vec.reserve(vec_size); for ( int i = 0; i < vec_size; i++ ) { double tmp; ifs.read((char*)& tmp, sizeof(double)); myclass.vec.push_back(tmp); } vec_myclass.push_back(myclass); } for ( auto imyclass : vec_myclass ) { // 適当な処理 } std::exit(0); }
書き込みは以下のように行う.
#include <fstream> #include <string> #include <vector> #include <iomanip> #include "MyClass.hpp" void WriteMyClassHeader(std::ofstream &ofs, MyClass myclass) { int vec_size = myclass.vec.size(); ofs.write((char*)& myclass.var1, sizeof(int)); ofs.write((char*)& myclass.var2, sizeof(double)); ofs.write((char*)& vec_size, sizeof(int)); } int main() { std::string filename = "test.bin"; std::ofstream ofs(filename, std::ios::binary); std::vector<MyClass> myclass_vector; // myclass vector を適当に作成 if ( !ofs ) { std::cerr << "File : " << filename << " not found." << std::endl; std::exit(1); } else if ( myclass_vector.empty() ) { std::cerr << "Data null" << std::endl; std::exit(1); } else { for ( auto myclass : myclass_vector ) { WriteMyClassHeader(ofs, myclass); for ( auto ivec : myclass.vec ) { ofs.write((char*)& ivec, sizeof(double)); } } } std::exit(0); }