Шаг 57.
Основы логического программирования.
Работа с файлами

    На этом шаге мы рассмотрим работу с файлами.

    На этом шаге мы опишем несколько других предикатов для работы с файлами. Это предикаты filepos, eof, flush, existfile, deletefile, renamefile, disk и copyfile.

Предикат filepos

    Предикат filepos может управлять позицией, где производится чтение или запись. Он имеет формат:

   filepos(SymbolicFileName,FilePosition,Mode) % (i,i,i),(i,o,i)

    Если FilePosition - связанная переменная, предикат может изменить позицию чтения и записи для файла с именем SymbolicFileName. Если при вызове FilePosition является свободной переменной, то SymbolicFileName возвращает текущую позицию в файле.

    Mode является целой величиной и указывает, как должно интерпретироваться (согласно таблице 1) значение FilePosition.

Таблица 1. Интерпретация значения FilePosition
Mode FilePosition
0 Относительно начала файла
1 Относительно текущей позиции
2 Относительно конца файла (конец файла соответствует позиции 0)

    Когда возвращается FilePosition, то filepos возвращает позицию относительно начала файла независимо от значения Mode.

Предикат eof/1

    Предикат eof проверяет, является ли позиция, полученная в процессе чтения, концом файла. В этом случае eof успешен. В противном случае он терпит неуспех. Предикат eof имеет вид:

   eof(SymbolicFileName) % (i)

eof выдает ошибку во время выполнения, если файл был открыт с правами только на запись. Обратите внимание, что предикат не придает особого значения символу конца файла DOS (комбинация клавиш Ctrl+Z).

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

   predicates
      repfile(FILE)
   clauses
      repflie(_). 
      repfile(F) :-
         not(eof(F)),
         repfile(F).
    Следующая программа преобразует один файл в другом все буквы которого являются заглавными.
   domains
      file=input; output
   predicates
      convert_file
      repfile(FILE)
   clauses
      convert_file:-
         repfile(input),
         readln(Ln), % Перевод букв строки в заглавные
         upper_lower(LnInUpper,Ln) ,
         write(LnInUpper),nl,
         fail.
     convert_file.
     repfile(_).
     repfile(F):-
        not(eof(F)),
        repfile(F).
   goal
     write("Which file do you want convert?"),
     readln(InputFileName),nl,
     write("What is the name of the output file?"),
     readln(OutputFileName),nl,
     openread(input,InputFileName),
     readdevice(input),
     openwrite(output,OutputFileName),
     writedevice(output),
     convert_file,
     closefile(input),
     closefile(output).
    Текст этой программы можно взять здесь.

Предикат flush/1

    Предикат flush записывает содержимое внутреннего буфера в именованный файл. Он имеет формат.

   flush(SymbolicFileName) % (i)
    Он же запрашивает систему "сбросить все буферы".

Предикат existfile/1

    Предикат existfile выполняется успешно, если файл OSFileName будет найден. Формат его следующий:

   existfile(OSFileName) % (i)

    Предикат OSFileName может содержать каталог, а само имя может содержать знаки подстановки, как c:\psys\*.cfg. Предикат existfile завершается неуспешно, если имя файла не найдено в обозначенном пути каталога. Однако, заметьте, несмотря на то, что existfile находит все файлы, включая файлы с установленными атрибутами "system" (Системный) и "hidden" (Скрытый), он не находит каталоги.

    Для проверки того, что файл присутствует на диске (прежде чем открывать его), вы можете воспользоваться:

   open(File, Name):-
      existfile(Name), 
      !,
      openread(File,Name).
   open(_, Name):-
      writeName("Error: the file",Name," is not found").

Предикат deletefile/1

    Предикат deletefile удаляет файл, заданный его аргументом, и имеет формат:

   deletefile(OSFileName) % (i)

    Предикат deletefile даст ошибку, если не сможет удалить файл. OSFileName не может содержать подстановочные символы.

Предикат renamefile/1

    Предикат renamefile переименовывает файл с именем OldOSFileName в NewOSFileName. Он имеет формат:

   renamefile(OldOSFileName, NewOSFileName) %(i,i)

    Предикат renamefile будет успешен, если файл с именем NewOSFileName не существует, и оба имени являются допустимыми файловыми именами. В противном случае будет выдана ошибка.

Предикат disk/1

    Предикат disk используется для изменения текущего диска и/или каталога/подкаталога и имеет формат:

   disk(Path) %(i),(о)

    При вызове со свободной переменной в качестве параметра, disk возвратит текущий каталог. В DOS-ориентированных версиях для переключения на другой диск без изменения существующего текущего каталога на этом диске используйте D:. Здесь D - буква, обозначающая устройство.

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




Предыдущий шаг Содержание Следующий шаг