Reading parameters from a text file into the workspace

痴心易碎 提交于 2019-12-21 22:57:38

问题


I have a file which has the following information:

% ---------------------- location details --------------------------
%
% lat : latitude  [minimum = -90, maximum = 90, unit =  
%       degrees north]
% lon : longitude [ minimum = -360, maximum = 360, unit = 
%       deg east]
% z: altitude (above sea level, m)
%---------------------------------------------------------------
% location:
   lat = 54.35
   lon = -2.9833

This is a small section of the file.

I would like to read some of this information into MATLAB, where the information can then be used to perform some calculations. The part of the file that I would like to read into MATLAB are those in the text file that are not commented, i.e have a % at the start of the line, and the variable should then be saved in the workspace. For example, I would like to have:

lat = 54.35
lon = -2.9833

in the workspace.

How would I go about this? I have read about textscan and fopen, although these don't really seem to help me in this instance.


回答1:


The quick-and-dirty approach

The simplest solution I could think of to read this file indeed employs textscan :) and since the lines are conveniently written in valid MATLAB syntax, you could use eval later to evaluate them. Start by reading each line as one string (ignoring the comments in the header)

fid = fopen(filename);
C = textscan(fid, '%s', 'Delimiter', '', 'CommentStyle', '%')
fclose(fid);

Then feed the lines one by one into eval to create the variables in the MATLAB workspace:

cellfun(@eval, C{1});

What this does is interpret the line as a MATLAB command, i.e create variables as named in the file and assign the appropriate values. If you want to suppress the output of eval, you can use evalc instead to "absorb the output":

cellfun(@evalc, C{1}, 'UniformOutput', false);

This should work for your basic example, but it would fail if you have more than one instance of any parameter. Also note that the eval family is notoriously slow.

A more robust approach

If the lines in your file structure have the parameter name = number pattern, you can read the lines more intelligently:

fid = fopen(filename);
C = textscan(fid, '%[^= ]%*[= ]%f', 'CommentStyle', '%')
fclose(fid);

The %[^= ] in the pattern matches the first characters until the first space or equality sign. The %*[ =] ignores the equality sign and any trailing spaces, and then the numerical value is matched with %f. The resulting cell array C stores the parameter names in the first cell and their corresponding values in the second cell.

Now it's up to you to manipulate the parsed data. For instance, to extract all values of lat and lon, you can do this:

lat = C{2}(strcmp(C{1}, 'lat'));
lon = C{2}(strcmp(C{1}, 'lon'));

If you have more than one "lat" line, lat will be an array holding all these values.




回答2:


Here's another quick and dirty way:

fp = fopen('foo.txt');

found = 1;
while ~feof(fp)
    line = fgetl(fp);
    if (line(1) ~= '%') && ischar(line)
        value(found) = sscanf(line,'%*s %*s %f');
        found = found + 1;
    end
end

The %*s skips the 'lat' or 'long' and the '='.




回答3:


The example you provided is kinda well-behaved, therefore the following solution might need some tailoring. However, I would recommend it against any eval():

% Read whole file ignoring lines that start with '%' and using '=' as delimiter
fid = fopen('test.txt');
s   = textscan(fid,'%s%f', 'CommentStyle','%','Delimiter','=');
fclose(fid);

% Identify lines with latitude and those with longitude
idxLat = strncmpi('lat',s{1},3);
idxLon = strncmpi('lon',s{1},3);

% Store all latitudes and longitudes
lat = s{2}(idxLat);
lon = s{2}(idxLon);



回答4:


Gets you a structure with field names matching parameter names, accepts comma-separated lists. List any parameters that should stay as strings in char_params

char_params={};
fid = fopen(filename);
% Load lines into cell (1x1) containing cell array s (Nx1), 
% skipping lines starting with % and cutting off anything after % in a line
s   = textscan(fid,'%s', 'CommentStyle','%','Delimiter','%');
fclose(fid);
% access the lines strings s{1}, split across '=' and remove whitespace on     both sides
s=strtrim(split(s{1},'='));
% Interpret parameters and save to structure
for ind=1:length(s)
%    User says which parameters are strings
    if any(strcmpi(s{ind,1},char_params))
        file_struct.(s{ind,1})=s{ind,2};
    % Otherwise, assume they are numbers or numeric row arrays
    else
%         remove parentheses and brackets
        trim_s=regexprep(s(ind,2),'[[]()]','');
%         convert comma-separated lists into row arrays
        file_struct.(s{ind,1})=str2double(split(trim_s{1},',')).';
    end
end


来源:https://stackoverflow.com/questions/16900851/reading-parameters-from-a-text-file-into-the-workspace

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