バイナリデータの入出力

基礎知識

順番探査 (Sequential Access)

直接探査(Direct Access)

直接探査ファイルの使い方

http://mns2.c.u-tokyo.ac.jp/arasaki/fortran/direct.html

「書式なし直接探査ファイル (unformatted direct access file)」の特徴

  1. ファイルの途中の一部を読み書きできる
  2. 内部表現のまま読み書きされるので書式変換のオーバーヘッドがかからない (記憶容量・速度・精度の面で)
  3. ただし、すべての記録が同じ長さ

順番探査がテープをイメージしているなら直接探査はディスクのイメージです。

プログラム例1

書き出し

program write_direct

integer, parameter :: m=10
real, allocatable :: a(:),b(:)
character(100) ofname
ofname="tmp_direct_access.dat"
write(*,'(A,A)')'output file name: ',ofname
n=5
allocate(a(n),b(n))
do i=1,n
  a(i)=i
  b(i)=i*2.0
enddo !i
INQUIRE(IOLENGTH=nreclen)a,b
open(10,file=ofname,access='direct',recl=nreclen)
write(*,*)'Record length= ',nreclen
write(10,rec=1)a,b
write(*,'(A)')'output data:'
do i=1,n
  write(*,*)a(i),b(i)
enddo 
stop
end

$ ifort tmp_write_directac.f90 -o tmp_write_directac

$ ./tmp_write_directac

output file name: tmp_direct_access.dat

Record length= 10

output data:

1.000000 2.000000

2.000000 4.000000

3.000000 6.000000

4.000000 8.000000

5.000000 10.00000

読み込み

program read_direct
integer, parameter :: m=10
real, allocatable :: a(:),b(:)
character(100) ifname
ifname="tmp_direct_access.dat"
write(*,'(A,A)')'input file name: ',ifname
n=5
allocate(a(n),b(n))
INQUIRE(IOLENGTH=nreclen)a,b
open(10,file=ifname,access='direct',recl=nreclen)
write(*,*)'Record length= ',nreclen
read(10,rec=1)a,b
write(*,'(A)')'Input data'
do i=1,n
  write(*,*)a(i),b(i)
enddo
stop
end

$ ifort tmp_read_directac.f90 -o tmp_read_directac

$ ./tmp_read_directac

input file name: tmp_direct_access.dat

Record length= 10

Input data

1.000000 2.000000

2.000000 4.000000

3.000000 6.000000

4.000000 8.000000

5.000000 10.00000

プログラム例2

データは、tとsの2種類ある。

1ヶ月ごとに、1レコードとしてまとまっている。

!

! 仮定しているデータファイルの構造

!

! レコード番号 データ

! 1 t,s

! ............

! 12 t,s

!

t,sの配列のサイズは(nx,ny,nz)

サンプルプログラム

real, allocatable(t(:,:,:), s(:,:,:))
integer, parameter :: nx=10,ny=20,nz=5
allocate (t(nx,ny,nz),s(nx,ny,nz))
INQUIRE(IOLENGTH=L) t,s
nt=12
iu2=20
open(iu2,file=infle2,form="unformatted",access='direct',recl=L)
print *, ' Reading t & s'
do m=1,nt
  read(iu2,rec=m)t,s
enddo !m
close(iu2)
print *, 'Done.'
print *
stop
end