新浪博客

Matlab读取数据文件-fscanf, fgetl+textscan

2014-10-24 16:40阅读:
如果数据文件里有文字说明,或着内容复杂,不是简单的矩阵形式的纯数据,一般采用fgetl+textscan来实现。但是此方法必定使用MATLAB的for循环或者while循环,MATLAB为解释型语言执行效率较低。因此需要采用fscanf和fgetl+textscan结合使用。我们通过一个实例来探讨里面的注意事项:
数据文件:
Frequency (GHz): From | To | Num
1 3 3
1
2
3
Theta (Degree): From | To | Num
0 90 2
0
90
Phi (Degree): From | To | Num
0 360 5
0
90
180
270
360
E-Field (V/m): E_r | E_theta | E_phi | H_r |H_theta |H_phi
(8.40643e-006,0.000245996) (0.00103001,0.000451517) (0.409242,1.07181) (-8.26922e-008,6.4936e-007) (-0.00109092,-0.00284011) (-5.06344e-024,3.97619e-023)
(0.000116073,0.000214235) (0.00113539,-9.36016e-005) (0.826323,0.812999) (2.15004e-007,6.14576e-007) (-0.00219529,-0.0021515) (1.31652e-023,3.76319e-023)
(0.000196986,0.000138011) (0.000967579,-0.000629785) (1.10041,0.399242) (4.63276e-007,4.49752e-007) (-0.0029196,-0.00105301) (2.83674e-023,2.75394e-023)
(0.000234162,3.47261e-005) (0.000560779,-0.0010272) (1.17746,-0.0962978) (6.08595e-007,1.92562e-007) (-0.00312114,0.000261053) (3.72657e-023,1.1791e-023)
....................


说明:该数据是描写电场(E_r | E_theta | E_phi)和磁场(H_r |H_theta |H_phi)随着频率(Frequency和观察角(Theta Phi 变化的数据集合,即 F_u(f,theta,phi)。中四部分:
数据共四部分,1-3部分为变量(f,theta,phi)的扫描信息,第四部分为真正的数据部分。
1. 打开文件
fid = fopen(filepath,'r');
if fid == -1
disp('can not open file!');
end

2. 跳过注释部分行
nextline = fgetl(fid); % Line1
由于如果使用fscanf(fid,'%s',1) 遇到空格Frequency (GHz): From | To | Num就会只读到Frequency
3. 读取1-3部分数据: fscanf和 fgetl+textscan两种方式,前者对于有规律(矩阵排布)的数据读取效率极高,fgetl+textscan要用for循环效率极低,但是灵活性特别高。


以读取第一部分数据为例:
Frequency (GHz): From | To | Num
1 3 3
1
2
3
3.1 fscanf:fscanf(fid,'%f',n)
nextline = fgetl(fid);
DATA.FreqFrom = fscanf(fid,'%f',1);
DATA.FreqTo = fscanf(fid,'%f',1);
DATA.FreqNum = fscanf(fid,'%d',1);
DATA.FreqList= fscanf(fid,'%f',DATA.FreqNum );
fscanf(fid,'%f',n ); 这里n表示读取一次读取n个%f类型的数据,如果每行数据不止一个可以采用[m n], 对于与格式部分要有m个%f


3.2 fgetl+textscan
nextline = fgetl(fid); % Line1
nextline = fgetl(fid);
line_content = textscan(nextline, '%f %f %d');
DATA.FreqFrom = line_content{1,1}(1);
DATA.FreqTo = line_content{1,2}(1);
DATA.FreqNum = line_content{1,3}(1);
for idx = 1:DATA.FreqNum
nextline = fgetl(fid);
line_content = textscan(nextline, '%f');
DATA.FreqList(idx) = line_content{1,1}(1);
end
fgetl:得到当前行数据,以字符串形式返回,因此还要使用textscan把数据格式读取;
textscan:格式读取数据,数据格式与C语言相同,返回cell,因此采用line_content{1,1}(1),红色的那个序号就是第几个数据的序号。


同样的方式可以读取Theta和phi信息


4. 读取第四部分数据
4.1 fscanf:fscanf(fid,''(%f,%f) (%f,%f) (%f,%f) (%f,%f) (%f,%f) (%f,%f)',[m n])
Field = fscanf(fid, '(%f,%f) (%f,%f) (%f,%f) (%f,%f) (%f,%f) (%f,%f)', [12 inf]);
注意:
a. 在格式串中必须加上
b. 如果使用fscanf后又想使用fgetl,并且fscanf读取的数据后面换行了,你们使用fscanf时也必须使用
c. 上面使用[12 inf]表示读取到文件尾,如果后面还有其他数据可以把inf替换成n


4.2 fgetl+textscan同3.2使用形式一样。


5. 数据转成多维矩阵:


如果采用fscanf去取的数据,得到的书12xn的数据,对于E_r | E_theta | E_phi | H_r |H_theta |H_phi而言 ,如果般数据文件之前程序输出的时候是下面这种方式的,
for iThetaIdx = 1:iThetaNum
for iPhiIdx = 1:iPhiNum
for iFreqIdx = 1:iFreqNum
printf(fid,'(%f,%f) (%f,%f) (%f,%f) (%f,%f) (%f,%f) (%f,%f)',........)
end
end
end
通过reshape函数可以把1xn的数据转成三维数组:
DATA.Er = reshape(DATA(1,:)+1i*DATA(2,:),iPhiNum ,iThetaNum, iFreqNum );
DATA.EriPhiNum x iThetaNum x iFreqNum 的三维矩阵,由于reshape函数是把数据先列拆分和重新整合的,务必注意此顺序!

我的更多文章

下载客户端阅读体验更佳

APP专享