Reputation: 1153
I want to ask you for help in what follows: I have couple of structures saved in a .txt file and I want to read them in matlab and save in a convenient type to load them later on into a .mat file. I've been searching through the internet to find a solution but what I got was info about reading columns, specific strings... but I cannot combine it to get the answer I want. Any help appreciated! Thanks a lot!
here code I'm trying to work on:
struct
studentname: joe
notes:
n1 = 1.3
n2 = 2.0
average =1.7
endstruct
struct
studentname : marc
notes:
n1 = 2.3 %commentary, to be ommitted while reading from the file
n2 = 3.0
average = 2.7
endstruct
Upvotes: 2
Views: 4762
Reputation: 124563
Here a complete solution (similar to what @Marc described):
%# read lines
fid = fopen('file.txt','rt');
C = textscan(fid, '%s', 'Delimiter',''); C = C{1};
fclose(fid);
%# start/end of each structure
startIdx = find(ismember(C, 'struct'));
endIdx = find(ismember(C, 'endstruct'));
%# array of strucutres
N = numel(startIdx);
arr = struct('studentname','', 'notes','', 'n1',0, 'n2',0, 'average',0);
arr = repmat(arr,[N 1]);
%# parse and store each structure in the array
for i=1:numel(startIdx)
%# parse key/value of struct
s = C(startIdx(i)+1:endIdx(i)-1);
s = regexp(s, '(\w+)\s*[:=]\s*([^%$]*)(?:%[^$]*)?', 'tokens', 'once');
s = vertcat(s{:});
%# try to parse as numbers
v = str2double(s(:,2));
s(~isnan(v),2) = num2cell(v(~isnan(v)));
%# store: struct.key = value
for j=1:size(s,1)
arr(i).(s{j,1}) = s{j,2};
end
end
The result:
>> arr(1)
ans =
studentname: 'joe'
notes: ''
n1: 1.3
n2: 2
average: 1.7
>> arr(2)
ans =
studentname: 'marc'
notes: ''
n1: 2.3
n2: 3
average: 2.7
Of course this assumes the file is well formatted (struct/endstruct blocks, all structs contain the same fields, and field types are consistent)
The code starts by reading the file lines into a cell array. Then we look for the start/end position of struct/endstruct constructs. We initialize an empty array of structure with some default values, and we iterate through the file parsing each block, and storing that info in one structure.
Next we use regular expression to detect the following pattern:
some_key_name = some value % optional comment here
we allow for some variations in spaces, and also accept either =
or :
as character in between. We use capturing tokens in regexp to recover each component of the above, and store them in a temporary cell array. At this point, everything is stored as strings.
Now that actual values can either be numeric or strings. We initially try to parse them as numbers using STR2DOUBLE. This function returns NaN
if it fails, which we use to change only the parts that were successfully converted.
Finally with the above result, we use dynamic field names to store each value in the corresponding key inside the structure array.
Upvotes: 4
Reputation: 3313
Unfortunately, you are basically going to have to roll your own. You can start with fileread()
, which reads the entire file into a string, then, reading line by line, maybe using regexp()
or strfind()
to parse each line, then finally using either struct()
or dynamic field access
to construct your structs.
Untested, incomplete, but rough idea (presumes file is well-formed - you will need to add checks):
%read file
wholeFile = fileread(myfilename);
%find starts & ends:
starts = strfind(wholeFile, 'struct');
ends = strfind(wholeFile, 'endstruct');
For i = 1:numel(starts);
rawStruct = wholeFile(starts(i)+7, ends(i)-2);
%parse line by line getting field names using the string "rawStruct"
out(i).(fieldname) = content;
end
Upvotes: 1
Reputation: 2114
You could give the XML_io_tools from the Matlab file exchange a try. It can parse a XML file to a matlab struct and visa versa.
Upvotes: -2