Мы помним, что тип FilePath – это просто удобное обозначение для String. Функция readFile принимает путь к файлу и возвращает действие ввода-вывода, которое прочитает файл (лениво, конечно же) и свяжет содержимое файла в виде строки с некоторым именем. Обычно это более удобно, чем вызывать функцию openFile и связывать дескриптор с именем, а затем вызывать функцию hGetContents. Вот как мы могли бы переписать предыдущий пример с использованием readFile:
import System.IO
main = do
contents <– readFile "girlfriend.txt"
putStr contents
Так как мы не получаем дескриптор файла в качестве результата, то не можем закрыть его сами. Если мы используем функцию readFile, за нас это сделает язык Haskell.
Функция writeFile имеет тип
writeFile :: FilePath –> String –> IO ()
Она принимает путь к файлу и строку для записи в файл и возвращает действие ввода-вывода, которое выполнит запись. Если такой файл уже существует, перед записью он будет обрезан до нулевой длины. Вот как получить версию файла
import System.IO
import Data.Char
main = do
contents <– readFile "girlfriend.txt"
writeFile "girlfriendcaps.txt" (map toUpper contents)
Функция appendFile имеет ту же сигнатуру, что и writeFile, и действует почти так же. Она только не обрезает уже существующий файл до нулевой длины перед записью, а добавляет новое содержимое в конец файла.
Список дел
Воспользуемся функцией appendFile на примере написания программы, которая добавляет в текстовый файл, содержащий список наших дел, новое задание. Допустим, у нас уже есть такой файл с названием
Наша программа будет читать из стандартного потока ввода одну строку и добавлять её в конец файла
import System.IO
main = do
todoItem <– getLine
appendFile "todo.txt" (todoItem ++ "\n")
Обратите внимание на добавление символа конца строки вручную, функция getLine возвращает строку без него.
Сохраните этот файл с именем
$ ./appendtodo
Погладить посуду
$ ./appendtodo
Помыть собаку
$ ./appendtodo
Вынуть салат из печи
$ cat todo.txt
Погладить посуду
Помыть собаку
Вынуть салат из печи
ПРИМЕЧАНИЕ. Программа cat в Unix-подобных системах используется для вывода содержимого текстового файла на терминал. В Windows можно воспользоваться командой type или посмотреть содержимое файла в любом текстовом редакторе.
Удаление заданий
Мы уже написали программу, которая добавляет новый элемент к списку заданий в файл System.Directory и одну новую функцию из модуля System.IO; их работа будет объяснена позднее.
import System.IO
import System.Directory
import Data.List
main = do
contents <– readFile "todo.txt"
let todoTasks = lines contents
numberedTasks = zipWith (\n line –> show n ++ " – " ++ line)
[0..] todoTasks
putStrLn "Ваши задания:"
mapM_ putStrLn numberedTasks
putStrLn "Что вы хотите удалить?"
numberString <– getLine
let number = read numberString
newTodoItems = unlines $ delete (todoTasks !! number) todoTasks
(tempName, tempHandle) <– openTempFile "." "temp"
hPutStr tempHandle newTodoItems
hClose tempHandle
removeFile "todo.txt"
renameFile tempName "todo.txt"
Сначала мы читаем содержимое файла todoTasks выглядит примерно так: