C ++ |如何格式化和导出由二维矩阵组成的简单二进制文件

时间:2014-04-19 01:24:59

标签: c++ matlab file binary format

我需要导出非常大的矩阵,它可以具有各种尺寸(100x10,1000000x4,100000x100)到格式化的二进制文件中,该文件将携带如何划分列的信息。然后将此文件加载到Matlab中以获得一些绘图结果。

到目前为止,我在我的一个I类函数(其他地方定义的文件构造函数)中使用了如下的简单ASCII导出:

void file_io::writeColData(vector< vector<double> >* data){
    for(unsigned int i = 0;i < (*data).size();i++){
        for(unsigned int j = 0;j < (*data)[i].size();j++){
                file << (*data)[i][j] << '\t';
        }
        file << '\n';
    }
}

使用完整格式化打印一个很好的文件,只需将其作为load(file.txt);加载到Matlab中。一切都很好,矩阵被保留下来,除了它令人难以置信和痛苦地缓慢。

我设法在二进制文件中工作的只是导出一个简单的向量:

void file_io::writeColDataBin(vector<double>* data){
    for(unsigned int i = 0;i < (*data).size();i++){
        file.write(reinterpret_cast<const char*>(&(*data)[i]), sizeof((*data)[i]));
    }
}

我可以对上面的void函数应用另一个维度,但是我无法设置格式化输出 - 我得到的只是一个长列数据(我需要更多的列,数量取决于具体情况)。

我知道我可以包含一些Matlab库(我正在使用Eclipse IDE),但我认为这对我的需求来说只是一个大的过度杀戮,没有提到我几乎无法让它工作的事实痛苦的时刻。我所知道的另一个库是MAT IO(matio.h),但我也无法使用它。

导出后,我需要将其导入Matlab,可能是

fid = ('data.dat','r','l');
data = fopen(fid,'double');

(希望)显示我需要的矩阵。

有没有办法实现这个目标?一个非常简单,简单的方式?

提前致谢!

2 个答案:

答案 0 :(得分:1)

到目前为止,您对二进制输出数组数据的尝试看起来还不错。但是,您还需要在数据之前写入数组维度(行,列)。然后,假设这些数字被写入例如作为C ++中的uint64_t,您可以在matlab中读取文件,如下所示:

function matrix = load_2d(filename, data_type)

    fid = fopen(filename, 'rb');
    rows = fread(fid, 1, 'uint64');
    cols = fread(fid, 1, 'uint64');
    matrix = fread(fid, [rows cols], data_type);
    fclose(fid);

end

其中data_type是与{C ++中的数据类型对应的matlab data type的字符串表示形式。

由于您使用vector vectors代表您的矩阵(每个内部vector持有一列),这仅在所有内部向量具有相同大小时才有效。否则,您需要单独编写每列的大小(行)并相应地调整load_2d。但如果目标是单个2d矩阵,则必须以某种方式截断。

同样,要保存回来:

function save_2d(filename, matrix, data_type)

    fid = fopen(filename, 'wb');
    [rows, cols] = size(matrix);
    fwrite(fid, rows, 'uint64');
    fwrite(fid, cols, 'uint64');
    fwrite(fid, matrix, data_type);
    fclose(fid);

end

我还没有测试过。

答案 1 :(得分:0)

所以我最终使输出满足了我的需求。结果与iavr写的非常相似(感谢您的快速回复!),但是我会复制我的完整(工作)代码,这样对其他人也有好处。

这是编写数据的类file_io的我的函数:

void file_io::writeColDataBin(vector< vector<double> >* data){
    double rows = (double)(*data).size();
    double cols = (double)(*data)[0].size();
    file.write(reinterpret_cast<const char*>(&rows), sizeof(rows));
    file.write(reinterpret_cast<const char*>(&cols), sizeof(cols));
    for(unsigned int j = 0;j < (*data)[0].size();j++){
        for(unsigned int i = 0;i < (*data).size();i++){
            file.write(reinterpret_cast<const char*>(&(*data)[i][j]), sizeof((*data)[i][j]));
        }
    }
}

它首先简单地写入行数和列数,然后继续正常运行,然而在每列中首先按行写入矩阵的单元格,然后移动到下一列。这很重要,因为Matlab按列而不是行来命令它的fread。行和列的大小也被转换为double,因此Matlab可以立即读取整个文件。

同一个类还会打开ofstream file的文件:

void file_io::fileOpenBin(const char* fileName){
    file.open(fileName, ios::out | ios::binary | ios::trunc);
}

在此之后,矩阵被导出并加载到Matlab中:

fid = fopen('data.dat','r');
data = fread(fid,'double');
fclose(fid);
rows = data(1);
cols = data(2);
data(1:2) = [];
data = reshape(data,rows,cols);

导入行和列,然后从数据中删除前两个单元格,然后将它们重新整形为所需的矩阵。

希望这对未来的某些人有所帮助,它可能不是最快的二进制读取过程,但它肯定比读取ASCII快许多倍。