How do I determine the number of headerlines in a text document?

25 ビュー (過去 30 日間)
Joshua
Joshua 2014 年 6 月 17 日
コメント済み: dpb 2020 年 5 月 25 日
I need to read in data from a text document. The document starts with an unknown number of headerlines (zero up to 20), and the data is broken into two columns with an unknown number of rows.
4 points
PER AREA
1.000000 0.995458
0.997791 0.981313
0.988447 0.980913
0.987217 0.971326
I would like to determine the number of headerlines there are in the document, and then use textscan to skip them. My code so far is...
fileID = fopen('nameoffile.txt');
n = 0;
tline = fgetl(fileID);
while ( ischar(tline) || isinteger(tline) )
tline = fgetl(fileID);
n = n+1;
end
data = textscan( fileID, '%f%f%*[^\n]','Headerlines',n,'CollectOutput',true);
This gives me a header count, 'n', that is equal to the number of lines in the file. Is there a way to do this?
Thanks.

回答 (4 件)

Jos (10584)
Jos (10584) 2014 年 6 月 18 日
Read the file as strings and parse the strings. The following might work (at least it works when I copied your example into a file.)
DataFile = 'data.txt'
C = textread(DataFile, '%s','delimiter','\n')
V = cellfun(@(s) sscanf(s,'%f%f').', C, 'un', 0)
DATA = vertcat(V{:})
  1 件のコメント
Jos (10584)
Jos (10584) 2014 年 6 月 18 日
And to obtain the headers:
HEADER = C(cellfun('isempty',V))

サインインしてコメントする。


dpb
dpb 2014 年 6 月 17 日
TMW has already done it for you...
doc importdata
  2 件のコメント
Joshua
Joshua 2014 年 6 月 18 日
I tried that command, and it does work with the example I gave. However, my actual header is more complex and it doesn't want to work with it.
Is there any reason 'importdata' would not work?
Shape name
Size #, #, #
# of vertices
Perimeter is the first column, Area is the second column.
This was created by 'person' on 'date' using the function 'name'.
PER AREA
1.000000 0.995458
0.997791 0.981313
0.988447 0.980913
0.987217 0.971326
dpb
dpb 2014 年 6 月 18 日
Doesn't look like should be...and indeed, it worked on that snippet of a file here--
>> josh=importdata('josh.txt')
josh =
data: [4x2 double]
textdata: {6x2 cell}
colheaders: {'PER' 'AREA'}
>> josh.data
ans =
1.0000 0.9955
0.9978 0.9813
0.9884 0.9809
0.9872 0.9713
>>
This is R2012b/32-bit Windows. Your version and if fails consistently on your system would seem to be worthy a bug report.

サインインしてコメントする。


Joseph Cheng
Joseph Cheng 2014 年 6 月 18 日
編集済み: Joseph Cheng 2014 年 6 月 18 日
Well if you are having arbitrary headers but you know where the data starts (with the column headers PER and AREA); then you can hunt for the start of data using fgetl and strfind. so you'll open the file, fgetl and given certain conditions look for strfind(line,'PER')==1 and the same for AREA (i don't know the line position of AREA). Additionally you can put in a check to see that the data afterwords is 2 numbers if ~isempty(str2num(nextline));
after you get your heading position use that in dlmread.

Gabriel Felix
Gabriel Felix 2020 年 5 月 24 日
I had to use \n at the end of each line. Without it I couldn't make textscan() work properly, even thoug the "HeaderLines" was configured according to the text file lines. This was the only solution I found after struggling with the code for an intire day.
This was the text:
!
!
! alfa (graus) = 5.0
!
! Id. x/s z/s alfai cl c*cl/cmed cdi cmc/4
! (graus)
1 .246 .050 -1.209 .255 .332 .00538 .0170
2 .292 .150 -1.098 .259 .319 .00496 .0545
3 .339 .250 -.925 .254 .297 .00410 .0944
4 .385 .350 -.741 .243 .268 .00315 .1341
5 .432 .450 -.561 .227 .235 .00223 .1714
6 .479 .550 -.393 .206 .199 .00141 .2034
7 .525 .650 -.238 .181 .163 .00075 .2266
8 .572 .750 -.101 .152 .126 .00027 .2362
9 .619 .850 .014 .116 .089 -.00003 .2236
10 .659 .938 .103 .074 .052 -.00013 .1693
!
! CL asa = .208
! CDi asa = .00258
! e (%) = 88.9
! CMc/4 asa = .1339
My code:
%! alfa (graus) = 5.0
P = textscan(fid,'! alfa (graus) = %f','Delimiter',' ','MultipleDelimsAsOne',true,'headerLines',2,'CollectOutput',1);
alpha(1) = P{1};
%! CL asa = .208
P = textscan(fid,'! CL asa = %f\n','Delimiter',' ','MultipleDelimsAsOne',true,'CollectOutput',1,'headerLines',4+n);
CL(1) = P{1};
%! CDi asa = .00258
P = textscan(fid,'! CDi asa = %f\n','Delimiter',' ','MultipleDelimsAsOne',true,'CollectOutput',1,'headerlines',0);
CDi(1) = P{1};
%! CMc/4 asa = .1339
P = textscan(fid,'! CMc/4 asa = %f','Delimiter',' ','MultipleDelimsAsOne',true,'CollectOutput',1,'HeaderLines',2);
Cmc4(1) = P{1};
  3 件のコメント
Gabriel Felix
Gabriel Felix 2020 年 5 月 25 日
What an elegant solution! Thank you for helping. I posted it here because I thought it was related to this topic's subject. (This topic was one of the many I consulted for trying to solve my problem).
However I should have made a question with it. I would have done it if I hadn't solved the problem with this less elegant solution.
I really liked your approach. Thanks a lot man!
dpb
dpb 2020 年 5 月 25 日
No problem; glad to be of help.
Illustrating some of the newer string class functionality that is useful for such -- even I wasn't sure the lookup syntax was going to work as intended but tried it as being what I knew I wanted! :)
The other really important takeaway is when you have strings for variables, use a struct or a table or one of the similar data structures that has the facility to address the field or variable name within it--don't try to make variables directly that end up with the dreaded eval as only way to use them.

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeText Data Preparation についてさらに検索

Community Treasure Hunt

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

Start Hunting!

Translated by