FORTRAN による 'unformatted' のバイナリファイルを読み込むことはできますか?
9 views (last 30 days)
Show older comments
以下は FORTRAN により生成されたデータファイルを 16 進数で表示した例です。
0000000 0000 0048 4920 616d 2061 2067 656e 6975
0000020 7320 6772 6f75 6e64 686f 6721 2020 5275
0000040 6e21 2020 5275 6e21 2020 5275 6e21 2020
0000060 2020 2020 2020 2020 2020 2020 2020 2020
0000100 2020 2020 2020 2020 2020 2020 0000 0048
0000120 0000 000c 3f8c cccd 400c cccd 4053 3333
0000140 0000 000c 0000 0008 0000 0004 0000 0005
0000160 0000 0008
C 言語によるフラットバイナリのファイル内の同様のデータが本ソリューションに添付されています。以下はこのファイルからデータを読み込むためのプログラム例です。
program wrt_bin
character*72 name
real*4 xsource, zsource, dt
integer*4 ntrace, nt
name='I am a genius groundhog! Run! Run! Run!'
xsource=1.1
zsource=2.2
dt=3.3
ntrace=4
nt=5
open(unit=11, file='wrt_bin.bin', form='unformatted',
+ status='new')
WRITE(11) NAME
WRITE(11) XSOURCE,ZSOURCE,DT
WRITE(11) NTRACE,NT
close(11)
end
以下はフラットバイナリデータを生成するための C コードです。
#include<stdio.h>
#include<stdlib.h>
void main()
{
char name[72];
int ntrace, nt;
double xsource, zsource, dt;
FILE *fp;
sprintf(name," I am a genius groundhog! Run! Run! Run!");
xsource=1.1;
zsource=2.2;
dt=3.3;
ntrace=4;
nt=5;
fp=fopen("wrt_binc.bin", "wb");
fwrite(name, sizeof(char), 72, fp);
fwrite(&xsource, sizeof(double), 1, fp);
fwrite(&zsource, sizeof(double), 1, fp);
fwrite(&dt, sizeof(double), 1, fp);
fwrite(&ntrace, sizeof(int), 1, fp);
fwrite(&nt, sizeof(int), 1, fp);
fclose(fp);
}
Accepted Answer
MathWorks Support Team
on 8 Jul 2013
MATLAB はフラットバイナリファイルには対応していますが、FORTRAN によって生成された unformated のバイナリファイルはそれとは異なるため、MATLAB で読み込むには工夫が必要です。
以下に事例が紹介します。なお、Windows の場合、Unix よりさらに工夫が必要で、それについては、以下の URL の最下方に記述があります。
1. UNIX の場合
FORTRAN による unformated のバイナリファイルは各データのデータ長を含んでいます。このデータは WRITE ステートメントとなっています。このため、上記のコードでは 3 つのデータを持っていることになります。データ長の情報は各データの開始位置と終了位置に記録されています。FORTRAN バイナリファイルの開始位置では、データ長が "0000 0048" のように保存されています。これは 16 進数ですので、72 バイトのデータ長ということになります。このポイントからの 72 バイトのカウントは "0000 0048" とは別のもので "0000 000c" (これは次のデータ長で、たとえば 12 バイトまたは 4 バイトの 3 倍)となります。外部からの文字はフィルター等で解読可能である必要があります。もっとも簡単な方法は、MATLAB への読み込み時にフィルターをかけ、C コードでも書き込み可能としておくことです。
以下に MATLAB コマンドによる方法を紹介します。
fid=fopen('wrt_bin.bin', 'rb'); % Open the file.
hr1=fread(fid, 1, 'int32') % Read the first record start tag. Returns hr1 = 72
name=setstr(fread(fid, 72, 'uchar'))' % Read the first record. Returns name = I am a genius
% groundhog! Run! Run! Run!
hr1=fread(fid, 1, 'int32') % Read the first record end tag. Returns hr1 = 72
hr2=fread(fid, 1, 'int32') % Read the second record start tag. Returns hr2 = 12
xsource=fread(fid, 1, 'float32') % Read data. Returns xsource = 1.1000
zsource=fread(fid, 1, 'float32') % Read data. Returns zsource = 2.2000
dt=fread(fid, 1, 'float32') % Read data. Returns dt = 3.3000
hr2=fread(fid, 1, 'int32') % Read the second record end tag. Returns hr2 = 12
hr3=fread(fid, 1, 'int32') % Read the third record start tag. Returns hr3 = 8
ntrace=fread(fid, 1, 'int32') % Read data. Returns ntrace = 4
nt=fread(fid, 1, 'int32') % Read data. Returns nt = 5
hr3=fread(fid, 1, 'int32') % Read the third record end tag. Returns hr3 = 8
fclose(fid); % Close file.
所望のデータのデータ長を読み込み、データそのものにアクセスするためには、MATLAB ファイルを書き換える必要があります。一つの方法として、FSEEK コマンドを使用する方法があります。この方法ではデータ長の分だけポインタを移動し、データに直接アクセスします。
fid=fopen('wrt_bin.bin', 'rb');
fseek(fid, 4, 'cof');
name=setstr(fread(fid, 72, 'uchar'))';
fseek(fid, 4, 'cof');
fseek(fid, 4, 'cof');
xsource=fread(fid, 1, 'float32');
zsource=fread(fid, 1, 'float32');
dt=fread(fid, 1, 'float32');
fseek(fid, 4, 'cof');
fseek(fid, 4, 'cof');
ntrace=fread(fid, 1, 'int32');
nt=fread(fid, 1, 'int32');
fclose(fid);
xsource, zsource, dt, ntrace, nt
結果は以下の通りです。
xsource = 1.1000 zsource = 2.2000 dt = 3.3000 ntrace = 4 nt = 5
2. Windows および Digital Visual Fortran によるバイナリファイル の場合
MATLAB コードを Windows および Digital Visual Fortran によるバイナリファイルに対応させるためにはもう一工夫必要です。Since Digitial Fortran は開始タグに 2 つの符号なしの数値が記述され、終了タグがありません。このため、以下のようなプログラムにする必要があります。
tag=setstr(fread(fid,2,'uchar')); %read the first record start tag
capf=fread(fid,1,'float'); %capture fraction
rot=fread(fid,1,'float'); %grid rotation, radians
tag=setstr(fread(fid,2,'uchar')); %read the second record start tag
nx=fread(fid,1,'int'); %number cells alongwind
xgrid=fread(fid,nx,'float'); %alongwind grid points, m
tag=setstr(fread(fid,2,'uchar')); %read the third record start tag
ny=fread(fid,1,'int'); %number cells crosswind
ygrid=fread(fid,ny,'float'); %crosswind grid points, m
tag=setstr(fread(fid,2,'uchar')); %read the fourth record start tag
dose=fread(fid,nx*ny,'float32'); %read the dose matrix
tag=setstr(fread(fid,2,'uchar')); %read the fifth record start tag
dep=fread(fid,nx*ny,'float32'); %read the deposition matrix
注意: Digital Visual Fortran に関する情報は外部情報によるものであり、MathWorks では動作確認はしておりません。
0 Comments
More Answers (0)
See Also
Categories
Find more on 低水準ファイル I/O in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!