Skip to content

Instantly share code, notes, and snippets.

@KmolYuan
Created July 17, 2020 12:13
Show Gist options
  • Save KmolYuan/7cdaa3315a42433e692b6f3a65e35005 to your computer and use it in GitHub Desktop.
Save KmolYuan/7cdaa3315a42433e692b6f3a65e35005 to your computer and use it in GitHub Desktop.
Save structure to a binary file.
#include <cstdio>
#include <fstream>
#include <iostream>
#include <tuple>
#include <vector>
using namespace std;
using array1d = vector<double>;
using array2d = vector<array1d>;
using array3d = vector<array2d>;
// Avoid duplicate naming
namespace {
const auto FILE_NAME = "data.bin";
// Get the shape of arrays
tuple<size_t, size_t, size_t> get_shape(array3d &vec) {
return {vec.size(), vec[0].size(), vec[0][0].size()};
}
// Copy vector into an 1d pointer
double *dump_3d(array3d &vec, size_t ind1d, size_t ind2d, size_t ind3d) {
auto ptr = new double[ind1d * ind2d * ind3d];
for (auto i = 0u; i < ind1d; i++)
for (auto j = 0u; j < ind2d; j++)
for (auto k = 0u; k < ind3d; k++)
ptr[(i * ind2d + j) * ind3d + k] = vec[i][j][k];
return ptr;
}
// load 1d pointer to a vector
void load_3d(const double *ptr, array3d &vec, size_t ind1d, size_t ind2d,
size_t ind3d) {
array3d vec_new(ind1d, array2d(ind2d, array1d(ind3d)));
for (auto i = 0u; i < ind1d; i++)
for (auto j = 0u; j < ind2d; j++)
for (auto k = 0u; k < ind3d; k++)
vec_new[i][j][k] = ptr[(i * ind2d + j) * ind3d + k];
// Swap to current vector
vec.swap(vec_new);
}
} // namespace
// Simple data format without array
struct Base {
int age = 0;
};
// Full data format in calculation
struct Student : Base {
// Array data (dynamic space)
array3d grades;
// Data creation (blank)
Student() : Base{} { grades = {}; }
// Create from a base class pointer
explicit Student(Base *me) : Base(*me) { grades = {}; }
};
int main() {
// Try to delete cache file if exist
remove(FILE_NAME);
size_t ind1d, ind2d, ind3d;
{
// Get dynamic dimension
array3d example_array = {{{0, 0, 0}, {0, 0, 0}}, {{0, 0, 0}, {0, 0, 0}}};
auto size3d = get_shape(example_array);
// C++17
// auto [ind1d, ind2d, ind3d] = get_array3d_size(student.grades);
ind1d = get<0>(size3d);
ind2d = get<1>(size3d);
ind3d = get<2>(size3d);
}
size_t array3d_size = ind1d * ind2d * ind3d;
ofstream output_file(FILE_NAME, ios::binary | ios::out);
double *tmp;
for (auto i = 0; i < 500; i++) {
// Calculation
// Data creation -> delete after current step
Student student;
student.age = (20 + i) % 90;
student.grades = {{{1, 2, 3}, {4, 5, 6}}, {{7, 8, 9}, {10, 11, 12}}};
// Transfer members create from the method
tmp = dump_3d(student.grades, ind1d, ind2d, ind3d);
// Write by base size
output_file.write((char *)&student, sizeof(Base));
// Write array data
output_file.write((char *)tmp, sizeof(double[array3d_size]));
// Clear cache
delete tmp;
}
output_file.close();
ifstream input_file(FILE_NAME, ios::binary | ios_base::in);
auto buffer = new Base;
auto id = 0u;
// Read until next character is the end of file (EOF)
while (input_file.peek() != EOF) {
// Read basic data
input_file.read((char *)buffer, sizeof(Base));
// Require space to save array data
tmp = new double[array3d_size];
// Read array data
input_file.read((char *)tmp, sizeof(double[array3d_size]));
// Re-build class from Base buffer
Student student(buffer);
// Load array from pointer
load_3d(tmp, student.grades, ind1d, ind2d, ind3d);
// Clear cache (grades is transferred)
delete tmp;
// Show data
cout << "ID: " << id++ << endl;
cout << "Age: " << buffer->age << endl;
cout << "Grades:";
for (auto &iter1d : student.grades)
for (auto &iter2d : iter1d) {
for (auto elem : iter2d)
cout << " " << elem;
cout << ";";
}
cout << endl;
}
delete buffer;
input_file.close();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment