LINUX.ORG.RU

История изменений

Исправление 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; с ним и перестановка блоков должна быть несложной, так как размер каждой записи известен.