我需要导出非常大的矩阵,它可以具有各种尺寸(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');
(希望)显示我需要的矩阵。
有没有办法实现这个目标?一个非常简单,简单的方式?
提前致谢!
答案 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快许多倍。