How To Read Binary File From FORTRAN Program (1999/10/05) Y.Tajima 1) FORTRANで読み込む。 まず、重要なのはFORTRANでは固定長でしか読み込むことが出来ません。 ですのでその時々で読み込む長さを変えられません。どうしてもという 場合にはrecord lengthを1byteにするという無茶もできますが、大変 遅くなるでしょうから、実用的ではないでしょう。それならbufferingして 必要な部分を切り出すのがよいでしょう。 sample1.f ------------------------- program test integer*4 buf(32) integer ptr,iostat open(unit=9,file='input.file',status='OLD', >form='UNFORMATTED',access='direct',err=99, >recl=128) ptr = 1 10 read(9,rec=ptr,err=2,iostat=iostat) (buf(i),i=1,32) write(6,*) (buf(i),i=1,32) ptr = ptr+1 goto 10 99 write(*,*) "open error" goto 999 2 write(*,*) "read error",iostat 999 end ---------------------------------- このプログラムではrecord lengthを128byteにして、一回のreadで 128byteずつ読み込んで表示をしています。 binary dataではopen時にformatをunformattedにするのと、 accessをdirectにします。accessがdirectなので、読み込むときに 読み込む場所のrecord numberをptrで与えています。ptrは1から file_size/record_lengthまで可能です。順番に読み込む場合は ptrを1から順番にcount upさせていけばよいです。もちろんこの 操作はディスクを前提に考えてあり、テープデバイスをダイレクトに 扱うとそちらのrecord lengthも係わって来ますし、テープの前の ほうに戻るのは大変コストが高くなりますので注意しましょう。 2) FORTRANからCのfunctionを呼び出して読み込む。 Cでは簡単に可変長でbinary dataを読み込むことが出来ます。 FORTRANからCのfunctionを呼び出すには、 a) FORTRANからの呼び出しはCALL(つまりsubroutineとして見える。) b) 引数は全て参照渡し(Cではみんなポインタ) c) Cでの関数名には最後に'_'がつく。 という条件が(たいていのcompilerで)つきます。 以下サンプルプログラムです。 sample2.f ---------------------------------- program test character*20 name integer*2 buf(1280) data name / 'input.file\0' / call c_open(name) buf(1) = 1 buf(2) = 2 call c_read(128, buf) write(*,*) (buf(i),i=1,128) end ----------------------------------- sample3.c -------------------------- #include #include #include #include int fp; void c_open_(str) char *str; { printf("c_open: %s\n",str); fp = open(str,O_RDONLY); return ; } void c_read_(size, buf) int *size; short buf[]; { printf("%d %d %d %d \n",*size,buf[0],buf[1],fp ); read(fp, (void *)buf, 2*(*size)); printf("end:\n"); return ; } ------------------------------------ 頭の128byteを読んで表示して終了するプログラムです。 面倒だったのでloopにはしていません。loopにするときには 終了条件の返り値が必要でしょう。compileは % cc -c sample3.c ; f77 sample2.f sample3.o でできます。 ちなみにCOMMON文についてはCの方でglobal変数を COMMON文の名前で定義すれば使えるはずです。 例) common pawc / h(10000) / <-> int pawc[10000]; CとFORTRANの相互の呼び出しについてはKEK-Internal 95-7 "Combining FORTRAN with C and C++ -- A practical Guide to Mixing the Languages --", Ken URQUHART というのが参考になります。 1),2)どちらにしろ機種依存の部分もある場合がありますので、 正確にはcompilerのマニュアルを読んで下さい。 どちらもとりあえず即興で作ったので正確でない部分もありますが、 参考になれば幸いです。