2
votes

I am trying to read a particular textfile into Matlab, and store only float values into a Matlab matrix. I have found a few different ways to do it, but none work quite the way I want. I think the problem is the formatting of the textfile. Here are the first few lines of the file:

**K = 1, J = 1
37.9072 37.9072 37.872 37.9072 37.9072 37.5572 37.9072
37.9072 37.9172 37.9072 37.962 37.9552 37.9072
37.9222 37.9072 37.9322 37.9072 37.9332 37.9072
** K = 2, J = 1
34.9249 34.9249 34.9349 34.9249 34.9679 34.9249 34.9249
34.9249 34.2439 34.9249 34.9249 34.9249 34.9249
34.9459 34.9249 34.9549 34.9249 34.6749 34.9889
**K = 3, J = 1
37.94501 37.94401 37.94501 37.94501 37.99501 37.96501 37.94501
37.94501 37.94101 37.93301 37.94501 37.94501 37.94501
37.94501 37.90501 37.94501 37.90001 37.94501 37.99801

The issues I am having are that: 1) each number is not separated by a tab, and instead are separated by multiple spaces, and 2) the first row of each line after the '**' contains 7 columns of data, and subsequent rows only contain 6 columns of data. I am able to read the lines I want using tline = fgetl(fid), but how do I then extract the floating values in tline so that I can assign them into a Matlab vector?

Ideally, what I would like to have is for each block of data separated by the '**', the I/O code reads this into a Matlab vector. For example, for the first block K = 1, J = 1, I would have a vector:

vec1 = [37.9072 37.9072 37.9072 37.9072 37.9072 ...]

And then for the second block K = 2, J = 1, I would have:

vec = [37.9429 37.9429 37.9429 37.9429 37.9429 37.9429 ...]

Each vector, vec would be of size [1 19] (ie. 19 data points in each block of data). Below is my attempt at the problem (which is not correct):

fid = fopen('Temp2017-01-01.txt');

m = 1;

while ischar(tline)

if(tline(1) == '*') %to skip lines which start with '*'
    tline = fgetl(fid);
elseif(length(tline) > 112) %to get the line containing 7 columns of data

vec(m, :) = sscanf( tline( 1:end ), '%f,%f,%f,%f,%f,%f,%f' )

else %to get the lines containing 6 columns of data

    vec(m, :) = sscarf(tline(1:end), '%f,%f,%f,%f,%f,%f,%*s' )

end

m = m + 1;

end

fclose(fid);

Any advice would be appreciated. Thanks,

EDIT: I still cannot get this to work even using textscan as Hoki suggested (thanks btw). The error messages I get are: 1) Improper assignment with rectangular empty matrix, and 2) Cannot support cell arrays containing cell arrays or objects. Also, the assignment M = cell2mat(g) returns something like:

NaN NaN NaN NaN NaN NaN NaN NaN 37.9828800000000 NaN NaN NaN NaN NaN NaN NaN 37.9828800000000

I forgot to make it clear that between each float in the sample textfile above, there are 8 spaces. When I do use textscan it returns a cell array of strings. Each string is something like:

'37.9072    37.9072    37.9072       ...'

I would like to extract each of these individual entries into a vector or matrix. Upon reading the errors I get, one explanation is that cell2mat only works for non-string entries. Any further advice is much appreciated.

Thanks,

2

2 Answers

1
votes

The textscan function is your friend (read the doc for more info). Using that :

fid = fopen('Temp2017-01-01.txt');

vec = zeros( 0,19 ) ;
while ~feof(fid)
    l0 = fgetl(fid) ; %// do nothing with that (or extract the K and J if you need them)

    %// this will read as many '%f' numbers it can (19 in your case)
    M = textscan( fid , '%f' , 'delimiter',' ' ) ;

    vec(end+1,:) = cell2mat( M ) ; %// convert them to matrix and add to global result
end

fclose(fid)

Mlint will complain that the matrix vec is growing at each iteration but unless you know in advance the number of block you are going to read you have no choice. Just go with it.

1
votes

If you don't need to know what the values in the ** are, then you can use 'CommentStyle' to make textscan ignore those rows, and let MATLAB figure out the numeric parts (with potential multiple whitespace delimiters in). Then, since you know that each section has 19 values in, do a generic reshape. No loop needed (this works on R2013b with your sample data):

fid = fopen('yourfile.txt')
C = textscan(fid,'%f','CommentStyle','**');
fclose(fid)
C = C{1}; % escaping cell
% reshape to be 19 numbers on each row
C = reshape(C,19,[]); 
C = C';

C(1,:) is now your first set of data, C(2,:) the second set, and so on (easier to loop through if needed).