современный фортран , Бортеньев. О. В. Бартеньев Современный Фортран
Скачать 2.24 Mb.
|
344 10. Файлы Фортрана Один и тот же двоичный или неформатный файл может быть открыт с разными значениями спецификатора RECL. Пример: character(14) ch integer ner open(2, file = 'a.bin', access = 'direct', form = 'binary', recl = 8) write(2, rec = 1) 'C12-', '92' ! Пишем в файл 8 байт write(2, rec = 2) 'C16-', '99' ! Вторая запись двоичного файла ! Читаем 14 байт из двоичного файла, т. е. больше, чем задано RECL read(2, rec = 1) ch inquire(2, nextrec = ner) print *, ner ! 3 write(*, *) ch ! C12-92 C16-99 end ! Прочитать 14 байт из неформатного файла, ! открытого с RECL = 8, нельзя Приведенный текст в FPS может выглядеть так: character(14) ch integer ner open(2, file = 'a.bin', access = 'direct', form = 'binary', recl = 8) write(2) 'C12-', '92' ! Пишем в файл 8 байт write(2) 'C16-', '99' ! Вторая запись двоичного файла rewind 2 read(2) ch ! Читаем 14 байт из двоичного файла inquire(2, nextrec = ner) print *, ner ! 3 write(*, *) ch ! C12-92 C16-99 end В CVF этот код неприменим, поскольку, во-первых, операторы В/В не содержат спецификатор REC, а во-вторых, использован оператор REWIND, который в CVF употребляется только с последовательными файлами. В FPS текстовой прямой файл устроен так же, как и текстовой последовательный файл, в котором все записи имеют одинаковую длину. Поэтому текстовой файл с равными по длине записями может быть открыт в FPS как для прямого, так и для последовательного доступа. Пример. В текстовом файле, подсоединенном для прямого доступа, каждая запись имеет поля "Фамилия И. О.". По ошибке в некоторых записях фамилия начинается со строчной буквы. Исправить ошибку в исходном файле и сформировать отчет в виде двоичного файла, содержащего исправленные записи. integer(4), parameter :: n = 15 type person character(len = n) lastn, firstn end type person 345 О. В. Бартеньев. Современный ФОРТРАН type(person) line integer(4) :: code, dco, cco, ut = 2, ub = 3, ir 100 format(2a15) open(ut, file = 'a.txt', form = 'formatted', access = 'direct', recl = 2 * n) open(ub, file = 'b.dat', form = 'binary') ! Создадим две записи ! Запись без ошибки write(ut, fmt = 100, rec = 1) person('Blake', 'William') ! Запись с ошибкой write(ut, fmt = 100, rec = 2) person('maugham', 'W. Somerset') code = ichar('Z') ! 90 - ASCII-код символа Z dco = ichar('z') - code ! Вернет dco = 32 ir = 0 do ir = ir + 1 ! Номер текущей записи в прямом файле read(ut, fmt = 100, rec = ir) line ! или: read(ut, '(3a)', rec = ir) line cco = ichar(line.lastn(1:1)) if(cco > code) then ! Если первая буква фамилии строчная, то: line.lastn(1:1) = char(cco - dco) ! • переводим строчную букву в прописную; write(ut, fmt = 100, rec = ir) line ! • исправляем ошибку в исходном файле; write(ub) line ! • пишем в двоичный файл end if if(eof(ut)) exit ! Если ситуация "конец файла" end do close(ut) ! Закрываем прямой файл rewind ub ! Контрольный вывод do while(.not. eof(ub)) read(ub) line write(*, *) line end do close(ub) end Результат. Файл a.txt после исправлений (случай CVF; в случае FPS каждая запись размещается на отдельной строке): Blake William Maugham W. Somerset Пояснение. Строчные буквы в таблице ASCII расположены после прописных. Для получения ASCII-кода прописной буквы по известному коду строчной достаточно вычесть из кода строчной буквы dco: dco = ichar('z') - ichar('Z'). 10.14. Удаление записей из файла с прямым доступом Приводимые в разделе сведения применимы только в FPS, поскольку в обсуждаемом механизме присутствует оператор ENDFILE, неупотребляемый в CVF с прямыми файлами. 346 10. Файлы Фортрана Способ удаления завершающих записей из файла прямого доступа FPS был рассмотрен в предыдущем разделе. Удаление ненужных промежуточных записей можно выполнить, пользуясь методом, принятым в системах управления базами данных. Во-первых, необходимо иметь возможность отмечать удаляемые записи (а также снимать эту отметку). Для этой цели в записи можно выделить отдельное, однобайтовое поле, проставляя в него 1 (.TRUE.), если запись подлежит удалению, или 0 (.FALSE.), если нет. Далее необходимо будет написать процедуру, которая может работать, например, по следующему алгоритму: • обменять помеченные для удаления записи с записями, имеющими наибольшие номера; • установить файл перед первой помеченной для удаления записью и выполнить оператор ENDFILE. Запуск такой процедуры следует выполнять по мере необходимости, памятуя, что удаленные записи не могут быть восстановлены. 10.15. Выбор типа файла Двоичные и неформатные файлы имеют очевидные преимущества перед текстовыми: • передача данных выполняется быстрее, поскольку нет потерь на преобразование данных; • в текстовых файлах из-за округления могут возникнуть потери точности; • программировать двоичный и неформатный В/В значительно проще, чем форматный; • двоичные и неформатные файлы, как правило, имеют меньший размер, чем текстовые файлы с теми же данными. Последнее обстоятельство проиллюстрируем примером: real(4) :: a(20) = 1255.55 open(1, file = 'a.txt') write(1, '(5f8.2)') a ! Размер текстового файла 168 байт open(2, file = 'a.dat', form = 'binary') write(2) a ! Размер двоичного файла 80 байт end Программа создает два файла. В текстовом файле a.txt под данные занято 160 байт и дополнительно 8 байт (2*4) займут символы конца записи. Всего в файле a.txt будет создано 4 записи, каждая запись будет содержать 5 полей длиной по 8 символов. Размер двоичного файла a.dat составит 80 байт: всего в файл будет выведено 20 элементов по 4 байта каждый. То есть в случае двоичного файла имеем существенную экономию внешней памяти. 347 О. В. Бартеньев. Современный ФОРТРАН Текстовые файлы содержат данные в пригодной для чтения форме и также используются для обмена данными между программами, работающими в различных операционных системах. Примером такого рода обменных файлов являются DXF-файлы программы Автокад. Выбор способа доступа к файлу (последовательный или прямой) определяется характером решаемых задач. Если необходимо редактировать записи файла, или индексировать файл по одному или нескольким полям записи, или делать недоступными отдельные записи файла для других процессов, то используются файлы прямого доступа. 348 11. Операции над внешними файлами Внешний файл доступен из программы, если он, во-первых, открыт и, во-вторых, не заблокирован другим процессом. Файл открывается в результате подсоединения его к устройству В/В, которое, в свою очередь, создается (открывается) оператором OPEN. Столь же равнозначно можно говорить и о подсоединении устройства к файлу. Между устройством u и файлом file существует однозначное соответствие: все операторы Фортрана в любой программной единице, ссылающиеся на устройство u, получают доступ к файлу file. К устройству может быть подсоединен как существующий, так и вновь создаваемый файл. Нельзя подсоединить один и тот же файл к разным устройствам одновременно, так же как и нельзя одновременно подсоединить одно устройство к разным файлам. После того как файл открыт, с ним возможны операции: • позиционирования (BACKSPACE, REWIND, ENDFILE, READ, WRITE); • передачи данных (READ, WRITE, PRINT и ENDFILE); • изменения свойств подсоединения (оператор OPEN); • опроса (INQUIRE и EOF). Закрывается файл в результате выполнения оператора CLOSE или при нормальном завершении программы. Управляющие файлами и выполняющие их опрос операторы перечислены в табл. 11.1. Их подробное описания дано в последующих разделах. Таблица 11.1. Применяемые при работе с файлами операторы Оператор Назначение Операторы , применимые в CVF и FPS BACKSPACE Возвращает файл на одну запись назад REWIND Позиционирует файл в начало его первой записи ENDFILE Записывает специальную запись "конец файла" OPEN Создает устройство В/В и подсоединяет к нему внешний файл CLOSE Отсоединяет файл от устройства В/В и закрывает это устройство READ Выполняет передачу данных из файла, подсоединенного к устройству В/В, в указанные в списке ввода переменные WRITE Передает данные из списка вывода в файл, подсоединенный к устройству В/В Выводит данные на экран (устройство *) INQUIRE Возвращает свойства устройства или внешнего файла 349 О. В. Бартеньев. Современный ФОРТРАН Функция EOF Возвращает .TRUE., если подсоединенный к устройству В/В файл позиционирован на специальной записи "конец файла" или после этой записи. Иначе EOF возвращает .FALSE. Операторы , применимые в CVF ACCEPT Выполняет форматный ввод данных или ввод под управлением списка клавиатуры TYPE Синоним PRINT; все правила для PRINT переносятся на TYPE REWRITE Замещает текущую запись на новую в файлах прямого доступа FIND Позиционирует прямой файл на заданную запись DELETE Удаляет заданную запись связанного файла UNLOCK Освобождает запись файла, закрытую для доступа предшествующим оператором READ Приведенные операторы (кроме PRINT), а также функция EOF содержат в качестве одного из спецификаторов устройство, к которому подсоединяется файл в результате выполнения оператора OPEN. Этот спецификатор является обязательным. В то же время каждый из работающих с файлами операторов имеет и необязательные, рассматриваемые в настоящей главе спецификаторы. Целесообразность их употребления определяется как решаемыми задачами, так и требованиями к надежности программного продукта. При описании операторов их необязательные элементы заключаются в квадратные скобки. Символ | используется для обозначения "или". Замечание. В CVF операторы BACKSPACE, REWIND и ENDFILE употребляются только с файлами, открытыми для последовательного доступа, т. е. так, как это предусмотрено стандартом Фортрана. В FPS эти операторы можно вдобавок использовать с файлами прямого доступа. 11.1. Оператор BACKSPACE Оператор возвращает файл на одну запись назад и имеет две формы: BACKSPACE u и BACKSPACE([UNIT =] u [, ERR = err] [, IOSTAT = iostat]) u - устройство внешнего файла (разд. 10.2). err - метка исполняемого оператора. При возникновении ошибки В/В управление передается на оператор, имеющий метку err. iostat - целочисленная переменная, принимающая значение 0 при отсутствии ошибок. В противном случае iostat равняется номеру ошибки. При отсутствии подсоединения возникнет ошибка выполнения. 350 11. Операции над внешними файлами Оператор BACKSPACE позиционирует файл ровно на одну запись назад, кроме приведенных в табл. 11.2 случаев. Таблица 11.2. Специальные случаи позиционирования файла оператором BACKSPACE Случай Результат Нет предшествующей записи Положение файла не меняется Предшествующая запись - "конец файла" Файл позиционируется до записи "конец файла" Файл находится в пределах одной записи Файл перемещается в начало этой записи В FPS в файлах, содержащих вывод, выполненный под управлением именованного списка, BACKSPACE рассматривает список как множество записей, число которых равно числу элементов списка плюс две записи: одна - заголовок списка, другая - завершающий список слеш (/). Пример: integer :: lunit = 10, ios backspace 5 backspace(5) backspace lunit backspace(unit = lunit, err = 30, iostat = ios) Замечания: 1. В CVF оператор BACKSPACE употребляется только с файлами, подсоединенными для последовательного доступа. Вдобавок он не используется с записями, созданными под управлением списка, как именованного, так и без имени. 2. Если спецификатор UNIT= опущен, то параметр u должен быть первым параметром оператора. В противном случае параметры могут появляться в произвольном порядке. Это замечание справедливо для всех приводимых в этой главе операторов, имеющих спецификатор UNIT=. 3. Если параметром оператора является выражение, которое содержит вызов функции, то эта функция не должна выполнять В/В или функцию EOF. В противном случае результаты непредсказуемы. Это замечание распространяется на все приводимые в этой главе операторы. 11.2. Оператор REWIND Оператор перемещает файл в начало первой записи файла. REWIND u или 351 О. В. Бартеньев. Современный ФОРТРАН REWIND([UNIT =] u [, ERR = err] [, IOSTAT = iostat]) Описание параметров u, err и iostat см. в разд. 11.1. При отсутствии подсоединения оператор REWIND не вызывает никаких действий. Замечание. В CVF оператор REWIND употребляется только с файлами, подсоединенными для последовательного доступа. 11.3. Оператор ENDFILE Оператор записывает специальную запись "конец файла". ENDFILE u или ENDFILE([UNIT =] u [, ERR = err] [, IOSTAT = iostat]) Описание параметров u, err и iostat см. в разд. 11.1. Если файл не открыт, то возникает ошибка выполнения. После выполнения записи "конец файла" файл позиционируется вслед за этой записью. Дальнейшая последовательная передача данных станет возможной только после выполнения операторов BACKSPACE или RE- WIND. После выполнения оператора ENDFILE все записи, расположенные после новой записи "конец файла", становятся недоступными. В FPS это справедливо как для последовательных файлов, так и для прямых файлов. По понятным причинам ENDFILE нельзя применять с файлами, открытыми с ACTION | MODE = 'READ'. Замечание. В CVF оператор ENDFILE употребляется только с файлами, подсоединенными для последовательного доступа. 11.4. Оператор OPEN Оператор OPEN создает устройство В/В с номером u и подсоединяет к нему внешний файл file. При успешном подсоединении файл считается открытым и к нему может быть обеспечен доступ других работающих с файлами операторов Фортрана. Оператор может быть использован и для подсоединения ранее открытого файла с целью изменения свойств подсоединения. Отмеченные звездочкой спецификаторы оператора могут применяться только в CVF. OPEN([UNIT =] u [, ACCESS = access] [, ACTION = action] & [, ASSOCIATEVARIABLE = asv*] [, BLANK = blank] & [, BLOCKSIZE = blocksize] [, BUFFERCOUNT = bc*] & [, BUFFERD = bf*] [, CARRIAGECONTROL = carriagecontrol] & [, CONVERT = fm*] [, DEFAULTFILE = def*] [, DELIM = delim] & [, DISPOSE = dis*] [, ERR = err] [, FILE = file] [, FORM = form] 352 11. Операции над внешними файлами [, IOFOCUS = iofocus] [, IOSTAT = iostat] [, MAXREC = mr*] & [, MODE = mode] [, ORGANIZATION = org*] [, PAD = pad] & [, POSITION = position] [, READONLY*] [, RECL = recl] & [, RECORDTYPE = rtyp*] [, SHARE = share] [, SHARED*] & [, STATUS = status] [, TITLE = title] & [, USEROPEN = user-function-name*]) u - устройство внешнего файла (разд. 10.2), к которому подсоединяется файл file. access - символьное выражение, вычисляемое со значениями 'APPEND', 'DIRECT' или 'SEQUENTIAL' (по умолчанию) и определяющее способ доступа к файлу (последовательный - 'SEQUENTIAL' или прямой - 'DIRECT'). Спецификатор ACCESS = 'APPEND' применяется при работе с последовательными файлами, открываемыми для добавления данных. При успешном выполнении оператора OPEN с ACCESS = 'APPEND' файл позиционируется перед записью "конец файла". action - символьное выражение, задающее возможные действия с файлом и вычисляемое со значениями 'READ' (процесс может только читать данные из файла), 'WRITE' (возможен только вывод данных) или 'READ- WRITE' (можно и читать и записывать данные). ЕслиспецификаторACTIONне задан, то система пытается открыть файл для чтения-записи ('READWRITE'). Если попытка неуспешна, то система пытается открыть файл снова первоначально только для чтения ('READ'), затем только для записи ('WRITE'). Значение спецификатора STATUS не оказывает никакого влияния на action. asv - целочисленная переменная стандартного целого типа, называемая ассоциируемой переменной файла; обновляется после каждой передачи данных при работе с прямыми файлами и содержит номер следующей записи файла. Имеет эффект только в CVF с операторами READ, WRITE, FIND, DELETE и REWRITE. Например: integer(4) asv ! Ассоциируемая переменная файла character(8) :: st = 'A record' ! Создадим прямой файл с тремя записями open(1, file = 'c.dat', access = 'direct', form = 'formatted', recl = 9, & status = 'new', associatevariable = asv) write(1, '(a8)', rec = 1) st; write(1, '(a8)', rec = 2) st; write(1, '(a8)', rec = 3) st print *, asv ! 4 read(1, '(a8)', rec = 1) st print *, asv ! 2 blank - символьное выражение, вычисляемое со значениями 'NULL' или 'ZERO'. В случае 'NULL' (устанавливается по умолчанию) пробелы при форматном вводе данных игнорируются (вводится в действие дескриптор BN). В случае 'ZERO' пробелы при форматном вводе данных рассматриваются как нули (вводится в действие дескриптор BZ). Однако 353 О. В. Бартеньев. Современный ФОРТРАН если одновременно заданы параметр blank оператора OPEN и дескрипторы BN или BZ в спецификации формата оператора В/В, то дескриптор формата перекрывает действие параметра blank. blocksize - выражение стандартного целого типа, задающее размер внутреннего буфера в байтах. bc - скалярное целочисленное выражение, задающее число буферов, ассоциируемых с устройством В/В при многобуферной передаче данных. Возвращаемое выражением значение должно находиться в диапазоне от 1 до 127. По умолчанию задействован один буфер. Спецификатор BLOCKSIZE задает размер одного буфера. Общее число байт, ассоциируемых с заданными буферами, если, например, BLOCKSIZE = 2048 и BUFFERCOUNT = 3, равно 3 * 2048 = 6144. bf - символьное выражение, вычисляемое со значением 'YES' или 'NO', определяющее характер передачи данных. Если bf возвращает 'NO', то данные в файл будут посылаться после каждого выполнения оператора WRITE. В противном случае данные, если позволяет физическое устройство и вид файла, предварительно накапливаются во внутреннем буфере, что может повысить производительность приложения. По умолчанию размер буфера - 8192 байта, а в случае FPS - 1024 байта. Общий размер буфера может быть изменен спецификаторами BLOCKSIZE и BUFFERCOUNT. Внутренний буфер может увеличиваться, чтобы разместить целиком запись, и никогда не уменьшается. carriagecontrol - символьное выражение, задающее способ интерпретации первого символа каждой записи в форматных файлах. Выражение может вычисляться со значениями 'FORTRAN' или 'LIST'. По умолчанию устройство u подсоединяется к внешнему устройству, например к принтеру или монитору, с carriagecontrol = 'FORTRAN'. Это означает, что первый символ записи интерпретируется как символ управления кареткой печатающего устройства и не выводится ни на принтер, ни на экран (разд. 9.1). К внешним файлам по умолчанию подсоединение выполняется с car- riagecontrol = = 'LIST'. В случае 'LIST' первый символ записи уже не интерпретируется как символ управления кареткой и выводится и на принтере, и на экране. Если в OPEN также задан спецификатор FORM = 'UNFORMATTED' или FORM = 'BINARY', то спецификаторCARRIAGECONTROL игнорируется. fm - скалярное символьное выражение, задающее вид представления числовых неформатных данных и вычисляемое со значением 'LITTLE EN- DIAN', 'BIG ENDIAN', 'CRAY', 'FDX', 'FGX', 'IBM', 'VAXD', 'VAXG' или 'NATIVE'. Используется для приведения данных к соответствующему виду. def - скалярное символьное выражение, задающее используемый по умолчанию путь к открываемому файлу. Если завершающий слеш (/) опущен, то он будет добавлен. Если спецификатор DEFAULTFILE отсутствует, то используется текущая рабочая директория. |