Is it possible to loop a textscan?

7 views (last 30 days)
Saeed Bello
Saeed Bello on 10 Apr 2017
Edited: dpb on 11 Apr 2017
I wrote a code in this form but could not read the data looping through textscan.
My deasire is the pick the header
Data looks like this:
CPNFC 2006/01/01 00:00:00
fmin =[---- ] foE =[---- ] h'E =[---- ] foE2 =[---- ]
fmin =[---- ] foE =[---- ] h'E =[---- ] foE2 =[---- ]
CPNFC 2006/01/01 00:15:00
fmin =[---- ] foE =[---- ] h'E =[---- ] foE2 =[---- ]
fmin =[---- ] foE =[---- ] h'E =[---- ] foE2 =[---- ]
''
''
''
%
fid = fopen(filename);
disp(filename)
format='%5s %4d/%02d/%02d %02d:%02d:%02d'
for m=1:4:6
[station,yyyy,mm,dd,hh,mn,ss] = textread(filename,format,m);
end
  2 Comments
Stephen23
Stephen23 on 10 Apr 2017
Your code shows textread, but it should be textscan.
The answer to your question is yes, you can call textscan in a loop.
You will need to allocate the output to some arrays, which get enlarged on each iteration. If you upload a sample file then we can show you how.
Saeed Bello
Saeed Bello on 10 Apr 2017
Edited: Saeed Bello on 10 Apr 2017
Thank you Stephen Cobeldick for your response. My goal is to extract the information from this attached file. First I want to pick all the header eg.g. CPNFC 2006/01/01 00:00:00,CPNFC 2006/01/01 00:15:00 in order to extract the date and time. Later work on picking the parameter e.g. h'F =[ 246 ] for each period. The raw data is attached.

Sign in to comment.

Answers (2)

dpb
dpb on 10 Apr 2017
Is the 'CPNC' string consistent throughout the file?
If so, read the whole file as cellstring array and just do findstr operation on the matching characters to locate the lines needed.
Alternatively, it appears that there are a fixed number of lines in each section; use that count to skip that many lines after the first...
Something like (caution air code...)
fmt=['%*s' {'yyyy/MM/dd HH:mm:SS'}%D]; % date format string for datetime variable
nH=15; % my count of records between headers
fid=fopen(...
d=textscan(fid,fmt,1); % first date/time
while ~feof(fid)
d=[d;textscan(fid,fmt,1,'headerlines',nH);
end
fid=fclose(fid);
Normally one doesn't want to "grow" an array dynamically, but for a single-time reading a relatively short file the overhead won't be too bad. If doing this over and over will be ongoing, then some efficiencies can be worked on.
  2 Comments
Saeed Bello
Saeed Bello on 10 Apr 2017
Yes the 'CPNC' string is consistent throughout the file I got this error after running your code
??? nH=15; % my count of records between headers
|
Error: The expression to the left of the equals sign is not a valid target for an
assignment.
dpb
dpb on 10 Apr 2017
Edited: dpb on 11 Apr 2017
Well, there's something else causing it then; that's a perfectly valid assignment statement. Check the preceding line is terminated with matching paren's,. quotes, etc., etc., ...
ADDENDUM
And, indeed, the format string was malformed...
>> fmt=['%*s %{yyyy/MM/dd}D %{HH:mm:ss}D %*[^\n]'];
>> while ~feof(fid)
d=[d;textscan(fid,fmt,1,'headerlines',16)];
end
>> whos d
Name Size Bytes Class Attributes
d 192x2 57952 cell
>> d{1,:}
ans =
2006/01/01
ans =
00:00:00
>>
As the note says it was air code; not tested.

Sign in to comment.


Stephen23
Stephen23 on 10 Apr 2017
Edited: Stephen23 on 11 Apr 2017
Here is an alternative to a loop. This code specifies the * character to be the newline and calls textscan just once to read the entire file. This will be faster than using a loop and expanding arrays on each iteration.
opt = {'EndOfLine','*', 'Delimiter','=[]',...
'MultipleDelimsAsOne',true, 'CollectOutput',true};
fmt = repmat('%s',1,1+15*8);
fid = fopen('CPNFC20060101.txt','rt');
C = textscan(fid,fmt,opt{:});
fclose(fid);
C = C{1};
D = regexp(C(:,1),'\s+','split');
D = vertcat(D{:});
C(:,1) = D(:,4);
D = D(:,2:3);
The two output arrays are D, which contains the date and time, and C, which contains both the fieldnames and the field values. On advantage of this is that it makes it easy to construct a non-scalar structure containing all of the data:
E = genvarname(C(1,1:2:120));
E(2,:) = num2cell(regexprep(C(:,2:2:end),{'-+','\s+'},{'-',''}),1);
S = struct(E{:});
which makes accessing the data trivial:
>> S(2).(genvarname('h''Es'))
ans =
E
>> S(12).(genvarname('foEs'))
ans =
283JG
>> S(end).(genvarname('M(3000)F2'))
ans =
115
I tested on this file here:
  2 Comments
Saeed Bello
Saeed Bello on 11 Apr 2017
Thank you, Stephen. Your code has helped me to read the file into Matlab by calling textscan once (What a great relief form me). Iwas unable to get the date from the D array as you mentioned.
  • The challenge now is extracting the dates and time.
  • Kindly help me to extract the date and time separately.
Stephen23
Stephen23 on 11 Apr 2017
@Saeed Bello: it is not clear to me what you are trying to do.
The cell array D contains two columns: the first with the date strings, the second with the time strings. You did not explain what you want to do with these strings, nor how you are trying to "extract" them. You did not even say what you want to the output to be. It is hard for me to help you if you do not give any information about what you are doing, and what you want.
Do you want to convert the date/time strings into date vectors, serial date numbers, datetime objects, or something else entirely?

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!