User Tools

Site Tools


programming:cpp:binary

バイナリ入出力

バイナリ入出力をする方法.
テキスト入出力するよりバイナリ入出力したほうがファイルサイズが小さくなるので使った.
ROOT を使っている限りは気にする必要がないが, emulsion とのデータをやり取りするために必要だった.

このとき,vector のような可変長配列は要素数を保持しておく必要がある.
したがって,ReadMyClassHeader/WriteMyClassHeader という関数を作成し,
単なるメンバ変数とともに vector の要素数を追加で読み書きできるようにしておくことがポイントだと思う.

たとえば以下のようなクラスを考える.

MyClass.hpp
#ifndef MYCLASS_HPP
#define MYCLASS_HPP
 
#include <vector>
 
class MyClass {
public : 
  int var1;
  double var2;
  std::vector<double> vec;
};
#endif

読み取りは以下のように行う.

TestBinaryInput.cpp
#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);
 
}

書き込みは以下のように行う.

TestBinaryOutput.cpp
#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);
 
}
programming/cpp/binary.txt · Last modified: 2022/04/30 17:48 by odagawa