0

I have a text file (lets call it an input file) of this type:

%My kind of input file % Comment 1 % Comment 2

4 %Parameter F

2.745 5.222 4.888 1.234 %Parameter X

273.15 373.15 1 %Temperature Initial/Final/Step

3.5 %Parameter Y

%Matrix A

1.1 1.3 1 1.05

2.0 1.5 3.1 2.1

1.3 1.2 1.5 1.6

1.3 2.2 1.7 1.4

I need to read this file and save the values as variables or even better as part of different arrays. For example by reading I should obtain Array1.F=4; then Array1.X should be a vector of 3 real numbers, Array2.Y=3.5 then Array2.A is a matrix FxF. There are tons of functions to read from text file but I don't know how to read these kind of different formats. I've used in the past fgetl/fgets to read lines but it reads as strings, I've used fscanf but it reads the whole text file as if it is formatted all equally. However I need something to read sequentially with predefined formats. I can easily do this with fortran reading line by line because read has a format statement. What is the equivalent in MATLAB?

Long Luong
  • 764
  • 2
  • 14
  • 28
ECrespo
  • 135
  • 1
  • 1
  • 8
  • [`textscan`](https://www.mathworks.com/help/matlab/ref/textscan.html#inputarg_N) allows you to read a specified number of lines, which does not rewind the file pointer. This allows for sequential reads with different format specifications. – sco1 Dec 29 '17 at 14:55
  • I am not fully understanding what you mean by "which does not rewind the file pointer" can you explain it better to me? Moreover, in C = textscan(FID,'FORMAT',N) reads data from the file, using the FORMAT N times, where N is a positive integer. To read additional data from the file after N cycles, call textscan again using the original FID. is the N parameter who tells the number of lines? like N=1 to read line by line? – ECrespo Dec 29 '17 at 15:56

1 Answers1

0

This actually parses the file you posted in your example. I could've done better, but I'm tired today:

res = struct();

fid = fopen('test.txt','r');
read_mat = false;

while (~feof(fid))
    % Read text line by line...
    line = strtrim(fgets(fid));

    if (isempty(line))
        continue;
    end

    if (read_mat) % If I'm reading the final matrix...
        % I use a regex to capture the values...
        mat_line = regexp(line,'(-?(?:\d*\.)?\d+)+','tokens');

        % If the regex succeeds I insert the values in the matrix...
        if (~isempty(mat_line))
            res.A = [res.A; str2double([mat_line{:}])];
            continue; 
        end
    else % If I'm not reading the final matrix...
        % I use a regex to check if the line matches F and Y parameters...
        param_single = regexp(line,'^(-?(?:\d*\.)?\d+) %Parameter (F|Y)$','tokens');

        % If the regex succeeds I assign the values...
        if (~isempty(param_single))
            param_single = param_single{1};
            res.(param_single{2}) = str2double(param_single{1});
            continue; 
        end

        % I use a regex to check if the line matches X parameters...
        param_x = regexp(line,'^((?:-?(?:\d*\.)?\d+ ){4})%Parameter X$','tokens');

        % If the regex succeeds I assign the values...
        if (~isempty(param_x))
            param_x = param_x{1};
            res.X = str2double(strsplit(strtrim(param_x{1}),' '));
            continue; 
        end

        % If the line indicates that the matrix starts I set my loop so that it reads the final matrix...
        if (strcmp(line,'%Matrix A'))
            res.A = [];
            read_mat = true;
            continue;
        end
    end
end

fclose(fid);
Tommaso Belluzzo
  • 23,232
  • 8
  • 74
  • 98
  • Many thanks for the help, as there are lines that are unknown to me, will it be too much to ask if you can edit and add just a couple of comments per section explaining what you are doing in each section? – ECrespo Dec 30 '17 at 15:36