用2种不同的格式创建一个2列矩阵 [英] Create a 2 column matrix with 2 different format types

查看:170
本文介绍了用2种不同的格式创建一个2列矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Matlab非常新,我无法读取二进制文件到矩阵。问题是我想写二进制文件到两列矩阵(其中有100000的行),其中每列是一个不同的格式类型。

我想列1为'int8'格式,第2列为'浮动'



这是我迄今的尝试:

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

这是行不通的,因为我得到错误信息'使用fread错误''无效的精确'

然后我将继续绘图一旦我成功完成了这个任务。



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

感谢任何能够帮助的人。 解决方案

Matlab 不能在矩阵中保存不同的数据类型(它可以在单元格数组中这样做,但这是另一个主题)。所以没有必要一次性读取混合类型的文件,这是不可能的。



除非你想要一个单元格数组,您将不得不使用2个不同类型的2个不同的变量。一旦建立起来,有很多方法可以读取这样的文件。






就这个例子而言,像你所描述的那样创建一个二进制文件。这是这样完成的:

$ $ p $ $ c $%$ //写入示例文件
A = int8(-5:5) ; %//一些int8数据
B =单(linspace(-3,1,11)); %//一些float(= single)数据

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

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



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






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

  %%之后转换为正确类型//一次读取所有数据 - 在
之后转换为正确类型fileID = fopen('testmixeddata.bin');
R = fread(fileID,'uint8 => uint8'); %//读取所有值,最基本的数据类型(无符号8位整数)
fclose(fileID);

R = reshape(R,5,[]); %//将数据整形成一个矩阵(5是因为1 + 4byte =每列5字节)
temp = R(1,:); %//将第一列的数据提取到临时变量(可选)
C = typecast(temp,'int8'); %//转换成int8
temp = R(2:end,:); %//提取第二列的数据
D = typecast(temp(:),'single'); %//转换为single / float

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

我使用的变量只是为了清楚/详细,如果你把你的索引加入到原始数据中,你完全可以避免它。


要理解的关键是使用函数 typecast 。好消息是自从它变得更快2014b




2)逐列阅读(使用skipvalue) - h2>

  %% //逐列读取(使用skipvalue) -  2遍方法
col1size = 1; %//第1列数据的大小(以[字节]为单位)
col2size = 4; %//第2列数据的大小(in [byte])
fileID = fopen('testmixeddata.bin');
C = fread(fileID,'int8 => int8',col2size); %//读取所有的int8值,跳过所有的float

fseek(fileID,col1size,'bof'); %//倒退到文件顶部第2列的开始部分
D = fread(fileID,'single => single',col1size); %//读取所有float值,跳过所有int8
fclose(fileID);

也可以。它工作正常...但可能比上面慢很多。虽然它可能是更清晰的代码来读取其他人...我发现丑陋(,但我已经使用了这种方式好几年,直到我使用上面的方法)。 >




3)元素读取元素



  %% //按元素读取元素(慢 - 不推荐)
fileID = fopen('testmixeddata.bin');
C = []; D = [];
,而〜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 ...请避免! (,最终你的选择




合并一个变量



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

  %% //合并成一个单元格数组 
Data = {C,D};

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


very very new to Matlab and I'm having trouble reading a binary file into a matrix. The problem is I am trying to write the binary file into a two column matrix (which has 100000's of rows) where each column is a different format type.

I want column 1 to be in 'int8' format and column 2 to be a 'float'

This is my attempt so far:

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

This is not working because I get the error message 'Error using fread' 'Invalid Precision'

I will then go on to plot once I have successfully done this.

Probably a very easy solution to someone with matlab experience but I haven't been successful at finding a solution on the internet.

Thanks in advance to anyone who can help.

解决方案

You should be aware that Matlab cannot hold different data type in a matrix (it can do so in a cell array but this is another topic). So there is no point trying to read your mixed type file in one go in one single matrix ... it is not possible.

Unless you want a cell array, you will have to use 2 different variables for your 2 columns of different type. Once this is established, there are many ways to read such a file.


For the purpose of the example, I had to create a binary file as you described. This is done this way:

%% // 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);

This create a 2 column binary file, with first column: 11 values of type int8 going from -5 to +5, and second column: 11 values of type float going from -3 to 1.

In each of the solution below, the first column will be read in a variable called C, and the second column in a variable called D.


1) Read all data in one go - convert to proper type after

%% // 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"

This is my favourite method. Specially for speed because it minimizes the read/seek operations on disk, and most post calculations are done in memory (much much faster than disk operations).

Note that the temporary variable I used was only for clarity/verbose, you can avoid it altogether if you get your indexing into the raw data right.

The key thing to understand is the use of the typecast function. And the good news is it got even faster since 2014b.


2) Read column by column (using "skipvalue") - 2 pass approach

%% // 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);

That works too. It works fine ... but probably much slower than above. Although it may be clearer code to read for someone else ... I find that ugly (and yet I've used this way for several years until I got to use the method above).


3) Read element by element

%% // 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);

Talking about ugly code ... that does work too, and if you were writing C code it would be more than ok. But in Matlab ... please avoid ! (well, your choice ultimately)


Merging in one variable

If really you want all of that in one single variable, it could be a structure or a cell array. For a cell array (to keep matrix indexing style), simply use:

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

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

这篇关于用2种不同的格式创建一个2列矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆