C | 使用C语言读取.mat文件
用C语言读.mat文件
目录
前言
故事的开始,是一个菜鸡要开始做毕设。然后…为了实现用C语言度MATLAB的.mat文件,大概划了半个月的水…现在交完毕设终稿,就来整理一下啦!(虽然我猜后面可能也不一定要用C读.mat了23333)
划水心路历程如下:stage1.先花了2-3天时间到处搜罗优秀网友们实现用C读取mat文件的实例,然后发现了matio;stage2.花了一个星期去调matio并且没有成功(;stage3.利用stage2的不完全版本算是实现了使用C读取.mat的目的。
平台:MATLAB(生成.mat文件),Visual Studio 2022
语言:MATLAB,C语言
一、使用matio读取.mat文件
matio是一个读取.mat文件的开源代码。
官网里的东西还挺多的,除了各个版本的代码外,也有关于matio使用的user_guide(我后面基于调试matio的半成品实现功能,也有一部分是参考了这一份说明。)
具体调试过程此处先挖坑,反正也是基于大佬博客的帮助,最后也是没有调处来orz。要是后面有心情的话再填坑= =(毕竟我不太记得了)
以及确实是有很多人通过matio实现了这个功能(羡慕.jpg),但很多人里面都没有本菜鸡就是了hhh。毕竟自从大一也不怎么认真地学完C语言后,基本就没认真学过软件的编程了。
1. matio_user_guide章节设置
1. Introduction
// 大概是对matio的介绍吧
2. Quick Start
// 关于如何用matio实现想要的功能的介绍,大致包括:打开/创建mat文件;读写mat文件
2.1 Opening and Creating MAT Files
2.2 Reading Variables in a MAT File
2.3 Writing Variables
3. Building matio
// 大概是关于在各个平台如何使用matio的介绍
3.1 Quick Build Guide
3.2 Configure Options
3.3 CMake build system
3.4 Visual Studio
3.5 Testsuite
4. MATLAB Variable
// 对可以读取的数据类型进行介绍。
// double; matrix; cell; struct
2. 下载地址
matio下载地址: matio下载官网
hdf5 下载地址: hdf5下载官网
二、利用库文件在其他工程实现读取.mat
可读取类型:double、matrix、cell、struct
1.导入库和头文件
关于Visual Studio如何导入外部库,因为有很多这方面的教程,这里先不多说。
(依然是挖个坑,万一哪天打算填坑呢?
#include "matio.h"
#pragma comment(lib,"libmatio.lib")
#pragma comment(lib,"zlib.lib")
#pragma comment(lib,"hdf5.lib")
#pragma comment(lib,"libhdf5.lib")
其中,zlib和hdf5主要是是在使用特殊格式的.mat文件时使用。
如果要使用的只是普通的.mat文件,可以忽略这几个库(实测没有问题)。
关于特殊格式的.mat文件,官方文档的说法是:
m a t i o matio matio库可以创建 v e r s i o n _ 4 version\_4 version_4的MAT文件, v e r s i o n _ 5 version\_5 version_5的MAT文件,带有可变压缩的 v e r s i o n _ 5 version\_5 version_5的MAT文件(使用zlib构建),引入HDF5格式的MAT文件。(但是本人并没有研究过.mat这种格式的文件)
2. 打开mat文件
- 如何创建一个新的MAT 文件; Mat_CreatVer
- 如何打开一个存在的MAT文件并进行读写访问; Mat_Open
- 如何关闭一个MAT文件。 Mat_Close
打开.mat文件的代码如下(以打开"xxx.mat"文件为例):
(创建MAT文件的代码可见官方文档)
void LoadStarData(void) {
// step1: 打开MAT文件
mat_t* matfp;
const char* file; // MAT文件名
file = "xxx.mat"; // 打开工程路径下的.mat文件
matfp = Mat_Open(file, MAT_ACC_RDONLY);
if (NULL == matfp) {
printf("Error opening MAT file %s!\n", file);
}
// step2: 读取MAT文件中保存的数据(double、matrix、cell、struct)
// ``````
// step3: 关闭MAT文件
Mat_Close(matfp);
}
其中,读取数据的部分在step2位置进行,将在文章后面介绍。
3. 读取matrix类型
此处先说明:因为本人属实菜得一批,所以虽然知道一般情况下声明结构体之类的变量后都需要划空间,但属实不太会操作= =。同时本人的指针也学得一塌糊涂= =。希望等后面重新自学了C语言后可以更新一下代码吧QAQ
读取matrix类型的数据(以打开xxx.mat里名为test的数组为例,test为3x3数组)
void LoadStarData(void) {
// step1: 打开MAT文件
// ``````见2.1
// step2: 读取MAT文件中保存的数据(double、matrix、cell、struct)
matvar_t* matvar_var = NULL;
matvar_var = Mat_VarRead(matfp, "test"); // 读取变量数值与信息
if (!matvar_var) {
printf("Error read MatVar: test!\n");
return -1;
}
int iDataN = matvar_var->nbytes / matvar_var->data_size; // 获取矩阵的大小
double* dI = (double*)malloc(iDataN * sizeof(double)); // 分配内存 // 不知道用法对不对hhh
memset(dI, 0, iDataN * sizeof(double));
if (matvar_var->data_type == MAT_T_DOUBLE) { // 判断数据类型是否是double
const double* xData_I = (const double*)(matvar_var->data); // 将data的值给xData_I
for (int i = 0; i < iDataN; ++i) {
printf("test[%d] = %lf\n", i, xData_I[i]);
/*
test[0] test[3] test[6]
test[1] test[4] test[7]
test[2] test[5] test[8]
*/
}
memcpy(dI, xData_I, iDataN * sizeof(double));
}
// step3: 关闭MAT文件
Mat_VarFree(matvar_var);
Mat_Close(matfp);
}
结构体matvar_t
将包含以下信息:(具体说明可查看官方文档4.1节)
name | The name may be NULL, so the field should be checked prior to use.
rank | The minimum rank is 2.
dims |
class_type | Indicates the class of variable(e.g. double-precision, structure, cell, etc)
data_type | Indicates the type of data stored in the data field of the MATLAB variable structure.
isComplex |
isLogical | is non-zero of the variable should be interpreted as logical.
isGlobal |
4. 读取struct类型
同2.3处声明:本人是菜鸡,代码随缘看= =
读取struct类型数据(以读取xxx.mat文件中的test2结构体数组为例。test2结构体有两个元素,读取其中的data1(数组类型))
void LoadStarData(void) {
// step1: 打开MAT文件
mat_t* matfp;
const char* file; // MAT文件名
file = "xxx.mat";
const int column = 2; // MAT文件对应的struct的元素数量。
matfp = Mat_Open(file, MAT_ACC_RDONLY);
if (NULL == matfp) {
printf("Error opening MAT file %s!\n", file);
}
// step2: 读取MAT文件中保存的数据(double、matrix、cell、struct)
matvar_t* structvar_patr = NULL, * data1 = NULL; // 初始化保存数据的指针
structvar_patr = Mat_VarRead(matfp, "test2");
if (!structvar_patr) {
printf("Error read MatVar: test2!\n");
}
else if (structvar_patr->data_type == MAT_T_STRUCT) { // 判断读取到的内容是否为结构体
const int list_length = structvar_patr->nbytes / structvar_patr->data_size / column; // list_length*1 struct
for (i = 0; i < list_length; i++) {
data1 = Mat_VarGetStructFieldByName(structvar_patr, "data1", i); // 以变量名读数据,也有其他读数据的模式。
if (data1 ) {
const double* xData_star = (const double*)(data1->data);
const int iDataN = data1->nbytes / data1->data_size; // data1数组的长度
for (j = 0; j < iDataN; j++) {
A[i].B[j] = xData_star[j]; // 随缘
}
}
}
}
Mat_VarFree(data1); // 释放空间,关闭文件
Mat_VarFree(structvar_patr);
Mat_Close(matfp);
}
总结
没啥好说的。如上。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)