如何正确读写此文件?

时间:2019-07-07 15:51:21

标签: fortran

我正在尝试使用BIG-ENDIAN格式读取未格式化的文件。如何读取此文件并将其正确输出到.dat文件中?

我在Fortran不太熟悉代码。在许多论坛上发布后,我得到了一些似乎不完整的代码。

 module modbin
type rectype
    character(len=8)::key
    integer::data_count
    character(len=4)::data_type
    logical::is_int
    integer, allocatable:: idata(:)
    real(kind=8), allocatable::rdata(:)
end type
contains
subroutine rec_read(in_file, out_rec)
    integer, intent(in):: in_file
    type (rectype), intent(inout):: out_rec
    !
    ! You need to play around with this figure.  It may not be
    ! entirely accurate - 1000 seems to work, 1024 does not
    integer, parameter:: bsize = 1000
    integer:: bb, ii, iimax

    ! read the header
    out_rec%data_count = 0
    out_rec%data_type = '    '
    read(in_file, end = 20) out_rec%key, out_rec%data_count, 
 out_rec%data_type
    ! what type is it?
    select case (out_rec%data_type)
    case ('INTE')
        out_rec%is_int = .true.
        allocate(out_rec%idata(out_rec%data_count))

    case ('DOUB')
        out_rec%is_int = .false.
        allocate(out_rec%rdata(out_rec%data_count))
    end select

    ! read the data in blocks of bsize
    bb = 1
    do while (bb .lt. out_rec%data_count)
        iimax = bb + bsize - 1
        if (iimax .gt. out_rec%data_count) iimax = out_rec%data_count
        if (out_rec%is_int) then
            read(in_file) (out_rec%idata(ii), ii = bb, iimax)
        else
            read(in_file) (out_rec%rdata(ii), ii = bb, iimax)
        end if
        bb = iimax + 1
    end do
20      continue
end subroutine rec_read

subroutine rec_print(in_recnum, in_rec)
    integer, intent(in):: in_recnum
    type (rectype), intent(in):: in_rec
    print *, in_recnum, in_rec%key, in_rec%data_count, in_rec%data_type
    ! print out data
    open(unit=12, file='reader.data' , status='old')

 write(*,'(i5)')GEOMETRY
    close(12)

end subroutine rec_print
end module modbin

program main
use modbin
integer, parameter:: infile=11
! fixed size for now - should really be allocatable
integer, parameter:: rrmax = 500
type (rectype):: rec(rrmax)
integer:: rr, rlast

open(unit=infile, file='TEST1603.SLN0001', form='UNFORMATTED', 
status='OLD', convert='BIG_ENDIAN')
rlast = 0
do rr = 1, rrmax
    call rec_read(infile, rec(rr))
    if (rec(rr)%data_type .eq. '    ') exit
    rlast = rr
    call rec_print(rr, rec(rr))
end do
close(infile)
end program main

我希望前几行数据的输出为 like this

这是DOWNLOAD LINK for the unformatted Version file

然后 这是Download link for the formatted version file

1 个答案:

答案 0 :(得分:0)

我制作了您的程序的稍作修改的版本,该程序读取二进制文件并生成符合格式文件的可读文件“ reader.data”。在标准输出上也是如此。

   module modbin
      implicit none
      type rectype
         character(len=8)::key
         integer::data_count
         character(len=4)::data_type
         logical::is_int
         integer, allocatable:: idata(:)
         real(kind=8), allocatable::rdata(:)
      end type
   contains
      subroutine rec_read(in_file, out_rec)
         integer, intent(in):: in_file
         type (rectype), intent(inout):: out_rec
         !
         ! You need to play around with this figure.  It may not be
         ! entirely accurate - 1000 seems to work, 1024 does not
         integer, parameter:: bsize = 1000
         integer:: bb, ii, iimax

         ! read the header
         out_rec%data_count = 0
         out_rec%data_type = '    '
         read(in_file, end = 20) out_rec%key, out_rec%data_count, out_rec%data_type
         ! what type is it?
         select case (out_rec%data_type)
          case ('INTE')
            out_rec%is_int = .true.
            allocate(out_rec%idata(out_rec%data_count))

          case ('DOUB')
            out_rec%is_int = .false.
            allocate(out_rec%rdata(out_rec%data_count))
         end select

         ! read the data in blocks of bsize
         bb = 0
         do while (bb .lt. out_rec%data_count)
            iimax = bb + bsize
            if (iimax .gt. out_rec%data_count) iimax = out_rec%data_count
            if (out_rec%is_int) then
               read(in_file) (out_rec%idata(ii), ii = bb+1, iimax)
            else
               read(in_file) (out_rec%rdata(ii), ii = bb+1, iimax)
            end if
            bb = iimax
         end do
     20  continue
      end subroutine rec_read

      subroutine rec_print(outfile, in_rec)
         integer, intent(in):: outfile
         type (rectype), intent(in):: in_rec
         integer, parameter:: bsize = 1000
         integer bb,iimax,ii
         write(outfile,'(" ''",a,"''",i12," ''",a,"''")') in_rec%key,in_rec%data_count,in_rec%data_type
         print '(" ''",a,"''",i12," ''",a,"''")', in_rec%key, in_rec%data_count, in_rec%data_type

         ! print out data

         bb = 0
         do while (bb .lt. in_rec%data_count)
            iimax = bb + bsize
            if (iimax .gt. in_rec%data_count) iimax = in_rec%data_count
            if (in_rec%is_int) then
               write(outfile,'(6i12)') (in_rec%idata(ii), ii=bb+1,iimax)
               print '(6i12)', (in_rec%idata(ii), ii=bb+1,iimax)
            else
               write(outfile,'(3d23.14)') (in_rec%rdata(ii), ii=bb+1,iimax)
               print '(3d23.14)', (in_rec%rdata(ii), ii=bb+1,iimax)
            endif
            bb = iimax
         enddo
      end subroutine rec_print
   end module modbin

   program main
      use modbin
      implicit none
      integer, parameter:: infile  = 11
      integer, parameter:: outfile = 12
      ! fixed size for now - should really be allocatable
      integer, parameter:: rrmax = 500
      type (rectype):: rec(rrmax)
      integer:: rr, rlast, k(10),i
      character*8 text1
      character*4 text2

      open(unit=outfile, file='reader.data')
      open(unit=infile, file='TEST1603.SLN0001', form='UNFORMATTED', status='OLD', convert='BIG_ENDIAN')
      read(unit=infile) text1,i,text2
      write(unit=outfile,fmt='(" ''",a,"''",i12," ''",a,"''")') text1,i,text2
      print '(" ''",a,"''",i12," ''",a,"''")',text1,i,text2
      read(unit=infile) k
      write(unit=outfile,fmt='(6i12)') k
      print '(6i12)',k
      rlast = 0
      do rr = 1, rrmax
         call rec_read(infile, rec(rr))
         if (rec(rr)%data_type .eq. '    ') exit
         rlast = rr
         call rec_print(outfile, rec(rr))
      end do
      close(infile)
      close(outfile)
   end program main