Изучай Haskell во имя добра! (Липовача) - страница 134

принимает дескриптор и применяет к нему функцию >f, которая по заданному дескриптору делает с файлом всё необходимое, будь то его чтение или запись.

Хватай дескрипторы!

Подобно тому как функция >hGetContents работает по аналогии с функцией >getContents, но с указанным файлом, существуют функции >hGetLine, >hPutStr, >hPutStrLn, >hGetChar и т. д., ведущие себя так же, как их варианты без буквы >h, но принимающие дескриптор как параметр и работающие с файлом, а не со стандартным вводом-выводом. Пример: >putStrLn – это функция, принимающая строку и возвращающая действие ввода-вывода, которое напечатает строку на терминале, а затем выполнит перевод на новую строку. Функция >hPutStrLn принимает дескриптор файла и строку и возвращает действие, которое запишет строку в файл и затем поместит в файл символ(ы) перехода на новую строку. Функция >hGetLine принимает дескриптор и возвращает действие, которое считывает строку из файла.

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

Сигнатура функции >readFile такова:

>readFile :: FilePath –> IO String

Мы помним, что тип >FilePath – это просто удобное обозначение для >String. Функция >readFile принимает путь к файлу и возвращает действие ввода-вывода, которое прочитает файл (лениво, конечно же) и свяжет содержимое файла в виде строки с некоторым именем. Обычно это более удобно, чем вызывать функцию >openFile и связывать дескриптор с именем, а затем вызывать функцию >hGetContents. Вот как мы могли бы переписать предыдущий пример с использованием >readFile:

>import System.IO


>main = do

>   contents <– readFile "girlfriend.txt"

>   putStr contents

Так как мы не получаем дескриптор файла в качестве результата, то не можем закрыть его сами. Если мы используем функцию >readFile, за нас это сделает язык Haskell.

Функция >writeFile имеет тип

>writeFile :: FilePath –> String –> IO ()

Она принимает путь к файлу и строку для записи в файл и возвращает действие ввода-вывода, которое выполнит запись. Если такой файл уже существует, перед записью он будет обрезан до нулевой длины. Вот как получить версию файла girlfriend.txt в верхнем регистре и записать её в файл girlfriendcaps.txt:

>import System.IO

>import Data.Char


>main = do

>   contents <– readFile "girlfriend.txt"

>   writeFile "girlfriendcaps.txt" (map toUpper contents)

Функция >appendFile имеет ту же сигнатуру, что и >writeFile, и действует почти так же. Она только не обрезает уже существующий файл до нулевой длины перед записью, а добавляет новое содержимое в конец файла.