#author("2018-07-25T19:34:40+09:00","default:Miyashita","Miyashita") #author("2018-07-25T19:35:53+09:00","default:Miyashita","Miyashita") *while文を使ったファイル終端までのデータ読み込み [#x9a72c1b] 一連のフォーマットがファイルの中で何回続くかわからない時に, #codeprettify(lang-matlab){{ while ~feof(fid) }} を使ってファイルの最後まで読み取る(fidはfopenで開いたファイルID).~ **ファイル形式例 [#u1b0f7ed] 例として,ny行nx列の値が時系列で並ぶ,とある量 f(x,y,t) を仮定し, 2017/01/01 00:00:00 f( 1, 1,1) f( 2, 1,1) f( 3, 1,1) ... f(nx, 1,1) f( 1, 2,1) f( 2, 2,1) f( 3, 2,1) ... f(nx, 2,1) f( 1, 3,1) f( 2, 3,1) f( 3, 3,1) ... f(nx, 3,1) ... ... ... ... ... f( 1,ny,1) f( 2,ny,1) f( 3,ny,1) ... f(nx,ny,1) 2017/01/01 00:10:00 f( 1, 1,2) f( 2, 1,2) f( 3, 1,2) ... f(nx, 1,2) f( 1, 2,2) f( 2, 2,2) f( 3, 2,2) ... f(nx, 2,2) .... というように,~ 「時刻(1行),量(ny行),時刻(1行),量(ny行)…」~ と続くファイルがあり,これを全て読み取り,変数へ格納したいとする.~ textscanとfscanfで方法が異なるので別々に.~ **事前作業 [#t1d5deab] どちらも共通の作業として, % % preallocate nt_upper = 1000; header = cell(nt_upper,1); dataorg = cell(nt_upper,1); % % open fid = fopen(filename,'r'); #codeprettify(lang-matlab){{ % % preallocate nt_upper = 1000; header = cell(nt_upper,1); dataorg = cell(nt_upper,1); % % open fid = fopen(filename,'r'); }} のように,ファイルを開き配列の事前割当てをする.~ 事前割当は処理時間の短縮に必要.超えることがないような時間ステップ数で宣言しておく.~ **textscan [#x37959aa] ヘッダー(時刻)と数値配列用で2種類の読み取り形式(FormatSpec)を用意する. % % format fmt_head = '%s%s%*[^\n]'; % header fmt = [repmat('%f',[1 nx]),'\n']; % matrix % % read i = 1; while ~feof(fid) header{i} = textscan(fid,fmt_head,1); dataorg{i} = cell2mat(textscan(fid,fmt,ny)); i = i + 1; end #codeprettify(lang-matlab){{ % % format fmt_head = '%s%s%*[^\n]'; % header fmt = [repmat('%f',[1 nx]),'\n']; % matrix % % read i = 1; while ~feof(fid) header{i} = textscan(fid,fmt_head,1); dataorg{i} = cell2mat(textscan(fid,fmt,ny)); i = i + 1; end }} 数値配列を読むところでは,「cell2mat」がないと,セル配列の中にセル配列が入るので厄介.~ **fscanf [#y6a69b83] 文字列を読み込むのにfscanfは不便なので,fgetlを使う. % % format fmt = [repmat('%f',[1 nx*ny]),'\n']; % % read i = 1; while ~feof(fid) header{i} = fgetl(fid); dataorg{i} = fscanf(fid,fmt,[nx ny])'; i = i + 1; end #codeprettify(lang-matlab){{ % % format fmt = [repmat('%f',[1 nx*ny]),'\n']; % % read i = 1; while ~feof(fid) header{i} = fgetl(fid); dataorg{i} = fscanf(fid,fmt,[nx ny])'; i = i + 1; end }} "[nx ny]"で読みその後転置しなければ,ファイルの配置通りに読めないことに注意.~ この場合,fmtの「'\n'(=改行コード)」は超重要.読み取り開始位置の調整をしている.~ **おわりに [#a030f9d7] また,textscanとfscanfの両方,読み終えた後に余分に宣言した分の空白セルを削除するため, % % delete empty cells header(i:end) = []; dataorg(i:end) = []; #codeprettify(lang-matlab){{ % % delete empty cells header(i:end) = []; dataorg(i:end) = []; }} をしてスマートに.~ この変数の格納形式だと,textscanの方が速かった.~ ***参考 [#oc65d5c6] -[[while>https://jp.mathworks.com/help/matlab/ref/while.html]]~ -[[feof>https://jp.mathworks.com/help/matlab/ref/feof.html]]~