C | 使用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);
}

总结

没啥好说的。如上。

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Qt可以使用matio库读取Matlab格式的.mat文件。 首先,需要下载和安装matio库。可以从matio的官方网站获取最新版本的库:https://sourceforge.net/projects/matio/files/matio/ 在Qt项目中包含matio库的头文件和链接matio库,可以使用以下代码读取.mat文件中的数据: ```cpp #include <matio.h> ... // 打开.mat文件 mat_t *mat = Mat_Open("file.mat", MAT_ACC_RDONLY); if (mat == NULL) { // 文件打开失败 return; } // 获取.mat文件中变量的数量 int num_vars = Mat_VarGetNumberOfVariables(mat); for (int i = 0; i < num_vars; i++) { // 获取.mat文件中第i个变量的名称和数据 matvar_t *matvar = Mat_VarReadNext(mat); if (matvar == NULL) { // 读取变量失败 continue; } // 处理.mat文件中的数据 if (matvar->class_type == MAT_C_DOUBLE) { // 变量类型为双精度浮点型 double *data = (double *)matvar->data; int num_elems = matvar->dims[0]; // 对数据进行处理 ... } // 释放.mat文件中变量的内存 Mat_VarFree(matvar); } // 关闭.mat文件 Mat_Close(mat); ``` 以上代码中,首先使用`Mat_Open`函数打开.mat文件,然后使用`Mat_VarReadNext`函数依次读取.mat文件中的变量。对于每个变量,可以通过`matvar_t`结构体中的`class_type`变量获取其类型,通过`dims`变量获取其维度,通过`data`变量获取其数据。读取完毕后,需要使用`Mat_VarFree`函数释放变量的内存。最后使用`Mat_Close`函数关闭.mat文件。 注意:matio库默认使用C语言的内存分配函数,如果需要在Qt中使用matio库,请在项目中加入以下代码以使用Qt的内存分配函数: ```cpp void *operator new(size_t size) throw(std::bad_alloc) { void *p = malloc(size); if (!p) throw std::bad_alloc(); return p; } void operator delete(void *p) throw() { free(p); } void *operator new[](size_t size) throw(std::bad_alloc) { void *p = malloc(size); if (!p) throw std::bad_alloc(); return p; } void operator delete[](void *p) throw() { free(p); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值