4. Потоки и файлы

 

Потоки и файлы

 

Система Mathematica имеет развитые средства для работы с потоками (streams) и файлами (files). Под потоком подразумевается непрерывная последовательность данных, циркулирующих внутри компьютера. Обмен потоками происходит практически непрерывно, например, при вводе поток ввода поступает от клавиатуры в компьютер, при печати поток данных поступает от компьютера в принтер через порт принтера и т. д.

Файлом является упорядоченная структура данных, имеющая имя и хранящаяся на каком-либо носителе, чаще всего на магнитном диске. Файлы могут иметь различные форматы и различный тип доступа к хранимой на них информации. Наиболее распространенные в системе Mathematica файлы документов являются файлами с последовательным доступом и имеют текстовый формат.

Последовательный доступ означает, что информация из открытого файла может быть считана строго последовательно от его начала до конца, отмеченного специальной меткой. Это напоминает считывание с магнитофонной кассеты. Текстовый формат означает, что все данные записаны в виде ASCII-кодов. Следовательно, прочесть такой файл можно с помощью любого текстового редактора, работающего с текстами в виде ASCII-кодов.

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

Упрощенная работа с файлами

Прежде чем рассматривать весьма обширные возможности системы по работе с файлами в целом, отметим упрощенный прием вызова файла с помощью двойного символа «<<»:


<<filename

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


Get["filename", key]

Для записи объекта (переменной, массива, списка и т. д.) в файл служат упрощенные команды:

  • expr >> filename — передает значение ехрг в файл с заданным именем;
  • ехрг >>> filename — добавляет ехрг в конец файла с заданным именем.

Указанные команды по существу есть укороченные (и потому более удобные) формы следующих функций:

  • Get ["filename", "key"] — читает файл, который закодирован функцией Encode с использованием ключа "key";
  • GetContext [ "context' " ] — загружает файл с заданным контекстом;
  • Put[exprl, expr2, ..., "filename"] — записывает последовательность выражений expri в файл с именем filename;
  • PutAppend[expr1, expr2, ..., "filename"] — присоединяет последовательность выражений expri к файлу с именем filename.

Еще одна упрощенная функция — ! ! filename — выводит содержимое файла с заданным именем.

Следующие примеры показывают запись списка в файл C:\ma.vat, его считывание, затем добавление в файл еще одного списка и контроль контекста файла:


{{l,2,3},{4,5,6},{a,b,c}}>>C:\ma.val

<<С: \ma. val

{{1, 2, 3}, {4, 5, б), {а, b, с}} {d,e,f}>>>C: \ma.val

<<С: \та. val

{d, e, f}

!!С:\mа.val

1, 2, 3, 4, 5, б, а, b, с d, e, f

Такая форма вызова особенно удобна для вызова файлов пакетов расширений и применений системы. Имя файла указывается по правилам, принятым в MS-DOS. Файлы пакетов применений имеют расширение .т. Мы уже приводили примеры использования определений, содержащихся в файлах пакетов расширения системы.

Имеется еще ряд функций для работы с файлами:

  • ReadList ["filename" ] — читает все оставшиеся в файле "filename" выражения и возвращает их в виде списка;
  • ReadList ["filename", type] — читает из файла "filename" объекты указанного типа type до конца файла. Возвращает список считанных объектов;
  • ReadList ["filename", {typel, type2,...}] — читает объекты указанных типов type1 до конца файла filename;
  • ReadList [ "filename", types, n] — читает только первые п объектов указанных типов types из файла filename;
  • Save ["filename", x1, x2,...] — создает файл с заданным именем filename, содержащий значения переменных x1, х2, ...;
  • ! command — исполняет заданную команду операционной системы.

Допустим, что в любом текстовом редакторе создан файл с полным именем C:\datas.txt в ASCII-формате, содержащий просто шесть чисел с разделительными пробелами, размещенные в двух строках и представляющие массив 2x3 элемента:


1 11.2 34.5

2. 3.4 56

Тогда о структуре файла можно судить, используя команду


!!С:\datas.txt

1 1.2 34.5 2. 3.4 56.

Нетрудно заметить, что структура файла соответствует структуре массива. Однако считывание файла командой «name дает следующий результат:


<<С: \datas. txt

380.8

Результат представляет вычисленное выражение второй строки файла. Считывание функцией ReadList без дополнительного аргумента также дает ошибочный результат:


ReadList["С:\datas.txt"]

{41.4, 380.8}

Нетрудно подметить, что функция восприняла каждую строку содержимого файла как результат перемножения трех чисел (пробел на языке Mathematica означает умножение). С дополнительным параметром Number все числа считываются верно:


ReadList["С:\datas.txt", Number]

{1, 1.2, 34.5, 2., 3.4, 56.}

Однако мы получили одномерный список — данные просто считываются построчно. Применение дополнительного параметра в виде {Number, Number} дает следующий результат:


ReadList["С:.txt", {Number, Number}]

{{1, 1.2), {34.5, 2.}, {3.4, 56.}}

Правильный результат можно получить, используя опцию RecordList->True: .


ReadList["C:.txt",Number,RecordLists-XTrue]

{{1, 1.2, 34.5), {2., 3.4, 56.}}

Для загрузки файлов пакетов расширений (Add-On) используются функции, позволяющие задать контекст файлов (подробнее о контекстах речь пойдет в уроке 10):

  • Needs ["context' ", "filename"] — загружает файл, если указанный контекст отсутствует в списке загруженных;
  • Needs [ "context s " ] — загружает файл, имя которого определяется с помощью функции ContextToFilename [ "context ч " ], если указанный контекст отсутствует в списке загруженных.

Загрузка файлов с указанием их контекстов позволяет избежать конфликтов между разными пакетами расширения, используемыми одновременно (см. более подробно урок 10).