matlabtext-filesscanftextscan

MATLAB - Read Textfile (lines with different formats) line by line


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?


Solution

  • 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);