Шаг 56.
Основы логического программирования.
Файловая система в Прологе

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

    На этом шаге мы представим вам файловую систему в Прологе и стандартные предикаты, обращающиеся с файлами. Познакомимся с переназначением ввода/вывода - эффективным методом связи ввода и вывода с различными устройствами.

    Пролог использует current_readdevice (текущее устройство чтения), с которого считывается ввод, и current_write_device (текущее устройство записи), на которое посылается вывод. Как правило, текущим устройством чтения является клавиатура, а текущим устройством записи - экран дисплея. Однако вы можете назначить другие устройства. Например, ввод может читаться из файла, хранимого во внешней памяти (возможно, на диске). Можно даже переопределить устройства текущего ввода и вывода во время исполнения программы.

    Независимо от того, какими устройствами чтения и записи вы пользуетесь, в программе на Прологе чтение и запись обрабатываются идентично. Для доступа к файлу вы должны сначала его открыть. Файл может быть открыт:

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

    Когда Пролог открывает файл, он связывает символическое имя с действительным именем файла операционной системы и использует это символическое имя для направления ввода и вывода. Символические имена файлов должны начинаться с маленькой буквы и должны быть объявлены в описании домена file. Например:

   file=file1; source; auxiliary; somethingElse

    В любой программе разрешен только один домен file. Пролог распознает пять встроенных альтернатив file, описанных в таблице 1.

Таблица 1. Встроенные альтернативы домена file
Альтернатива Описание
keyboard Чтение с клавиатуры (по умолчанию)
screen Запись в монитор
stdin Чтение из стандартного ввода
stdout Запись в стандартный вывод
stderr Запись на стандартное устройство для вывода ошибок

    Эти встроенные альтернативы не должны встречаться в описании file. Открывать и закрывать их не требуется.

Открытие и закрытие файлов

    Следующие разделы описывают стандартные предикаты для открытия и закрытии файлов.


    Замечание. Во время открытия файла необходимо помнить, что обратный слэш (\), используемый для указания подкаталога диска, в DOS-ориентированных версиях Пролога является ESC-символом (управляющим). Поэтому при указании пути доступа файла в программе нужно всегда указывать два обратных слэша (\\).

    Например, строка:

    "с:\\prolog\\include\\iodecl.con"

    представляет путь доступа к файлу:

    с:\prolog\include\iodecl.con

Предикат openread/2

    Предикат openread открывает файл OSFileName дли чтения, используя формат:

   openread(SymbolicFileName,OSFileName) % (i, i)

    Пролог обращается к открытому файлу по символическому имени SymbolicFileName, объявленному в домене file. Если файл не может быть открыт, Пролог выдаст сообщение об ошибке.

Предикат openwrite/2

    Предикат openwrite открывает файл OSFileName для записи, используя формат:

   openwrite(SymbolicFileName,OSFileName) % (i,i)

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

Предикат openappend/2

    Предикат openappend открывает файл OSFileName для записи в конец файла. При этом используется формат:

   openappend(SymbolicFileName,OSFileName) % (i,i)

    Если файл не может быть открыт на запись, Пролог сообщит об ошибке.

Предикат openmodify/2

    Предикат openmodify открывает файл OSFileName и для записи, и для чтения; если файл уже существует, он не будет перезаписан, openmodify имеет формат:

   openmodify(SymbolicFileName,OSFileName) % (i,i)

    Если система не может открыть OSFileName, Пролог сообщит об ошибке. Для заполнения файла с произвольным доступом предикат openmodify может использоваться вместе со стандартным предикатом filepos.

Предикат filemode/2

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

   filemode(SymbolicFileName,FileMode) % (i,i)

    Если FileMode=0, файл SymbolicFileName устанавливается в двоичный режим; если FileMode=1, то он устанавливается в текстовый режим.

    В текстовом режиме при записи к новым строкам добавляются символы "возврат каретки"\"перевод строки", а при чтении эта пара символов интерпретируется как новая строка.

    Carriage return (возврат каретки) = ASCII 13
    Line feed (перевод строки) = ASCII 10

    В двоичном режиме никаких преобразований не производится. Для чтения двоичного файла вы можете использовать только предикат readchar или предикаты для доступа к двоичным файлам.

Предикат closefile/1

    Предикат closefile закрывает указанный файл; он использует формат:

   closefile(SymbollcFileName) % (i)

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

Предикат readdevice/1

    Предикат readdevice переопределяет current_read_device (текущее устройство чтения) или возвращает его имя. Предикат имеет формат:

   readdevice(SymbolicFileName) % (i), (о)

    Предикат readdevice переопределяет текущее устройство чтения, если переменная SymbolicFileName определена, и файл открыт для чтения. Если SymbolicFileName является свободной переменной, то readdevice присвоит ей имя текущего активного устройства чтения.

Предикат writedevice/1

    Предикат writedevice либо назначает, либо позволяет получить имя current_ write_device (текущего устройства записи). Он имеет формат:

   writedevice(SymbolicFileName) % (i), (о)

    Предикат writedevice переопределит устройство записи, если указанный файл открыт для записи или добавления. Если переменная SymbolicFileName свободна, writedevice присвоит ей имя текущего активного устройства записи.


    Примеры открытия файла, записи в файл и закрытия файла:

  1. Следующая последовательность открывает файл MYDATA.FIL для записи, затем направляет весь вывод, порождаемый операторами между двумя предикатами writedevice, в этот файл. MYDATA.FIL соответствует символическому имени destination, появляющемуся в описании домена file.
       domains
          file=destination
       goal
          openwrite(destination, "MYDATA.FIL"),
          writedevice(OldOut), % Получаем текущее устройство вывода
          writedevice(destination), % Перенаправляем вывод в файл
             :
             :
          writedevice(OldOut), % Восстанавливаем устройство вывода
    
  2. Программа помещает символы, набранные наклавиатуре, в файл TRYFILE.ONE на текущем диске, использует стандартные предикаты read и write. Набираемые символы не выводятся на экран дисплея. Для вас будет хорошим упражнением написать программу, которая выводила бы эти символы и на экpaн. Файл закрывается при нажатии клавиши #.
       domains
          file=myfile
       predicates 
          readloop
       clauses
          readloop:-
             readchar(X),
            X<>'#',
            !,
            write(X),
            readloop.
          readloop.
       goal
          write("This program reads your input and writes it to"),nl,
          write("tryflie.one. For stop press #"),nl,
          openwrite(myfile,"tryfile.one") ,
          writedevice(myfile),
          readloop,
          closefile(myfile),
          writedevice(screen),
          write("Your input has been transferred to the file tryflie.one"),
          nl.
    
        Текст этой программы можно взять здесь.

Переопределение стандартного ввода/вывода

    Домен file имеет три дополнительные опции: stdin, stdout, stderr. Преимущество этих файловых потоков в том, что вы можете переназначить стандартный ввод/вывод в командной строке (таблица 2).

Таблица 2. Файловые потоки
Файловый поток Описание
stdin Стандартный ввод является файлом, доступным только для чтения. По умолчанию это клавиатура, readdevice(stdin) назначает устройством ввода stdin
stdout Стандартный вывод является файлом, доступным только для записи. По умолчанию это экран терминала, writedevice(stdout) назначает устройством ввода stdout
stderr Стандартный вывод ошибок является файлом, который доступен только для записи. По умолчанию это экран терминала. Writedevice(stderr) назначает устройством для вывода сообщений об ошибках stderr

    На следующем шаге мы начнем рассматривать работу с файлами.




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