1

我有一个文件,其中包含以下信息:

% ---------------------- 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

这是文件的一小部分。

我想将其中一些信息读入 MATLAB,然后这些信息可用于执行一些计算。我想读入 MATLAB 的文件部分是文本文件中没有注释的部分,在行首有一个%,然后应该将变量保存在工作区中。例如,我想拥有:

lat = 54.35
lon = -2.9833

在工作区。

我该怎么办?我已经阅读了textscanand fopen,尽管在这种情况下这些似乎对我没有帮助。

4

4 回答 4

4

快速而肮脏的方法

我能想到的读取这个文件的最简单的解决方案确实采用了textscan:),并且由于这些行是用有效的 MATLAB 语法方便地编写的,因此您可以eval稍后使用它们来评估它们。首先将每一行读取为一个字符串(忽略标题中的注释)

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

然后将这些行一一输入eval以在 MATLAB 工作区中创建变量:

cellfun(@eval, C{1});

它的作用是将这一行解释为 MATLAB 命令,即创建文件中命名的变量并分配适当的值。如果要抑制 的输出eval,可以改用evalc“吸收输出”:

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

这应该适用于您的基本示例,但如果您有多个任何参数的实例,它将失败。另请注意,eval家庭是出了名的慢。

更稳健的方法

如果文件结构中的行具有模式,则可以更智能地阅读这些行:parameter name = number

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

模式中的%[^= ]匹配第一个字符,直到第一个空格或等号。忽略等号和任何尾随空格,然后%*[ =]将数值与 匹配%f。生成的单元格数组C将参数名称存储在第一个单元格中,并将它们的对应值存储在第二个单元格中。

现在由您来操作解析的数据。例如,要提取 and 的所有值latlon您可以这样做:

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

如果您有多个“纬度”线,lat则将是一个包含所有这些值的数组。

于 2013-06-03T16:16:17.340 回答
0

这是另一种快速而肮脏的方式:

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

%*s跳过'lat'或'long'和'=' 。

于 2013-06-03T16:24:34.390 回答
0

您提供的示例表现良好,因此以下解决方案可能需要一些剪裁。但是,我会推荐它反对任何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);
于 2013-06-03T17:29:19.423 回答
0

为您获取字段名称与参数名称匹配的结构,接受逗号分隔的列表。列出所有应该在 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
于 2017-05-23T18:30:35.983 回答