| English | Русский |
|---|---|
| file/faɪl/ | файл |
| text file/tekst faɪl/ | текстовый файл |
| secondary storage/ˈsekəndəri ˈstɔːrɪdʒ/ | вторичное хранилище |
| persistence/pəˈsɪstəns/ | устойчивости |
| end of file/end ɒv faɪl/ | конец файла |
| separator/ˈsepəreɪtə/ | разделитель |
| sequential/siːˈkwenʃl/ | секвенциальный |
Игра, которая помнила
- До 1987 года выключение игровой консоли стирало всё. Каждая сессия начиналась с первого экрана; длинная игра означала долгий день или ничего.
- The Legend of Zelda поставлялась с маленькой батарейкой внутри картриджа, поддерживавшей работу нескольких сотен байт. Впервые домашняя игра могла сохранять прогресс и продолжать с того места, где она была прервана.
- Каждое рекордное значение, каждый документ, каждая настройка, которые вы когда-либо сохраняли, существуют по той же причине: ОЗУ забывает данные при отключении питания, а файл — нет.
- Этот урок объясняет, зачем нужны файлы и как псевдокод читает и записывает текстовый файл, строку за строкой.
Зачем нужны файлы
- Переменные живут в ОЗУ и исчезают после завершения программы. Файл на вторичном носителе сохраняет данные между запусками программы: персистентность (постоянство).
- Файлы позволяют вывод одной программы стать входными данными другой, обеспечивая совместное использование данных.
- Файл может хранить больше, чем помещается в памяти, а программа может возобновить работу из сохраненного состояния.

Переменная исчезает в конце выполнения; файл остается там и завтра
Почему программа записывает данные в файл вместо хранения их в переменной?
ОЗУ является энергозависимой памятью, поэтому данные теряются при выходе. Файл на вторичном носителе сохраняется между запусками.
Текстовые файлы и три режима
- Текстовый файл хранит данные в виде строк символов, которые программа читает и записывает по одной строке, начиная с начала. Последовательность этих строк позволяет циклу обрабатывать файл последовательно.
OPENFILE … FOR READчитает с первой строки.FOR WRITEсоздает новый файл или перезаписывает существующий.FOR APPENDдобавляет новые строки в конец, сохраняя имеющееся содержимое.- Открывайте перед использованием, закрывайте после. У файла может быть только один режим одновременно.
Соотнесите каждый режим открытия файла с его функцией.
READ читает; WRITE заменяет с нуля; APPEND добавляет в конец, не теряя того, что там есть.
Чтобы добавить строки в конец существующего файла без потери его содержимого, откройте его в режиме ____.
WRITE создал бы файл пустым. APPEND сохраняет то, что там есть, и записывает после него.
Чтение каждой строки
OPENFILE "data.txt" FOR READ
WHILE NOT EOF("data.txt") DO
READFILE "data.txt", LineString
OUTPUT LineString
ENDWHILE
CLOSEFILE "data.txt"
EOFпроверяет конец файла. Проверяйте это перед каждым чтением: чтение за пределами конца является ошибкой.CLOSEFILEимеет значение: буферизированные данные могут быть потеряны, а другие программы лишены доступа к файлу, который остался открытым.
Обработка файла: открытие → использование → закрытие
Пройдите по жизненному циклу, которому следует каждый файл. Две легко упускаемые части — это проверка EOF во время чтения в цикле и обязательное закрытие в конце.
Для чего служит проверка EOF?
EOF (конец файла) проверяется перед каждым чтением, чтобы цикл останавливался, когда нет больше данных.
Почему нужно всегда закрывать файл после использования?
Закрытие выводит буферизированные записи на диск и освобождает блокировку, позволяя другим программам использовать файл.
Запись строк
OPENFILE "log.txt" FOR WRITE
FOR i ← 1 TO 100
WRITEFILE "log.txt", "Event " & NUM_TO_STR(i)
NEXT i
CLOSEFILE "log.txt"
WRITEначинает файл пустым. Чтобы добавить запись в журнал, который должен сохранять историю, откройте его вместо этого в режимеFOR APPEND.- Текстовый файл содержит строки: число преобразуется с помощью
NUM_TO_STRпри записи.
Разбор примера: последние три строки файла
- Напишите процедуру
LastLines(FileName), которая выводит последние три строки текстового файла в правильном порядке.
PROCEDURE LastLines(BYVAL FileName : STRING)
DECLARE LineX, LineY, LineZ : STRING
LineX ← ""
LineY ← ""
LineZ ← ""
OPENFILE FileName FOR READ
WHILE NOT EOF(FileName) DO
LineX ← LineY
LineY ← LineZ
READFILE FileName, LineZ
ENDWHILE
CLOSEFILE FileName
OUTPUT LineX
OUTPUT LineY
OUTPUT LineZ
ENDPROCEDURE
- Каждая новая строка сдвигает предыдущие вперед, поэтому на
EOFтри переменные содержат последние три строки; более короткий файл выведет пустые строки. Для первых пяти строк подсчитывайте чтения и остановитесь на пяти или наEOF, в зависимости от того, что наступит раньше. Пустой файл делаетEOFистинным сразу после открытия.
Расставьте шаги процедуры LastLines в правильном порядке.
Инициализация, открытие, цикл со сдвигом перед чтением, закрытие, вывод. Сдвиг после чтения привёл бы к потере самой новой строки.
Поля в строке
- Запись записывается как одна строка, её поля разделены разделительным символом, а каждое число или логическое значение преобразуется с помощью
NUM_TO_STR(и читается обратно с помощьюSTR_TO_NUM, либо путем сравнения с"TRUE"). - Выберите разделитель, который никогда не появится в данных: запятая или
|для имен и чисел; никогда не используйте пробел, если имя может содержать пробел. - Чтение обратно: прочитайте строку, разбейте её по разделителю, преобразуйте каждое поле в его тип, сохраните в записи.

Соединяйте с помощью разделителя для записи; разделяйте и преобразовывайте для чтения
Строка хранит полное имя игрока и счёт. Какой разделитель является наиболее безопасным выбором?
Разделитель никогда не должен встречаться внутри поля. Полное имя содержит пробел, а счёт содержит цифры.
INTEGER можно записать в текстовый файл напрямую, не преобразуя его сначала в строку.
Текстовый файл содержит строки символов. Преобразуйте с помощью NUM_TO_STR для записи и STR_TO_NUM для обратного чтения.
Разобранное решение: сохранение записи и её последующее загрузочное чтение
- Запись
Playerимеет поляName : STRINGиScore : INTEGER. Напишите псевдокод для добавления этой записи вscores.txtодной строкой, а также для чтения одной строки обратно в запись.
OPENFILE "scores.txt" FOR APPEND
WRITEFILE "scores.txt", Player.Name & "," & NUM_TO_STR(Player.Score)
CLOSEFILE "scores.txt"
OPENFILE "scores.txt" FOR READ
READFILE "scores.txt", Line
Pos ← POSITION(Line, ",")
Player.Name ← LEFT(Line, Pos - 1)
Player.Score ← STR_TO_NUM(MID(Line, Pos + 1, LENGTH(Line) - Pos))
CLOSEFILE "scores.txt"
- Баллы: правильный режим, преобразование числа в обоих направлениях, разделитель, который не может встречаться в имени, и закрытие обоих файлов.
Чтобы сохранить запись в виде одной строки текстового файла, программа должна: выберите все подходящие варианты.
Преобразование, объединение, запись, закрытие. В текстовом файле нет двоичной структуры; это делает бинарный файл.
Последовательный и прямой доступ
- Текстовый файл является последовательным (послдовательным): он читается по порядку от начала, поэтому нахождение одной строки требует прочтения всех предшествующих строк.
- Прямой (случайный) доступ мгновенно переходит к записи по вычисленному адресу без чтения остальных; он требует фиксированной длины записей, которой у текстовых файлов нет.
- Для программы курса цикл работы с текстовым файлом выше является моделью: открытие, проверка
EOF, чтение, закрытие.
Прямой (случайный) доступ позволяет программе мгновенно перейти к записи, не читая остальные предварительно.
Последовательный доступ требует чтения с начала.
Потерянные баллы
- Чтение за пределами конца. Проверяйте
EOFперед каждымREADFILE. - Открытие
FOR WRITE, когда файл должен сохранить своё содержимое. Это означаетAPPEND. - Запись числа без
NUM_TO_STRили чтение его обратно безSTR_TO_NUM. Текстовый файл хранит только строки. - Забывание о
CLOSEFILEили использование файла доOPENFILE. Оба случая влекут потерю баллов за работу с файлами.
Вы поняли
- Файлы обеспечивают персистентность: данные сохраняются после завершения программы, могут быть общими и могут превышать объём памяти
OPENFILE … FOR READ | WRITE | APPEND→READFILE/WRITEFILE→CLOSEFILE;WRITEперезаписывает,APPENDдобавляет в конец- проверяйте
EOFперед каждым чтением; преобразовывайте числа с помощьюNUM_TO_STRпри записи иSTR_TO_NUMпри чтении - одна запись = одна строка, поля соединены разделителем, который никогда не встречается в данных