Create a 2 column matrix with 2 different format types

我们两清 提交于 2019-12-13 02:15:28

问题


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.


回答1:


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]


来源:https://stackoverflow.com/questions/32010039/create-a-2-column-matrix-with-2-different-format-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!