我一直在研究一个令人费解的问题,即将ascii文件读入matlab,其中包含2个不同格式的部分,第一部分还包括不同的列号。
MESH2D
MESHNAME "XXX"
E3T 1 1 29 30 1
E4Q 2 2 31 29 1 1
E4Q 3 31 2 3 32 1
...
...
...
ND 120450 5.28760039e+004 7.49260000e+004 8.05500000e+002
ND 120451 5.30560039e+004 7.49260000e+004 6.84126709e+002
ND 120452 5.32360039e+004 7.49260000e+004 6.97750000e+002
ND 120453 5.34010039e+004 7.49110000e+004 7.67000000e+002
NS 1 2 3 4 5 6 7 8 9 10
NS 11 12 13 14 15 16 17 18 19 20
NS 21 22 23 24 25 26 27 -28
BEGPARAMDEF
GM "Mesh"
我只对包含三角形的行感兴趣,并以E3T / E4Q开头,并且相应的行包含三角形节点的坐标并以ND开头。对于三角形(E3T / E4Q线),我只关注前4个数字,因此我试图做这样的事情:
fileID = fopen(test);
t1 = textscan(fileID, '%s',3);
t2 = textscan(fileID, '%s %d %d %d*[^\n]');
fclose(fileID);
因此,在标题中读取以跳转到数据,然后读取第一个字符串并跟随4个数字,然后跳转到行尾并重新启动。但这不起作用。我只获得一行数据,而不是文件的其余部分。另外,我不知道如何处理文件的第二部分,它以任意数量的数字开始(我当然可以手动查找并输入matlab,但更喜欢matlab自动找到格式的这种更改)
你有什么建议吗?
干杯!
答案 0 :(得分:2)
我建议你先用textscan
作为字符串读取文件的所有行,然后过滤掉你需要的任何内容:
fid = fopen(filename, 'r');
C = textscan(fid, '%s', 'delimiter', '');
fclose(fid);
然后使用regexp
解析E3T / E4Q / ND线:
C = regexp(C, '(\w*)(.*)', 'tokens');
C = cellfun(@(x){x{1}{1}, str2num(x{1}{2})}, C, 'UniformOutput', false);
C = vertcat(C{:});
然后将相应的E3T / E4Q和ND线分组:
idx1 = strcmp(C(:, 1), 'E3T') | strcmp(C(:, 1), 'E4Q');
idx2 = strcmp(C(:, 1), 'ND');
N = max(nnz(idx1), nnz(idx2));
indices = cellfun(@(x)x(1:4), C(idx1, 2), 'UniformOutput', false);
S = struct('tag', [C(idx1, 1); cell(N - nnz(idx1), 1)], ...
'indices', [indices; cell(N - nnz(idx1), 1)], ...
'nodes', [C(idx2, 2); cell(N - nnz(idx2), 1)]);
我将E3T / E4Q值命名为“indices”,将ND值命名为“nodes”。生成的数组S
包含结构,每个结构包含三个字段:tag
(E3T或E4Q),indices
和nodes
。请注意,如果您有“索引”而不是“节点”,反之亦然,则缺失值由空矩阵表示。
答案 1 :(得分:1)
我知道这并不完美,但如果你的文件不是太大,你可以做这样的事情:
fileID = fopen(test,'r');
while ~feof(fileID)
FileLine = fgetl(fileID);
[LineHead,Rem] = strtok(FileLine); % separated string header and numbers
switch LineHead
case 'MESH2D'
% do something here
case 'MESHNAME'
% do something here
case 'E3T'
% parse integer numbers
[Num,NumCount] = sscanf(Rem, '%d');
case 'E4Q'
% parse integer numbers
[Num,NumCount] = sscanf(Rem, '%d');
case 'ND'
% parse integer numbers
[Num,NumCount] = sscanf(Rem, '%d');
% or if you prefer to parse first number separately
[strFirst,strOthers] = strtok(Rem);
FirstInteger = str2num(strFirst);
[Floats,FloatsCount] = sscanf(strOthers, '%g');
% and so on...
end
end
fclose(fileID);
当然,您必须单独处理以 MESH2D , MESHNAME 或 GM 开头的字符串