Воспользуемся функцией >appendFile
на примере написания программы, которая добавляет в текстовый файл, содержащий список наших дел, новое задание. Допустим, у нас уже есть такой файл с названием todo.txt, и каждая его строка соответствует одному заданию.
Наша программа будет читать из стандартного потока ввода одну строку и добавлять её в конец файла todo.txt:
>import System.IO
>main = do
> todoItem <– getLine
> appendFile "todo.txt" (todoItem ++ "\n")
Обратите внимание на добавление символа конца строки вручную, функция >getLine
возвращает строку без него.
Сохраните этот файл с именем appendtodo.hs, скомпилируйте его и несколько раз запустите.
>$ ./appendtodo
>Погладить посуду
>$ ./appendtodo
>Помыть собаку
>$ ./appendtodo
>Вынуть салат из печи
>$ cat todo.txt
>Погладить посуду
>Помыть собаку
>Вынуть салат из печи
ПРИМЕЧАНИЕ. Программа >cat
в Unix-подобных системах используется для вывода содержимого текстового файла на терминал. В Windows можно воспользоваться командой >type
или посмотреть содержимое файла в любом текстовом редакторе.
Мы уже написали программу, которая добавляет новый элемент к списку заданий в файл todo.txt; теперь напишем программу для удаления элемента. Мы применим несколько новых функций из модуля >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"
Сначала мы читаем содержимое файла todo.txt и связываем его с именем contents. Затем разбиваем всё содержимое на список строк. Список >todoTasks
выглядит примерно так:
>["Погладить посуду", "Помыть собаку", "Вынуть салат из печи"]
Далее соединяем числа, начиная с >0
, и элементы списка дел с помощью функции, которая берёт число (скажем, >3
) и строку (например, >"привет"
) и возвращает новую строку (>"3 – привет"
). Вот примерный вид списка >numberedTasks
:
>["0 - Погладить посуду", "1 - Помыть собаку", "2 - Вынуть салат из печи"]
Затем с помощью вызова >mapM_ putStrLn numberedTasks