- •Операции над внешними файлами
- •Оператор Read
- •Оператор Write
- •Оператор Close
- •Файлы последовательного доступа Форматные файлы
- •Неформатные файлы
- •Файлы прямого доступа
- •Добавление записи в файл прямого доступа.
- •Удаление записи из файла прямого доступа
- •Создание информационно-справочной системы
- •Выбор метода доступа в файле и типа записи
Неформатные файлы
Рассмотрим теперь неформатные файлы последовательного и прямого доступа.
Неформатный файл не может быть создан и просмотрен в текстовом редакторе. Для его создания обязательно нужна программа, т.к. данные хранятся в машинном представлении (данные передаются без преобразования). Метод доступа будет фигурировать в операторе open в спецификаторе access = ‘sequential/direct’, а формат в спецификаторе form = ' unformatted'.
Из неформатного файла одним оператором ввода можно прочитать только одну запись. Каждый оператор вывода создает одну запись.
Рассмотрим сначала неформатные файлы последовательного доступа.
Для этих файлов справедливы все правила, которые используются для обработки, корректировки, добавления и удаления текстовых файлов. Разница лишь в том, что чтение и запись осуществляется без формата. Кроме того, как уже упоминалось для их создания и просмотра нужна специальная программа.
Пример
В неформатном файле последовательного доступа хранятся вещественные числа. Удалить из файла наименьшее значение .
Удаление будем делать, используя вспомогательный файл.
Вообще лучше сделать в отдельном проекте неформатный файл и подключить его в свой проект, чтобы не создавать файл при каждом запуске программы.
!процедура создания неформатного файла
subroutine create_sq(n)
implicit none
integer, intent(in)::n
integer i
real x
open (50, file='isxseq.txt', access= 'sequential', form='unformatted', status='new')
do i=1,n
print*,'bb cislo'
read *,x
write(50 ) x
enddo
close(50)
end subroutine
subroutine view_sq()
implicit none
real x
open (10,file='isxseq.txt',form='unformatted',status='old')
print*,'fail sq'
do while (.not.eof (10))
read(10) x
print '(f3.0, 2x\)', x
enddo
close(10)
!11 print*,'ochibka open'
end subroutine
subroutine del_min ()
implicit none
real x, min
open (10, file= 'isxseq.txt', form= 'unformatted', status='old')
open (30, form='unformatted', status='scratch') !временный файл
!нахождение наименьшего значения в файле
read(10) min ! чтение из файла первой записи
do while (.not. eof (10))
read(10) x
if (x < min) min=x
enddo
!удаление с использованием временного файла
rewind(10)
do while (.not. eof (10))
read(10) x
if (x /= min) write(30 ) x
enddo
rewind (10)
rewind (30)
do while (.not. eof (30))
read(30) x
write(10)x
enddo
close(10)
close(30)
end subroutine
program main
implicit none
integer, parameter:: n=10 !количество создаваемых чисел
call create_sq (n)
print*,' исходный файл '
call view_sq()
call del_min()
print*,' файл после удаления'
call view_sq()
end program
Файлы прямого доступа
В файле, присоединенном для прямого доступа, все записи имеют одинаковую длину, которая задается в операторе open, спецификатором recl.
В операторе open для неформатного файла прямого доступа обязательно должны быть спецификаторы:
open (<номер устройства> , file='<имя файла>', access= 'direct' , recl= <размер записи>)
Для определения размера записи можно использовать функцию:
Sizeof (<имя переменной> (recl = Sizeof (<имя переменной>)
Спецификатор form=' unformatted ' в случае прямого доступа задается по умолчанию и может быть опущен.
В случае форматного файла прямого доступа, он обязателен form=' formatte '.
Каждая запись в файле прямого доступа имеет свой уникальный номер. Читать и записывать данные в файл прямого доступа можно необязательно по порядку их номеров. Можно в него занести запись с любым порядковым номером (например, сначала запись №5, а затем запись №2). Если в файле не было записей с №1 и 2, все равно под них будет зарезервировано место (при просмотре их значения равны нулю).
В неформатном файле прямого доступа можно позиционировать (установить указатель) непосредственно на запись с № n:
В CVF для этих целей можно использовать оператор find.
Find (<номер устройства>, rec=№ n)
Этот оператор только устанавливает указатель на нужную запись.
Или использовать оператор Read (<номер устройства>, rec=№ n), если хотим прочитать запись и ее анализировать.
При использовании оператора write будет заменена та запись, номер которой задан спецификатором rec=№ n.
Write (<номер устройства>, rec=№ n)<новая запись>
Пример
Запись в неформатный файл прямого доступа может производиться в любом порядке.
program main
implicit none
integer x, y, z, i, n
open(10,file='a.txt',form='unformatted',access='direct',recl=4,status='new')
y = 15
write(10, rec=2)88 !записали в файл на 2 место - 88
write(10, rec=5)y !записали в файл на 5 место – значение y
write(10, rec=5)111 !заменили в файле 15 на 111
do I = 1, 5
read(10, rec=i) x
print*, x !вывод файла на экран (5 записей)
enddo
read(10, rec=4) y !прочитали 4 –ую запись
print*, y !вывели ее на экран
!Добавим в файл запись.
write(10, rec =6) 20 !записали на 6 место - 20
!установили указатель на 1-ую запись
find(10, rec=1)
print*, ' полученный файл '
i=0 !счетчик записей
do while (.not. eof (10))
i=i+1 !формируем номер записи
read(10, rec= i) z !считываем очередную запись
print*, z
enddo
close(10)
end
Получили: 0 88 0 0 111 20 (на месте не введенных компонент - 0)
Создание и просмотр неформатных файлов последовательного и прямого доступа осуществляется только программным путем.
Для создания и просмотра неформатных файлов прямого доступа напишем отдельную программу. Для этого лучше создать отдельный проект. В дальнейших задачах будем использовать эти процедуры, подключая их в свой проект.
Еще один вариант использования оператора inquire:
Для контроля открытия файла можно использовать следующую последовательность операторов:
logical tf
inquire( filenum, opened=tf)
if (.not. tf)then
print*,'file not opened'
stop
endif
Opened – логическая переменная, которая возвращает значение TRUE при опросе файла, если файл присоединен к устройству и FALSE в противном случае.
Процедуры создания и просмотра неформатных файлов прямого доступа можно поместить в модуль и подключать модуль в свой проект при необходимости или поместить в файлах отдельно.
Модуль, в котором помещены процедуры создания и просмотра неформатных файлов прямого доступа:
module in_out_fil
contains
!создание неформатного файла прямого доступа
subroutine create_dir(n)
implicit none
integer,intent(in)::n
integer i
real x
open (30, file='new_dir.txt', access= 'direct', form='unformatted', recl=4, status='new', err=21)
do i=1, n
print*,'bb cislo'
read *, x
write(30, rec=i, err=22) x ! rec=i
enddo
print*, 'zapis ok'
close(30)
return
21 print*,'ochibka open dir'
stop
22 print*,'oshibka write'
end subroutine
!Процедура просмотра неформатного файла прямого доступа
subroutine view_dir()
implicit none
integer i
real x
i=0
open (60, file='new_dir.txt', access='direct', form='unformatted', recl=4, status='old', err=21)
print*,'исходный файл'
do while (.not. eof (60))
i=i+1
read (60, rec = i) x ! rec=i- обязательно
print '(F4.0, 2x\)', x !вывод на экран
enddo
close(60)
return
21 print*,'ochibka open'
stop
end subroutine
end module
Пример
Вещественные числа хранятся в неформатном файле прямого доступа. Заменить максимальное значение удвоенным произведением.
В этом случае корректировка производится без вспомогательного файла.
!замена max на 2*max в файле прямого доступа
! n- количество вводимых чисел
subroutine create_dir ( n )
implicit none
integer, intent(in):: n
integer i
real x
open (30, file='new_dir.txt', access= 'direct', form='unformatted', recl=sizeof (x), err=21)
do i=1, n
print*,'bb cislo'
read *, x ! считывание числа с клавиатуры в ОП
write(30, rec=i, err=22) x !запись из ОП в файл
enddo
print*, ' zapis ok'
close(30)
return
21 print*, 'ochibka open dir'
return
22 print*, 'oshibka write'
stop
end subroutine
subroutine view_dir()
implicit none
integer i
real x
i=0
open (60, file='new_dir.txt', access='direct', form='unformatted', recl=4, status='old', err=21)
print*,' f ail dir'
do while(.not. eof (60))
i=i+1
read(60, rec=i) x
print '(f4.0, 2x\)', x
enddo
close(60)
return
21 print*, 'ochibka open'
stop
end subroutine
! процедура замены
subroutine chenc()
implicit none
integer i, imax
real x, max
open (10, file='new_dir.txt', access='direct', form='unformatted', recl=4, status='old', err=21)
!нахождение наибольшего значения и номера записи
i=1
read(10, rec=i) max
imax=i
do while (.not. eof (10))
i=i+1
read(10, rec=i) x
if (x < max) then
max=x
imax=i
endif
enddo
read (10, rec= imax) x !прочитали из файла запись с № imax
x=2*x ! увеличили в 2 раза х в ОП
write(10, rec= imax) x !записали измененный х в файл
close(10)
return
21 print *, 'ochibka open'
stop
end subroutine
program main
implicit none
integer,parameter:: n=10
call create_dir (n)
print*,'isx fil'
call view_dir()
call chenc()
print*,'posle zameni'
call view_dir()
end
Пример
В неформатном файле прямого доступа хранятся целые числа. Поменять местами наименьшее значение с первым. Результат вывести на экран.
subroutine create_dir(n)
implicit none
integer,intent(in)::n
integer i
real x
open (30, file='new_dir.txt', access= 'direct', form='unformatted', recl=4, status='new', err=21)
do i=1, n
print*,'bb cislo'
read *, x
write(30, rec=i, err=22)x
enddo
print*, 'zapis ok'
close(30)
return
21 print*, 'ochibka open dir'
stop
22 print*, 'oshibka write'
stop
end subroutine
subroutine view_dir()
implicit none
integer i
real x
i=0
open (60, file='new_dir.txt', access='direct', form='unformatted', recl=4, status='old', err=21)
print*,'fail dir'
do while(.not. eof (60))
i=i+1
read(60, rec=i) x
print '(f4.0, 2x\)', x
enddo
close(60)
return
21 print*, 'ochibka open'
stop
end subroutine
subroutine chenc()
implicit none
integer i,imin
real x,min
open (10, file='new_dir.txt', access='direct', form='unformatted', recl=4, status='old', err=21)
read(10,rec=1)min
i=1
imin=1
do while(.not.eof (10)
i=i+1
read(1, rec=i) x
if (x<min) then
min=x
imin=i
endif
enddo
read (10, rec=1) x
write(10, rec=1) min
write(10, rec= imin) x
close(10)
return
21 print*,'ochibka open'
stop
end subroutine
program main
implicit none
integer,parameter::n=10
call create_dir (n)
print*,'isx fil'
call view_dir()
call chenc()
print*,'posle zameni'
call view_dir()
end
Записями (компонентами) неформатного файла прямого доступа могут быть массивы.
Пусть в файле хранятся два целочисленных массива по 5 элементов каждый. Напишем процедуру создания файла, в котором хранятся массивы из определенного количества элементов, а также процедуру просмотра этого файла.
program main
implicit none
integer, parameter:: narr=2, n=5 !количество массивов
call create_dir (narr, n)
print*,'isx fil'
call view_dir(n)
end
subroutine create_dir(narr, n)
implicit none
integer, intent(in):: narr, n !количество массивов
integer i
real x(n)
open (30, file= 'mas_dir.txt', access= 'direct', form='unformatted', recl=sizeof (x) , err=21)
do i=1, narr
print*,'введи’, i, ‘ –ый массив'
read *, x !чтение массива с клавиатуры
write(30, rec=i, err=22) x !запись массива в файл
enddo
print*, 'zapis ok'
close(30)
return
21 print*, 'ochibka open dir'
stop
22 print*, 'oshibka write'
stop
end subroutine
subroutine view_dir ( n )
implicit none
integer i
real x (n)
i=0
open (60, file='mas_dir.txt', access='direct', form='unformatted', recl=sizeof (x), err=21)
print*,'fail dir'
do while (.not. eof (60))
i=i+1
read(60, rec=i) x !чтение массива из файла
print*,i, ' massiv'
print '(f4.0, 2x\)', x !вывод массива на экран
enddo
close(60)
return
21 print*, 'ochibka open'
stop
end subroutine