У меня есть неформатированный двоичный файл, созданный с помощью компилятора Compaq Visual Fortran (с прямым порядком байтов).
Вот что говорит о нем небольшая часть документации:
Бинарный файл записан вобщий формат, состоящий из массивов данных, возглавляемых записью дескриптора:
- 8-символьное ключевое слово, которое идентифицирует данные в блоке.
- 4-байтовое целое число со знаком, определяющееколичество элементов в блоке.
- 4-символьное ключевое слово, определяющее тип данных.(INTE, REAL, LOGI, DOUB или CHAR) Элементы заголовка считываются как одна запись.Данные следуют за дескриптором новой записи.Числовые массивы разбиты на блоки по 1000 единиц.Физический размер записи совпадает с размером блока.
Попытки чтения таких данных
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(12,*)key
!write(*,'(i5')GEOMINDX
!write(*,'(i5')ID_BEG
!write(*,'(i5')ID_END
!write(*,'(i5')ID_CELL
!write(*,'(i5')TIME_BEG
!write(*,'(i5')SWAT
!format('i5')
!end do
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
Этот код компилируется и работает гладкопоказывает
и не выдает ошибок, но это записано в выходном файле
не показывает никаких полезных числовых значений
Файл, о котором идет речь, доступен здесь
И правильный оператор WRITE должен создать такой файл здесь
Isмой ЗАПИСЬ, чтобы вывести этот тип файла неправильно?и если да, то как лучше?спасибо