Здесь есть несколько вопросов.
Принципиальным является то, что вы не должны использовать текст в качестве формата данных для значительных кусков данных. Это большой и медленный. Вывод текста хорош для того, что вы собираетесь читать сами; Вы не собираетесь сидеть с распечаткой 3,81 миллиона целых чисел и пролистывать их. Как показывает код ниже, правильный вывод текста примерно в 10 раз медленнее и на 50% больше, чем двоичный вывод. При переходе к значениям с плавающей запятой возникают проблемы потери точности при использовании строк ascii в качестве формата обмена данными. и т.д.
Если ваша цель - обмен данными с matlab, довольно легко записать данные в формат, который может прочитать matlab; Вы можете использовать API matOpen / matPutVariable из matlab или просто записать его в виде массива HDF5, который может читать matlab. Или вы можете просто записать массив в необработанном двоичном коде Фортрана, как показано ниже, и matlab прочитает его .
Если вы должны использовать ascii для записи огромных массивов (что, как уже упоминалось, является плохой и медленной идеей), то вы столкнетесь с проблемами с длинами записей по умолчанию в IO с фиксированным списком. Лучше всего генерировать во время выполнения строку формата, которая правильно описывает ваш вывод, и, кроме того, безопаснее всего для таких больших (~ 5000 символов!) Строк явно задавать длину записи, превышающую то, что вы будете распечатывать. так что библиотека Фортрана IO не поможет вам разбить строки.
В приведенном ниже коде,
WRITE(rowfmt,'(A,I4,A)') '(',numcols,'(1X,I6))'
генерирует строку rowfmt, которая в этом случае будет (762(1X,I6))
, это формат, который вы будете использовать для печати, а опция RECL
для OPEN
устанавливает длину записи больше 7 * чисел + 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