Java - 仅读取.mat文件的部分内容

3
我正在尝试在我的Java应用程序中读取一个.mat文件的一些部分,版本为v7.3。
特别地,我想只加载存储在.mat文件中的某个变量的一些部分。
Matlab支持该文件版本的这个功能,使用命令matfile(更多信息请参见这里)。
我想要实现的一个很好的例子可以在这个答案中找到。
我需要处理的文件包含1xN行,例如字段Date,如您在下面的图片中所见: enter image description here

我找不到任何能够支持.mat v7.3的Java库,但由于该文件版本是基于HDF5的,所以我尝试实现一个将文件视为HDF5文件进行处理的解决方案。 我正在使用JHDF,但我无法确定它是否支持类似matfile的命令。

特别地,我想从Duration字段中提取数据,只有当Date字段具有特定值时。Date包含以升序排列的整数值格式为yyyymmdd的日期。

假设我想在Date = 20230211时读取Duration的数据。我使用JHDF实现了以下代码:

HdfFile hdfFile = new HdfFile(Paths.get("file.mat"));
int[] dateArr = (int[]) hdfFile.getDatasetByPath("/Task/Date").getDataFlat();
if (dateArr.length > 0) {
    int startIdx = 0;
    int finalIdx = dateArr.length - 1;
    for (int i = 0; i < dateArr.length; i++) {
        if (dateArr[i] == 20230211) {
            startIdx = i;
            break;
        }
    }
    for (int i = startIdx + 1; i < dateArr.length; i++) {
        if (dateArr[i] > 20230211) {
            finalIdx = i - 1;
            break;
        }
    }
    float[] duration = (float[]) hdfFile.getDatasetByPath("/Task/Duration").getDataFlat();
    float[] desiredDuration = Arrays.copyOfRange(duration, startIdx, finalIdx + 1);
}

你知道我可以用Java模拟matfile命令吗?

1
你尝试过什么?你应该分享你的代码并请求一个具体的例子。请注意,在Stackoverflow上推荐库是不被接受的话题。 - aled
1
你尝试过什么?你应该分享你的代码并请求一个具体的例子。请注意,在Stackoverflow上,推荐使用库是不符合主题的。 - aled
1
你尝试过什么?你应该分享你的代码并请求一个具体的例子。请注意,在Stackoverflow上,推荐使用库是不被接受的话题。 - undefined
1
嗨,我是jhdf开发者,很乐意提供帮助。我对你的文件结构和你想要打开的部分不太清楚。也许你可以尝试在HDFView中打开一个示例文件,然后将树添加到问题中,或者在GitHub上提交一个问题。看到一个示例文件会非常有帮助。我应该在文档中添加一个示例,但你可以尝试查看Dataset#getData(long[] sliceOffset, int[] sliceDimensions)这个方法,它可以读取数据集的一部分。 - James Mudd
1
嗨,我是jhdf开发者,很乐意提供帮助。对于您的文件结构和您想要打开的部分,我还不太清楚。也许您可以尝试在HDFView中打开一个示例文件,然后将树添加到问题中,或者在GitHub上提交一个问题。看到一个示例文件会非常有帮助。我应该在文档中添加一个示例,但您可以尝试查看Dataset#getData(long[] sliceOffset, int[] sliceDimensions),它可以读取数据集的一部分。 - James Mudd
显示剩余8条评论
2个回答

1
根据您的用例标题和描述,似乎您需要使用HDF5点或超平面选择来部分读取数据(即其中的某些部分)。
如果您没有特定的HDF5库限制,您可以尝试使用HDFql,这是一种高级(声明式)编程语言,用于管理HDF5数据。下面是使用Java示例来说明前述类型的选择。
// create a chunked dataset named 'dset' of type int with one dimension (size 1000) 
HDFql.Execute("CREATE CHUNKED DATASET dset AS INT(1000)");

// read element stored in position #50 of 'dset' using a point selection
HDFql.Execute("SELECT FROM dset(49)");

// read elements stored in positions #100 and #200 of 'dset' using a point selection
HDFql.Execute("SELECT FROM dset(99; 199)");

// read elements stored in positions #50 through #70 of 'dset' using an (regular) hyperslab selection
HDFql.Execute("SELECT FROM dset(49:::20)");

// read elements stored in positions #10 through #20 and positions #200 through #500 of 'dset' using an (irregular) hyperslab selection
HDFql.Execute("SELECT FROM dset(9:::10 OR 199:::300)");

如何在Spring Boot应用程序中导入HDFql? - A M
如何在Spring Boot应用程序中导入HDFql? - A M

0

1.-

如果使用matfile创建了.mat文件,并且将'Writable'设置为false,那么你需要做的是
matfile(filename,'Writable',true)

否则filename是只读的。
如果.mat文件是这样创建的。
hm=matfile('filename.mat')

hm 是对这个新创建的 .mat 文件的句柄,然后使用 'Writable' 状态进行检查。

m.Properties.Writable

2.-

在下面的链接中,您将发现在Mathworks上精确地与.mat文件进行接口的产品被称为MATLAB builder JA

https://uk.mathworks.com/support/search.html/answers/100293-how-can-i-read-mat-files-from-java.html?fq%5B%5D=asset_type_name:answer&fq%5B%5D=category:compiler_sdk/java_packages&page=1

3.-

如果它不是'可写',且MATLAB builder JA超出范围,则我刚提供的链接中的相同问题的答案指向使用C/C++下降并编写自己的函数来连接MATLAB LIBMAT和JNI API。
对于2.-或3.-,您都需要MATLAB Compiler。
额外评论
在此页面中

https://uk.mathworks.com/help/matlab/matlab_external/list-of-examples.html

你将在这里找到可以从JAVA中使用的C语言函数链接,用于导入.mat文件。

然而,由于Mathworks有一个名为Builder JA的工具箱专门用于此目的,可能您需要修改我在答案中提供的最后一个链接中的免费函数,或者添加一些内容,这是在Builder JA工具箱中已经解决的问题。

为什么不安装免费试用Builder JA 30天,并评估您是否真正需要Builder JA呢?

然后您就可以考虑是否保留Builder JA,并付费购买,或者选择自己动手的选项。


如果我理解正确的话,你建议我使用MATLAB Builder JA或者使用MATLAB LIBMAT编写自己的库。 - A M
如果我理解正确的话,你建议我使用MATLAB Builder JA或者编写自己的库来使用MATLAB LIBMAT。 - A M
如果我理解正确的话,你建议我使用MATLAB Builder JA或者使用MATLAB LIBMAT编写自己的库。 - undefined
我已经添加了一个额外的注释来回答这个问题。 - John BG
我已经添加了一个额外的评论来回答这个问题。 - John BG
我已经添加了一个额外的评论来回答这个问题。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接