使用2种不同的格式类型创建2列矩阵

时间:2015-08-14 12:24:37

标签: matlab matrix types formatting

对于Matlab来说非常新,我在将二进制文件读入矩阵时遇到了麻烦。问题是我试图将二进制文件写入两列矩阵(其中包含100000行),其中每列是不同的格式类型。

我希望第1列位于' int8'格式和第2列是' float'

这是我到目前为止的尝试:

FileID= fopen ('MyBinaryFile.example');
[A,count] = fread(FileID,[nrows, 2],['int8','float']) 

这不起作用,因为我收到错误消息'错误使用fread' '无效精度'

一旦我成功完成了这一点,我将继续绘制。

对于有matlab经验的人来说,这可能是一个非常简单的解决方案,但我还没有成功地在互联网上找到解决方案。

提前感谢任何可以提供帮助的人。

1 个答案:

答案 0 :(得分:3)

你应该知道Matlab 不能在矩阵中保存不同的数据类型(它可以在cell array中这样做,但这是另一个主题)。因此,尝试在一个矩阵中一次性读取混合类型文件是没有意义的......这是不可能的。

除非您需要cell array,否则您必须为2列不同类型使用2个不同的变量。一旦建立,有很多方法可以读取这样的文件。

出于示例的目的,我必须按照您的描述创建二进制文件。这样做是这样的:

%% // write example file
A = int8(-5:5) ;                 %// a few "int8" data
B = single(linspace(-3,1,11)) ;  %// a few "float" (=single) data

fileID = fopen('testmixeddata.bin','w');
for il=1:11
    fwrite(fileID,A(il),'int8');   
    fwrite(fileID,B(il),'single');   
end
fclose(fileID);

这创建了一个2列二进制文件,第一列:类型为int8的11个值从-5到+5,第二列:类型为float的11个值从-3到1。

在下面的每个解决方案中,第一列将在名为C的变量中读取,第二列将在名为D的变量中读取。

1)一次读取所有数据 - 在

之后转换为正确的类型
%% // Read all data in one go - convert to proper type after
fileID = fopen('testmixeddata.bin');
R = fread(fileID,'uint8=>uint8') ;       %// read all values, most basic data type (unsigned 8 bit integer)
fclose(fileID);

R = reshape( R , 5 , [] ) ;             %// reshape data into a matrix (5 is because 1+4byte=5 byte per column)
temp = R(1,:) ;                         %// extract data for first column into temporary variable (OPTIONAL)
C = typecast( temp , 'int8' ) ;         %// convert into "int8"
temp = R(2:end,:) ;                     %// extract data for second column
D = typecast( temp(:) , 'single' ) ;    %// convert into "single/float"

这是我最喜欢的方法。特别是速度,因为它最大限度地减少了磁盘上的读/写操作,大多数后期计算都在内存中完成(比磁盘操作快得多)。

请注意,我使用的临时变量仅用于清晰/详细,如果您正确索引原始数据,则可以完全避免它。

要理解的关键是使用typecast功能。好消息是it got even faster since 2014b

2)逐列阅读(使用" skipvalue") - 2通过方法

%% // Read column by column (using "skipvalue") - 2 pass approach
col1size = 1 ;                                  %// size of data in column 1 (in [byte])
col2size = 4 ;                                  %// size of data in column 2 (in [byte])
fileID = fopen('testmixeddata.bin');
C = fread(fileID,'int8=>int8',col2size) ;       %// read all "int8" values, skipping all "float" 

fseek(fileID,col1size,'bof') ;                  %// rewind to beginning of column 2 at the top of the file
D = fread(fileID,'single=>single',col1size) ;   %// read all "float" values, skipping all "int8" 
fclose(fileID);

也有效。它工作得很好......但可能比上面慢得多。虽然为其他人阅读可能更清晰的代码......我觉得这很难看(但我已经用这种方式好几年了,直到我使用上面的方法)。 / p>

3)逐个元素地读取

%% // Read element by element (slow - not recommended)
fileID = fopen('testmixeddata.bin');
C=[];D=[];
while ~feof(fileID)
    try
        C(end+1) = fread(fileID,1,'int8=>int8') ;
        D(end+1) = fread(fileID,1,'single=>single') ;
    catch
        disp('reached End Of File')
    end
end
fclose(fileID);

谈论丑陋的代码......它确实有用,如果你正在编写C代码,那就不错了。但是在Matlab中......请避免! (嗯,你的选择最终

合并一个变量

如果真的想要在一个变量中使用所有这些变量,它可以是结构或单元格数组。对于单元格数组(保持矩阵索引样式),只需使用:

%% // Merge into one "cell array"
Data = { C , D } ;

Data = 
    [11x1 int8]    [11x1 single]