Поиск

Чтение данных из файла

В Perl существует несколько способов чтения файлов, определенных дескрипторами. Самый распространенный заключается в использовании оператора файлового ввода, называемого еще угловым оператором (<>). Длячтения информации из файла достаточно поместить его дескриптор в угловые скобки и присвоить это значение переменной, например:

Угловой оператор в скалярном контексте читает одну строку из файла. Если файл заканчивается, угловой оператор возвращает значение undef.

Строкой в текстовом файле называется последовательность символов, ограниченная специальным признаком конца строки. В UNIX таким признаком является символ перевода строки (ASCII-код 10), в DOS и Windows— последовательность символов возврата каретки и перевода строки (ASCII-коды: 13 и 10). Знамение стандартного признака конца строки может быть изменено в Perl, что позволяет добиться некоторых интересных эффектов. Подробнее об этом речь пойдет на 12-м занятии, "Работа с командной строкой Реrl.

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

Для чтения информации из файла удобно использовать цикл while. Если в цикле while вместо условного выражения используется угловой оператор, Perl автоматически присваивает введенную строку специальной переменной $_ и повторяет цикл, пока файл не закончится:

При этом на оператор while возлагается присваивание введенной строки переменной $_ и проверка признака достижения конца файла. Такое интересное поведение случается только в цикле while и лишь тогда, когда условное выражение состоит из углового оператора.

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

В контексте списка угловой оператор читает файл целиком и присваивает его списку. Каждая строка файла присваивается соответствующему элементу списка или массива, как показано ниже:

В этом примере через дескриптор MYFILE считываются все данные из файла novel.txt и присваиваются массиву {(contents. При этом первая строка файла novel.txt присваивается первому элементу массива (!contents: $contents [ 0 ]. Вторая строка присваивается $contents[l] и т.д.

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

Поместим в тестовый файл testfile следующий текст:

Тогда программа из листинга 5.1 выведет:

Проведем анализ программы.

  • Строка I. В этой строке находится путь к интерпретатору (измените его в соответствии с конфигурацией вашей системы) и ключ -w. Всегда включайте режим вывода предупреждений!
  • Строка 3. Открывается файл testfile, которому назначается дескриптор MYFILE. Если файл не может быть корректно открыт, выполняется функция die, выводящая сообщение об ошибке.
  • Строка 4. Все содержимое файла testfile читается в массив Sstuff.
  • Строка 5. Поскольку содержимое файла testfile успешно прочитано, файл можно закрыть и освободить дескриптор MYFILE.
  • Строка 7. Из массива @stuff создается список с обратным порядком следования элементов — первая строка становится последней и т.д., затем полученный список используется в операторе foreach. Каждая строка этого списка поочередно присваивается переменной $_, после чего выполняется тело цикла foreach.
  • Строка 8. Изменяется порядок следования символов строки файла (которая находится в переменной $_), после чего выполняется ее печать. Функция scalar в данном случае необходима, так как по умолчанию функция print ожидает получить список, а в контексте списка функция reverse инвертирует порядок следования элементов списка. Поэтому порядок следования символов переменной $_ остался бы неизменным. Функция scalar определяет скалярный контекст для функции reverse, изменяющей порядок следования символов в $_.

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

Если при чтении в массив слишком большого файла или выполнении каких-нибудь других действий доступная для Perl память будет исчерпана, интерпретатор выдаст сообщение об ошибке Out of memory! и прекратит выполнение программы. Если это произойдет при чтении всего файла в массив, вам следует подумать о построчной обработке файла.