Я хочу обработать двоичный файл и записать результаты в новый того же формата.
Мой код начинается с копирования заголовка и для каждого кадра данных его загрузки/обработки/вывода:
program main
use, intrinsic :: iso_fortran_env, only: int32, real32
implicit none
integer(kind=int32),dimension(:),allocatable :: header
real(kind=real32),dimension(:),allocatable :: frame
integer(kind=int32) nb_frames, frame_sz
integer i
allocate(header(256))
open(unit=1,file='fort.1',access='stream',status='old')
read(1) header
frame_sz = header(1)
nb_frames = header(2)
allocate(frame(frame_sz))
open(unit=2,file='fort.2',access='stream',status='new')
write(2) header
do i=1,nb_frames
read(1) frame
C ... some calculations
write(2) frame
enddo
close(unit=1)
C ... PLACEHOLDER: update a few values in the header of unit #2
close(unit=2)
deallocate(header)
deallocate(frame)
end
После обработки всего входного файла мне нужно обновить заголовок в выходном файле. Как бы вы это сделали?
@GhorbanM.Tavakoly записывает ли новый заголовок после fseeking усечение файла (т. е. данные после потери заголовка)?
нет. он просто перезаписывает заголовок. см. gcc.gnu.org/onlinedocs/gfortran/FSEEK.html
Можете ли вы объяснить формат заголовка? (Это не обязательно должно быть точно, но если, например, заголовок не фиксированного размера, влияние будет огромным.)
Однако, поскольку ваш файл подключен для потокового доступа, нет смысла использовать ерунду вроде нестандартных операторов позиционирования файла: write(..., pos=...).
@francescalus заголовок имеет фиксированный размер 1024 байта и может иметь необязательные поля; Я не буду добавлять или удалять какие-либо из этих полей.
@francescalus, спасибо, попробую write( ..., pos=...) позже.
+1 за отдельный пост @francescalus в качестве ответа на этот пост. rewind написан в стандартном формате Fortran 2003 (раздел 9.7.3) и предпочтительнее моего предложения fseek.
+1 за отдельный пост @francescalus в качестве ответа на этот пост. rewind написан в стандартном формате Fortran 2003 (раздел 9.7.3) и предпочтительнее моего предложения fseek.
О каком объеме данных вы говорите — о нескольких К или Гигабайтах? Если данных немного, то просто проделайте все манипуляции с памятью, а потом все выпишите в конце.
@cup Размер этих файлов может сильно различаться; от нескольких сотен МБ до нескольких десятков ГБ.





Если внешний файл имеет определенную позицию, следующий оператор передачи данных, включающий этот файл, начинается со следующей позиции. Вы можете разместить файл в исходной точке, используя оператор rewind:
rewind(unit)
write(unit=2, ...) ! Transfer starting from the initial point
С точки зрения перезаписи, влияние записи в файл, расположенный в его начальной или другой точке, зависит от режима доступа внешнего файла:
Для последовательно подключенного файла эффектом записи конечного файла является усечение (последующие записи больше не считаются существующими).
Все это означает: если у вас есть файл потокового доступа, вы можете (пере)записывать произвольные единицы хранения файлов. Вам даже не нужно перематывать назад:
write(unit=2, pos=1, ...)
Если вам нужно записать больше данных в более раннем месте файла, вам не повезло:
Вы можете использовать нестандартный (расширение gnu)
call fseek(file_unit, 0, 0, ierr)gfortran, чтобы вернуть указатель позиции файла в начало файла и снова записать заголовок. другие реализации Фортрана могут иметь аналогичные расширения.