Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
современный фортран , Бортеньев.pdf
Скачиваний:
242
Добавлен:
26.03.2015
Размер:
2.34 Mб
Скачать

О. В. Бартеньев. Современный ФОРТРАН

write(4, '(e20.8)') 1.4e-6

! Длина записи 20 байт

rewind(4)

! Переход на начало файла

read(4, '(Q)') recl

! Читаем число байт в третьей записи

print *, recl

! 10

end

 

Результат (состав файла a.txt):

123 555

Next record 0.14000000E-05

10.7. Передача данных с продвижением и без

Оператор В/В с продвижением всегда устанавливает файл после последней считанной или записанной записи (если не было ошибок).

Оператор В/В без продвижения, применяемый при форматной передаче данных и задаваемый спецификатором ADVANCE = 'NO' или (при выводе) дескрипторами \ и $, может устанавливать файл внутри текущей записи. Используя такой оператор, можно прочитать или записать одну запись с помощью нескольких операторов В/В, причем каждый из них будет обращаться к части записи, например:

character(6) :: st1, st2

 

open(1, file = 'a.txt')

 

write(1, *) 'Test string'

! Вывод с продвижением

rewind 1

! Переход на начало файла

read(1, '(a6)', advance = 'no') st1

! Ввод без продвижения

print *, st1

! Test

read(1, '(a6)', advance = 'no') st2

! Ввод второго слова в ту же запись

print *, st2

! string

10.8. Позиция файла перед передачей данных

Порядок установки позиции файла перед передачей данных зависит от способа доступа к файлу.

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

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

336

10. Файлы Фортрана

При прямом доступе перед передачей данных позиция файла устанавливается в начало записи, определяемой спецификатором оператора В/В REC. Эта запись становится текущей.

10.9. Позиция файла после передачи данных

При вводе без продвижения, если не было ситуации ошибки или ситуации "конец файла", но есть ситуация "конец записи", позиция файла устанавливается после только что считанной записи. Если же в операторе ввода без продвижения не было ситуаций ошибки, "конец файла" или "конец записи", то позиция файла не меняется. В операторе вывода без продвижения, если не было ситуации ошибки, позиция файла не изменяется.

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

10.10. Двоичные последовательные файлы

При работе с двоичными файлами обмен данными выполняется без их преобразования. При записи в двоичный файл в него фактически копируется содержимое ячеек оперативной памяти. При чтении, наоборот, последовательность байтов двоичного файла передается в ячейки оперативной памяти, отведенные под элементы ввода. В FPS число записей в двоичном файле равно числу переданных байт. Поэтому выполнение оператора BACKSPACE приведет к перемещению на 1 байт назад. Последовательный двоичный файл является потоком. Между его записями CVF и FPS не проставляют символов или полей с контрольными данными.

Ввод из двоичного файла значения переменной val, занимающей в оперативной памяти n байт, вызовет перемещение файла на n байт.

Если последовательный двоичный файл перед выполнением оператора вывода находился на байте bi, то bi и все последующие байты в результате вывода будут "затерты" (заменены на выводимые).

Оператор OPEN, подсоединяющий файл к устройству для двоичного последовательного доступа, обязательно включает спецификатор FORM = form, где form - символьное выражение, вычисляемое со значением

'BINARY'.

Пример управления двоичным последовательным файлом FPS: integer(2) :: ia, ib, d(5) = (/ 1, 2, 3, 4, 5 /), i

real(4) :: a

 

character(3) ca

 

open(1, file = 'a.dat', form = 'binary')

! Открываем двоичный файл

write(1) 1.1, 2.2

! Пишем в файл 8 байт

write(1) d

! Добавляем в файл 10 байт

write(1) 'aaa', 'bbb', 'ccc'

! Добавим в файл еще 9 байт

337

О. В. Бартеньев. Современный ФОРТРАН

rewind 1

 

 

read(1) a, a, (ia, i = 1, 5), ca, ca

! Читаем 24 байта одним оператором READ

do 2 i = 1, 10

! Перемещение назад на 10 записей (байт)

2 backspace 1

 

 

read(1) ib

! Читаем, начиная с 15-го байта

write(*, *) a, ia, ca, ib

!

2.200000 5bbb 4

rewind 1

 

 

read(1) a

! Файл переместился на 5-й байт

write(1) 'ghi'

! Заменены 5, 6 и 7-й байты;

rewind 1

! все последующие записи "затерты"

read(1) a, ca

 

 

write(*, *) a, ca

!

1.100000ghi (в файле 7 байт данных)

end

 

 

Замечания:

1. В CVF при работе с двоичными файлами оператор BACSPACE либо вызывает ошибку исполнения, либо, подобно оператору REWIND, позиционирует файл в его начало, например:

character(1) c

 

 

open(1, file = 'a.dat', form = 'binary')

! Открываем двоичный файл

write(1) 'a12', 'b34'

! Добавим в файл 6 байт

rewind 1

! Переход на начало файла

read(1) c

 

 

print *, 'c = ', c

! CVF:

c = a

 

! FPS:

c = a

rewind 1

! Переход на начало файла

! Те же действия, но с оператором BACKSPACE

write(1) 'a12', 'b34'

! Добавим в файл 6 байт

backspace 1

 

 

read(1) c

 

 

print *, 'c = ', c

! CVF:

c = a

end

! FPS:

c = 4

2. Любой внешний файл может быть открыт как двоичный (поток), например с целью копирования данных.

10.11. Неформатные последовательные файлы

В неформатные файлы, так же как и в двоичные, данные передаются без преобразований. Однако в неформатном файле в отличие от двоичного записью является не байт, а совокупность данных, выводимых в файл в результате выполнения оператора вывода WRITE. Каждый оператор вывода создает одну запись. Записи файла могут иметь разную длину. Каждая запись завершается символами конца записи.

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

338

10. Файлы Фортрана

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

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

Добавление новой записи при позиционировании файла вслед за записью ri - 1 приведет к удалению записи ri и всех последующих записей (к их замене на добавляемую).

Оператор OPEN, подсоединяющий файл к устройству для неформатного последовательного доступа, включает спецификатор FORM = form, где form - символьное выражение, вычисляемое со значением 'UNFORMATTED'.

Пример управления неформатным последовательным файлом: integer(2) :: ia, ib, d(4) = (/ 1, 2, 3, 4 /)

real(4) a

 

character(3) ca

! Открываем неформатный файл

open(1, file = 'a.dat', form = 'unformatted')

write(1) 1.1, 2.2

! Добавление в файл 1-й записи

write(1) d

! Вторая запись

write(1) 'aaa', 'bbb', 'ccc'

! Третья запись

rewind 1

! Переход в начало файла

read(1) a, a

! Соблюдаем соответствие между

read(1) ia, ia, ia, ia

! вводом и выводом

read(1) ca, ca

 

backspace 1

! Переход в начало 3-й записи

backspace 1

! Переход в начало 2-й записи

read(1) ib, ib

 

print *, a, ia, ca, ib

! 2.200000 4bbb 2

rewind 1

 

read(1) a

! Переход в начало 2-й записи

write(1) 'ghi'

! Замена 2-й и 3-й записей на ghi

rewind 1

 

read(1) a, a

! В файле осталось 2 записи:

read(1) ca

! числа 1.1 и 2.2 и строка ghi

print *, a, ca

! 2.200000ghi

end

 

10.12. Текстовые последовательные файлы

Текстовой файл содержит символьное представление данных всех типов. При работе с текстовыми файлами используется форматный или управляемый списком В/В. При выводе данные из внутреннего представления преобразовываются во внешнее символьное представление. При вводе происходит обратное преобразование из символьного представления во внутреннее (разд. 9.1).

339

О. В. Бартеньев. Современный ФОРТРАН

При выводе в конце каждой записи Фортран проставляет два неотображаемых символа CHAR(13) - возврат каретки и CHAR(10) - новая строка,. То есть записи являются LF-потоками. В случае вывода под управлением списка оператор вывода вставляет в начало каждой записи пробел (по умолчанию первый символ каждой записи форматного файла рассматривается как символ управления кареткой). Записи текстового последовательного файла могут иметь разную длину.

Порядок изменения позиции текстового файла с последовательным доступом зависит от способа передачи данных (с продвижением или без,

разд. 10.6).

При форматном вводе число читаемых одним оператором ввода из текущей записи данных регулируется форматом (разд. 9.4). В отличие от неформатного файла одним оператором ввода в принципе может быть прочитано произвольное число записей текстового последовательного файла.

В простейшем случае, открывая текстовой файл для последовательного форматного доступа, можно указать в операторе OPEN только устройство внешнего файла и спецификатор FILE = file.

Пример управления текстовым последовательным файлом. (По умолчанию в файлах, открываемых для последовательного доступа,

спецификатор FORM = 'FORMATTED'.):

integer(2) :: ia, ib, d(4) = (/ 1, 2, 3, 4 /) real(4) a, b

character(3)ca

1format(6f7.2)

2format(8i5)

3format(7a4)

! Открываем последовательный текстовой файл a.txt и создаем в нем 3 записи

open(10, file = 'a.txt')

 

write(10, 1)

1.1, 2.2

! Запись 1

write(10, 2) d

! 2

write(10, 3)

'a', 'bc', 'def'

! и 3

!После выполнения трех операторов вывода в файле будет 3 записи:

!1.10 2.20

!

1

2 3 4

 

!

a

bc def

 

rewind 10

! Переход на 1-ю запись

read(10,

1) a, b

 

read(10,

2) ia, ia, ia

! Читаем из 2-й записи

! или вместо двух последних операторов: read(1, *) a, b, ia, ia, ia

read(10, 3) ca, ca

! Читаем из 3-й записи

backspace 10

! Переход на начало 3-й записи

backspace 10

! Переход на начало 2-й записи

read(10, 2) ib, ib

! Читаем в ib 2-й элемент 2-й записи

write(*, *) a, ia, ca, ib

! 1.100000 3 bc 2

rewind 10

! Переход на начало 1-й записи

340