Ответ 1
Здесь есть несколько вопросов.
Фундаментальным является то, что вы не должны использовать текст в качестве формата данных для значительных фрагментов данных. Он большой и медленный. Вывод текста хорош для того, что вы собираетесь читать сами; вы не собираетесь садиться с распечаткой 3,81 миллиона целых чисел и перелистывать их. Как показывает приведенный ниже код, правильный вывод текста примерно на 10 раз медленнее и на 50% больше, чем двоичный вывод. Если вы переходите к значениям с плавающей запятой, возникают проблемы с точной потерей при использовании строк ascii в качестве формата обмена данными. и др.
Если ваша цель - обмен данными с помощью Matlab, довольно легко записать данные в формат, который может читать MATLAB; вы можете использовать API matOpen/matPutVariable из Matlab или просто записать его как массив HDF5, который может читать Matlab. Или вы можете просто записать массив в необработанном двоичном формате Fortran, как показано ниже, и matlab прочитать его.
Если вы должны использовать ascii для записи огромных массивов (что, как уже упоминалось, представляет собой плохую и медленную идею), тогда у вас возникают проблемы с размерами записей по умолчанию при редактировании ввода-вывода со списком. Лучше всего генерировать во время выполнения строку формата, которая правильно описывает ваш вывод, и безопаснее всего для таких больших (~ 5000 символов!) Строк - это установить длину записи явно на нечто большее, чем то, что вы будете распечатывать так что библиотека forran IO не поможет разбить линии для вас.
В приведенном ниже коде
WRITE(rowfmt,'(A,I4,A)') '(',numcols,'(1X,I6))'
генерирует строку rowfmt, которая в этом случае будет (762(1X,I6))
, который является форматом, который вы будете использовать для распечатки, а опция RECL
для OPEN
устанавливает длину записи как нечто большее, чем 7 * numcols + 1.
PROGRAM test3
IMPLICIT NONE
INTEGER :: i, j, k, numrows, numcols
INTEGER, DIMENSION(:,:), ALLOCATABLE :: a
CHARACTER(LEN=30) :: rowfmt
INTEGER :: txtclock, binclock
REAL :: txttime, bintime
numrows=5001
numcols=762
ALLOCATE(a(numrows,numcols))
k=1
DO i=1,SIZE(a,1)
DO j=1,SIZE(a,2)
a(i,j)=k
k=k+1
END DO
END DO
CALL tick(txtclock)
WRITE(rowfmt,'(A,I4,A)') '(',numcols,'(1X,I6))'
OPEN(UNIT=12, FILE="aoutput.txt", ACTION="write", STATUS="replace", &
RECL=(7*numcols+10))
DO i=1,numrows
WRITE(12,FMT=rowfmt) (a(i,j), j=1,numcols)
END DO
CLOSE(UNIT=12)
txttime = tock(txtclock)
CALL tick(binclock)
OPEN(UNIT=13, FILE="boutput.dat", ACTION="write", STATUS="replace", &
FORM="unformatted")
WRITE(13) a
CLOSE(UNIT=13)
bintime = tock(binclock)
PRINT *, 'ASCII time = ', txttime
PRINT *, 'Binary time = ', bintime
CONTAINS
SUBROUTINE tick(t)
INTEGER, INTENT(OUT) :: t
CALL system_clock(t)
END SUBROUTINE tick
! returns time in seconds from now to time described by t
REAL FUNCTION tock(t)
INTEGER, INTENT(IN) :: t
INTEGER :: now, clock_rate
call system_clock(now,clock_rate)
tock = real(now - t)/real(clock_rate)
END FUNCTION tock
END PROGRAM test3