Как написать / прочитать собственную матрицу из двоичного файла

Для записи Eigen::Matrix в файл мне действительно нравится использовать следующее:

typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix_MxN;
Matrix_MxN J = Matrix_MxN::Zeros(10,10);      
std::ofstream("matrix.txt") << J;

Но, к сожалению, что-то, что может сделать обратное, не определено:

std::ifstream("matrix.txt") >> J;

Чтобы обойти эту проблему, как вы можете вместо этого читать / записывать Eigen::Matrix в двоичный файл?

2 ответа

Вы можете определить эти методы:

namespace Eigen{
template<class Matrix>
void write_binary(const char* filename, const Matrix& matrix){
    std::ofstream out(filename, std::ios::out | std::ios::binary | std::ios::trunc);
    typename Matrix::Index rows=matrix.rows(), cols=matrix.cols();
    out.write((char*) (&rows), sizeof(typename Matrix::Index));
    out.write((char*) (&cols), sizeof(typename Matrix::Index));
    out.write((char*) matrix.data(), rows*cols*sizeof(typename Matrix::Scalar) );
    out.close();
}
template<class Matrix>
void read_binary(const char* filename, Matrix& matrix){
    std::ifstream in(filename, std::ios::in | std::ios::binary);
    typename Matrix::Index rows=0, cols=0;
    in.read((char*) (&rows),sizeof(typename Matrix::Index));
    in.read((char*) (&cols),sizeof(typename Matrix::Index));
    matrix.resize(rows, cols);
    in.read( (char *) matrix.data() , rows*cols*sizeof(typename Matrix::Scalar) );
    in.close();
}
} // Eigen::

и вы можете проверить их использование с:

typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor> Matrix_MxN; 
Matrix_MxN J = Matrix_MxN::Random(10,5);
Eigen::write_binary("matrix.dat",J);
std::cout << "\n original \n" << J << std::endl;
Matrix_MxN J_copy;
Eigen::read_binary("matrix.dat",J_copy);
std::cout << "\n copy \n" << J_copy << std::endl;
cout.flush();'

Если вы знаете лучший способ, предложения приветствуются!

Модификации , чтобы избежать вторжения в пространство имен Eigen, используя zlib для больших матриц.

#include <string>
#include <zlib.h>
#include <Eigen/Core>

namespace myEigen{
template<class Derived>
void write_binary(const std::string &filename,
    const Eigen::PlainObjectBase<Derived> &matrix)
{
    typedef typename Derived::Index Index;
    typedef typename Derived::Scalar Scalar;

    gzFile out = gzopen(filename.c_str(), "wb");
    Index rows=matrix.rows(), cols=matrix.cols();

    gzwrite(out, (char*) (&rows), sizeof(Index));
    gzwrite(out, (char*) (&cols), sizeof(Index));
    gzwrite(out, (char*) matrix.data(), rows*cols*sizeof(Scalar) );
    gzclose(out);
}

template<class Derived>
void read_binary(const std::string &filename,
    Eigen::PlainObjectBase<Derived> &matrix)
{
    typedef typename Derived::Index Index;
    typedef typename Derived::Scalar Scalar;

    gzFile in = gzopen(filename.c_str(), "rb");
    Index rows=0, cols=0;
    gzread(in, (char*) (&rows),sizeof(Index));
    gzread(in, (char*) (&cols),sizeof(Index));
    matrix.resize(rows, cols);
    gzread(in, (char*) matrix.data(), rows*cols*sizeof(Scalar) );
    gzclose(in);
}
} // myEigen::

Я думаю, что в read_binary() метод. Там должно быть in.seekg(0, in.beg); до первого in.read((*char)) линия.

Другие вопросы по тегам