История изменений
Исправление Jini, (текущая версия) :
Тогда, если не заморачиваться на пропуск одного любого символа при чтении,
Там есть ещё ряд подводных камней, и написать совместимый парсер довольно непросто. Но в первом приближении пойдёт.
Остается только понять, как при чтении определять, что одна порция данных закончилась и нужно вычитывать следующий заголовок и следующую порцию данных.
Обычно это пишется в заголовке. Считай, что это один из интов.
Вот программа, генерирующая файл на 1.5 Гб со случайными данными:
implicit none
type THeader
real f
integer length
integer i(2)
endtype THeader
type TBody
real f(7)
integer i
double precision e
endtype TBody
integer f, i, j, k
type(THeader) h
type(TBody) b
open(newunit=f, file='data', status='replace')
do i = 1, 15000
print *, i
h%f = rnd()
h%length = 350 + irnd(2000 - 350)
h%i(1) = irnd(1000000)
h%i(2) = irnd(1000000)
write (f, '(1X,F9.4,3(1X,I15))') h
do j = 1, h%length
do k = 1, 7
b%f(k) = rnd()
enddo
b%i = irnd(1000)
b%e = rnd()
write (f, '(1X,7(1X,F9.4),1XI3,1XE12.4)') b
enddo
enddo
close(f)
contains
function rnd()
real rnd
call random_number(rnd)
endfunction rnd
function irnd(imax)
integer irnd
integer imax
real x
call random_number(x)
irnd = x * imax
endfunction irnd
end
Вот программа для чтения. Может, skvitek сможет выкатить что-то получше, но те физики, которых я знаю, написали бы примерно также (только без проверки на ошибки :E )
use iso_fortran_env
implicit none
type THeader
real f
integer length
integer i(2)
endtype THeader
type TBody
real f(7)
integer i
double precision e
endtype TBody
integer f, stat, i
type(THeader) h
type(TBody) b
open(newunit=f, file='data', status='old')
do while (.true.)
read (f, '(1X,F9.4,3(1X,I15))', iostat=stat) h
if (stat /= 0) then
if (stat == iostat_end) exit
write (error_unit, *) 'Error while reading header: ', stat
stop
endif
do i = 1, h%length
read (f, '(1X,7(1X,F9.4),1XI3,1XE12.4)', iostat=stat) b
if (stat /= 0) then
if (stat == iostat_eor .or. stat == iostat_end) then
write (error_unit, *) 'Unexpected end of file'
else
write (error_unit, *) 'Error while reading body: ', stat
endif
stop
endif
enddo
enddo
close(f)
end
Компилировать gfortran, так же, как обычным gcc (расширение файла с программой на фортране --- .f08). Если интересно, посравнивай. Если C++ будет тормозить, то я бы использовал mmap; с ним и перестановка блоков должна быть несложной, так как размер каждой записи известен.
Исправление Jini, :
Тогда, если не заморачиваться на пропуск одного любого символа при чтении,
Там есть ещё ряд подводных камней, и написать совместимый парсер довольно непросто. Но в первом приближении пойдёт.
Остается только понять, как при чтении определять, что одна порция данных закончилась и нужно вычитывать следующий заголовок и следующую порцию данных.
Обычно это пишется в заголовке. Считай, что это один из интов.
Вот программа, генерирующая файл на 1.5 Гб со случайными данными:
implicit none
type THeader
real f
integer length
integer i(2)
endtype THeader
type TBody
real f(7)
integer i
double precision e
endtype TBody
integer f, i, j, k
type(THeader) h
type(TBody) b
open(newunit=f, file='data', status='replace')
do i = 1, 15000
print *, i
h%f = rnd()
h%length = 350 + irnd(2000 - 350)
h%i(1) = irnd(1000000)
h%i(2) = irnd(1000000)
write (f, '(1X,F9.4,3(1X,I15))') h
do j = 1, h%length
do k = 1, 7
b%f(k) = rnd()
enddo
b%i = irnd(1000)
b%e = rnd()
write (f, '(1X,7(1X,F9.4),1XI3,1XE12.4)') b
enddo
enddo
close(f)
contains
function rnd()
real rnd
call random_number(rnd)
endfunction rnd
function irnd(imax)
integer irnd
integer imax
real x
call random_number(x)
irnd = x * imax
endfunction irnd
end
Вот программа для чтения. Может, skvitek сможет выкатить что-то получше, но те физики, которых я знаю, написали бы примерно также (только без проверки на ошибки :E )
use iso_fortran_env
implicit none
type THeader
real f
integer length
integer i(2)
endtype THeader
type TBody
real f(7)
integer i
double precision e
endtype TBody
integer f, stat, i
type(THeader) h
type(TBody) b
open(newunit=f, file='data', status='old')
do while (.true.)
read (f, '(1X,F9.4,3(1X,I15))', iostat=stat) h
if (stat /= 0) then
if (stat == iostat_end) exit
write (error_unit, *) 'Error while reading header: ', stat
stop
endif
do i = 1, h%length
read (f, '(1X,7(1X,F9.4),1XI3,1XE12.4)', iostat=stat) b
if (stat /= 0) then
if (stat == iostat_eor .or. stat == iostat_end) then
write (error_unit, *) 'Unexpected end of file'
else
write (error_unit, *) 'Error while reading body: ', stat
endif
stop
endif
enddo
enddo
close(f)
end
Компилировать gfortran, так же, как обычным gcc (расширение файла с программой на фортране --- .f08). Если интересно, посравнивай. Если будет тормозить, то я бы использовал mmap; с ним и перестановка блоков должна быть несложной, так как размер каждой записи известен.
Исходная версия Jini, :
Тогда, если не заморачиваться на пропуск одного любого символа при чтении,
Там есть ещё ряд подводных камней, и написать совместимый парсер довольно непросто. Но в первом приближении пойдёт.
Остается только понять, как при чтении определять, что одна порция данных закончилась и нужно вычитывать следующий заголовок и следующую порцию данных.
Обычно это пишется в заголовке. Считай, что это один из интов.
Вот программа, генерирующая файл на 1.5 Гб со случайными данными:
implicit none
type THeader
real f
integer length
integer i(2)
endtype THeader
type TBody
real f(7)
integer i
double precision e
endtype TBody
integer f, i, j, k
type(THeader) h
type(TBody) b
open(newunit=f, file='data', status='replace')
do i = 1, 15000
print *, i
h%f = rnd()
h%length = 350 + irnd(2000 - 350)
h%i(1) = irnd(1000000)
h%i(2) = irnd(1000000)
write (f, '(1X,F9.4,3(1X,I15))') h
do j = 1, h%length
do k = 1, 7
b%f(k) = rnd()
enddo
b%i = irnd(1000)
b%e = rnd()
write (f, '(1X,7(1X,F9.4),1XI3,1XE12.4)') b
enddo
enddo
close(f)
contains
function rnd()
real rnd
call random_number(rnd)
endfunction rnd
function irnd(imax)
integer irnd
integer imax
real x
call random_number(x)
irnd = x * imax
endfunction irnd
end
Вот программа для чтения. Может, skvitek сможет выкатить что-то получше, но те физики, которых я знаю, написали бы примерно также (только без проверки на ошибки :E )
use iso_fortran_env
implicit none
type THeader
real f
integer length
integer i(2)
endtype THeader
type TBody
real f(7)
integer i
double precision e
endtype TBody
integer f, stat, i
type(THeader) h
type(TBody) b
open(newunit=f, file='data', status='old')
do while (.true.)
read (f, '(1X,F9.4,3(1X,I15))', iostat=stat) h
if (stat /= 0) then
if (stat == iostat_end) exit
write (error_unit, *) 'Unexpected error while reading h: ', stat
stop
endif
do i = 1, h%length
read (f, '(1X,7(1X,F9.4),1XI3,1XE12.4)', iostat=stat) b
if (stat /= 0) then
if (stat == iostat_eor .or. stat == iostat_end) then
write (error_unit, *) 'Unexpected end of file'
else
write (error_unit, *) 'Unexpected error while reading b: ', stat
endif
stop
endif
enddo
enddo
close(f)
end
Компилировать gfortran, так же, как обычным gcc (расширение файла с программой на фортране --- .f08). Если интересно, посравнивай. Если будет тормозить, то я бы использовал mmap; с ним и перестановка блоков должна быть несложной, так как размер каждой записи известен.