2016-01-04 2 views
3

Если я использую Fortran для записи и чтения файла таким же образом с потоком, он работает хорошо. Если я отредактирую файл с текстовым редактором, не изменяя ничего (например, return backspace) и сохраните файл, который он не будет читать, цитируя конец файла перед позицией, которую я ожидаю, что она закончится.Форматированный поток Fortran считывает файл с новой строкой, вызывает проблемы

Чтобы исследовать, я написал следующий код, который пишет мою таблицу, затем читает ее в одной позиции за раз в качестве символа. Он работает только правильно, если в файле, который я читаю, нет новых строк. В противном случае я получаю только последние n чисел, n - количество данных в строке.

Идея состоит в том, чтобы узнать более мощные способы, чем последовательное чтение для чтения в больших файлах, форматированных в странном формате, которые я использую на работе, поступающей от инженерного программного обеспечения и испытательного оборудования.

program stream 
implicit none 

character(len=1)    :: text 
integer(kind=4), dimension(100) :: array 
integer(kind=4)     :: status = 0, i 



open (unit=11, file='out.txt', form='formatted', access='stream', action='readwrite', status='replace') 

array = (/(i, i = 1,100)/)   ! Populate vector from 1 to 100 

write(unit=11,fmt='(10i4)') array ! Write array to file 

i=0 
do while (status == 0)    ! Read array back from file, one position at a time until end of file 
i=i+1 
read(unit=11, fmt='(a1)', pos=i, iostat=status) text 
write(*,fmt='(a1)', advance='no') text ! Write results to screen to see what is in each position 
end do 


close(unit=11) 


end program stream 

    File written then read: 
     1 2 3 4 5 6 7 8 9 10 
     11 12 13 14 15 16 17 18 19 20 
     21 22 23 24 25 26 27 28 29 30 
     31 32 33 34 35 36 37 38 39 40 
     41 42 43 44 45 46 47 48 49 50 
     51 52 53 54 55 56 57 58 59 60 
     61 62 63 64 65 66 67 68 69 70 
     71 72 73 74 75 76 77 78 79 80 
     81 82 83 84 85 86 87 88 89 90 
     91 92 93 94 95 96 97 98 99 100 

    Result: (many spaces here) 
8 8 8 8 8 8 8 8 9 91 92 93 94 95 96 97 98 99 100 
+0

PS, gfortran на OSX, все до даты, как 1/2016 –

+0

Используйте тег fortran, чтобы больше людей могли видеть ваш вопрос. Используйте версии только в том случае, если вы хотите ограничить одну версию (нет F 2008). –

ответ

2

Я думаю, что вы видите, это проблема с выполнением компилятора, усугубляется выбором вы сделали с вашей программой.

С форматированным потоком оператор чтения без спецификатора ADVANCE переходит к следующей записи, как READ с форматированным последовательным файлом. Из-за спецификации формата, связанной с READ, вы затем отбрасываете все, кроме первого символа, но основная позиция файла по-прежнему изменяется.

Поскольку у вас есть спецификатор POS с READ, каждый READ требует, чтобы среда выполнения переместилась назад от конца записи к следующему интересующему персонажу. Среда выполнения компилятора неправильно обрабатывает это.

Но вам не нужно, чтобы вы делали эту константу, перескакивая назад и вперед в файл - вместо этого, прежде чем читать, переместите файл в исходную точку (возможно, используя REWIND), а затем используйте непередвигающий ввод без спецификатора POS для постепенного прохождения символа файла по символу. Вам нужно будет соответствующим образом обработать код состояния IOSTAT_EOR, когда достигнут конец конкретной записи.

Обратите внимание, что для форматированного потока нет гарантии (зависит от процессора), что все положительные целые числа соответствуют действительной позиции в файле (F2008 9.3.3.4p4 bullet 5, см. Также Примечание 9.10). Это относится к структурам файлов, которые используют более одной позиции файла для таких вещей, как конец маркера записи (например, возможно, они используют CR-LF).

(Замечу, что вы также при условии, что по умолчанию персонажу занимает одно устройство для хранения файлов -., Что также процессор зависит)

program stream 
    implicit none 

    character(len=1)    :: text 
    integer(kind=4), dimension(100) :: array 
    integer(kind=4)     :: status = 0, i 

    open( & 
     unit=11, & 
     file='out.txt', & 
     form='formatted', & 
     access='stream', & 
     action='readwrite', & 
     status='replace') 

    array = [(i, i = 1,100)]   ! Populate vector from 1 to 100 

    write (unit=11, fmt='(10i4)') array ! Write array to file 

    rewind 11 
    do 
    read (unit=11, fmt='(a1)', iostat=status, advance='no') text 
    if (is_iostat_eor(status)) then 
     write (*, fmt="()") 
     cycle 
    else if (status /= 0) then 
     exit 
    end if 
    write (*,fmt='(a1)', advance='no') text ! write results to screen to see what is in each position 
    end do 

    close(unit=11) 

end program stream 
+0

Очень информативно, спасибо! –

Смежные вопросы