Search code examples
matlabimporttext-files

Trouble Reading in .txt File


I have a text file I'd like to read in in MATLAB. Here is aforementioned text file (text_a2p.txt):

object index_image.nii

plane transverse

range 100 150

factor 3.1415926535897

coeff .0001 .0004 -.0006

As you can see, it's not vertically oriented like most tables (honestly I wouldn't even really call it a table). It also contains both strings and doubles in varying amounts, which throws pretty much every method I've tried completely off-kilter.

The word that begins each line specifies what comes after it (ex. the last line contains the coefficients for a polynomial fit generated by the code). Those specifying words don't actually count as data, and won't end up being processed, they just help to clarify. They could serve as the names of the variables the data is stored in, however.

Unfortunately, the general format of the text file is fixed. It is also worth mentioning that 'object' and 'plane' will always only have one string after them, and 'factor' will always have one number after it, but there could be any number of range pairs, and coefficients. So, the text file could also look like this.

object index_image.nii

plane sagittal

range 100 150 200 250

factor 2.7182818284590

coeff 3 1 4 1 5 9

How do I import this text file and neatly separate it so that I can isolate each variable? Ideally, I'd have a few arrays (or cells, or whatever is most convenient) that look like this.

object = "index_image.nii";
plane = "saggital";
range = [100, 150, 200, 250];
factor = 2.17182818284590;
coeff = [3, 1, 4, 1, 5, 9];

The variables don't have to be named any particular way, I'm more just focused on the issue of extracting them. Thank you!


Solution

  • You can read the file line by line with the fopen/fgetl/fclose approach, split each line on the first space to differentiate the property from the value, and then assign to a struct based on the property.

    This gives you a struct with nicely named fields, as numeric or text data defined by the property name and the switch/case as shown. See code comments for details.

    data = struct();               % structure to hold the data from file
    fid = fopen( 'temp.txt' );     % open file reference to read input
    thisLine = '';
    while ~isnumeric(thisLine)
        if isempty( thisLine )
            thisLine = fgetl(fid); % skip empty, read next line from the file
            continue              
        end
        prop = extractBefore( thisLine, ' ' ); % property name before space
        val = extractAfter( thisLine, ' ' );   % value(s) after first space
        % Define how to read in specific line types based on prop name
        switch prop
            case {'object','plane'}
                % treat as single string
                data.(prop) = val;
            otherwise
                % treat as numeric arrays
                data.(prop) = str2num( val );
        end
    
        thisLine = fgetl(fid); % read next line from the file
    end
    
    fclose( fid ); % close the file reference
    

    Output from your first example (full precision not displayed in workspace screenshot, but it is there in the data):

    data structure