记一次java读取matlab数据方式

背景,了解一下

目前在做一个有点科研性质的软件项目,应用程序难免要涉及到一些科学计算上相关的东西,而matlab是科学计算领域最常用的工具,这不,刚接到产品经理描述的需求,用户会将matlab产生的结果文件(.mat)上传到系统,系统解析这个结果,然后在网页上展示。虽说最近哈工大被禁用matlab风波一时,大家隐忧不解,但是没有好的替代品前,还是得硬着头皮继续用着(客户不是哈工大,还可以用)。 在接到这样的需求时,首先去确认了下能否实现,随手baidu,出来不少神仙们写的java读取matlab数据的博客,内心放心了一大半,能解决就好。产品经理一听能够解决,心里美滋滋,以最快的速度进行了需求确认->产品设计->评审、并向客户要了份测试数据交了过来,于是那时那刻手里攥着一份.mat数据,对它还一所知。

问题解决思路

接下来就得以科学严谨的态度来解决问题了,大概分这样几步:

  • 找研究算法同事(他们的电脑一般都装有matlab)帮忙打开这个.mat文件,看看它长什么样子(何方妖怪),结果,清秀的像个excel表格。
图1
  • 先了解下matlab,所谓磨刀不误砍柴工。有些道友可能会直接施展CV大法,轻松搞定。但是如果根基薄弱的话,还是不建议这样做,提前了解多一些,还是多少可以减少点后期的问题,而且也能更加从容的应对后续的变化。

  • 动手、尝试与封装

matlab扫盲学习,简单总结

Matlab可以说是一个计算平台,也可以说是一门高级语言,它有着自定义的数据类型,和其他语言相似,也有数值、字符、map等。下图是在后续实现中看到的封装matlab数据类型类的部分截图:

图2

比较疑惑的可能是sparse 和 cell 。sparse是稀疏矩阵,cell 是索引数据容器的数据类型,它是一个数组,只是数组里存放的是其他类型数据的索引。数组和矩阵是matlab总信息和数据的基本表示形式。

通过官网学习是才是扫盲的第一步, 从matlab语言基础知识可以了解到更多数据类型的介绍,比如table类型,还记的.mat打开后清秀的样子吗,大胆猜测产品经理拿来的数据可能就和table有关。

扫盲方式: 先从官网学习,一知半解,然后再实践中对照印证。

动手,尝试过程记录

百度一下清一色 都是使用ujmp-jmatio 来实.mat文件内容的读写,

1. 尝试使用jmatio, 结果失败了。
  • 首先在项目中引入
<dependency>
    <groupId>net.sourceforge.jmatio</groupId>
    <artifactId>jmatio</artifactId>
    <version>1.0</version>
</dependency>
  • 实在读取mat文件,结果报错了
MatFileReader reader = new MatFileReader("QA_table.mat");

Exception in thread "main" java.lang.ClassCastException: com.jmatio.types.MLUInt32 cannot be cast to com.jmatio.types.MLUInt8

ujmp-jmatio 实际上也是引用了jmatio, 再进行了一层封装,尝试使用ujmp-jmatio结果抛了同样的错误,怀疑是不是版本的问题,看了mvnrepository, 只有1.0版本,matlab不同版本数据定义有差异,估计我拿到的文件版本确实不兼容了。 这条路没有再深究下去。

2. 转换为mfl,结果成功了

在github 搜索了一番,找到项目 https://github.com/HebiRobotics/MFL, 引入项目尝试

<dependency>
        <groupId>us.hebi.matlab.mat</groupId>
        <artifactId>mfl-core</artifactId>
        <version>0.5.6</version>
</dependency>
Mat5File file = Mat5.readFromFile("QA_table.mat");
System.out.println(file);

很庆幸,没有再报错了,看看打印出来的结果:

Mat5File{description='MATLAB 5.0 MAT-file, Platform: PCWIN64, Created on: Wed Apr 01 14:52:21 2020', subsysOffset=213, byteOrder=LITTLE_ENDIAN, version=1}
QA_table = 1x1 table
    ndims: 2.0
    nrows: 3.0
    rownames: {}
    nvars: 16.0
    varnames: 1x16 cell
    data: 1x16 cell
    props: 1x1 struct
        Description: ''
        VariableDescriptions: {}
        VariableUnits: {}
        DimensionNames: 1x2 cell
        UserData: []
"" = 1x6600 uint8

从结果可以看出文件有两个主体,一个是name为QA_table的 table, 另一个是name为空串的unit8, 第一个应该就是要读取的主体内容(1x6600 unit8 一时没弄明白是什么含义),MFL库中没有table结构相关的封装类,但是可以直接使用getStruct来获取。

// 使用name 或者索引都可以
Struct struct = file.getStruct("QA_table");
// Struct struct = file.getStruct(0); 

假如要读取图1中filename列中的三行分别的值,先简单分析下file 打印的信息(以下没有任何官方说明,仅为个人推测和实践):

  • ndims: 表示维度,当前为2维数据
  • nrow3: 数据行数,3行,和图1是一致的。
  • nvars: 变量个数,等同于列数
  • varnames: 存放列名
  • data: 存放数据
  • props:表的属性

以下是具体读取信息的代码:

// 首先获取数据, data: 1x16 cell
Cell data = struct.getCell("data");
// 读取cell中第二列 ,就是filename列
Cell filenameValues = data.get(0, 1);
// 打印所有filename 值
for (int i=0; i<3; i++) {
    System.out.println(filenameValues.get(i, 0) .toString());
}

之所以像上面这般读取,是因为给的数据结构是 116 cell数组,数组内元素 是 31 的cell数组;

图3

接来下就是封装工具,将表格转为json数据,提供给业务方调用,具体代码就不贴了。整个过程就是如此,感谢抽空阅读。

参考文档

1、《MatLab数据结构》BlueHeart0621

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343