Введение
Пункт выдачи должен помнить, у кого находится каждый инструмент, даже после закрытия приложения. Это независимое окружение предоставляет рабочие правила выдачи и новый файл пункта, в котором уже есть выдачи и инструмент на обслуживании. Незавершённый код хранения сейчас теряет сохранённое состояние при загрузке и не записывает изменения.
Вы сопоставите записи файла UTF-8 с объектами и будете сохранять только допустимые изменения. Предполагается знание правил объектов из предыдущей работы; её файлы не нужны. Это учебное однопроцессное приложение, а не база данных и не гарантия защиты от отключения питания. Авторская оценка времени на чтение и практику — 45 минут.
Загрузите состояние, которое действительно находится на диске
На этом шаге вы прочитаете обычную запись файла, затем исправите преобразование сохранённого состояния и связей с заёмщиками в объекты Java.
Откройте вкладку Terminal. cd выбирает папку этой независимой лабораторной работы. Клавишами Ctrl+U можно очистить ошибочную строку оболочки, которую вы ещё не выполнили. При ошибке пути вернитесь сюда и повторите правильную команду.
cd /home/labex/project/tool-library
Приложение предоставляет рабочие правила объектов, но незавершённое хранение. Сначала используйте небольшой учебный файл, чтобы увидеть формат из пяти полей без риска для существующих выдач. mkdir -p создаёт учебный каталог при необходимости. printf выводит данные по заданному формату: \t создаёт табуляцию, \n завершает запись; > записывает вывод в указанный файл, заменяя предыдущую учебную копию. Одинарные кавычки не позволяют оболочке менять формат. cp копирует список участников рядом с этим файлом, поскольку приложение ищет members.tsv рядом с входным файлом пункта выдачи. Ни одна из этих команд не меняет настоящий пункт выдачи.
mkdir -p work
printf 'S01\tSpare drill\tAVAILABLE\t-\tPractice only\n' > work/sample.tsv
cp members.tsv work/members.tsv
Скомпилируйте текущий исходный код. -encoding UTF-8 задаёт его текстовую кодировку, -d out — каталог скомпилированных файлов, а *.java выбирает файлы Java в этой папке. Продолжайте только после успешной компиляции без ошибок.
javac -encoding UTF-8 -d out *.java
-cp out указывает Java местоположение классов. -Dfile.encoding=UTF-8 задаёт кодировку текста при выполнении. Учебный входной файл — work/sample.tsv; --memory предотвращает сохранение этой демонстрации.
java -Dfile.encoding=UTF-8 -cp out Desk work/sample.tsv --memory
Внутри программы введите эти строки, нажимая Enter после каждой:
list
borrow S01 M01
list
quit
S01 начинает в состоянии AVAILABLE с заёмщиком -; его выдача M01 принимается. Этот обычный случай работает даже с незавершённым загрузчиком: учебная строка уже содержит состояние, которое предполагает ошибочный код. Он не доказывает сохранение существующих выдач. Учебное изменение исчезнет при закрытии процесса.
Прочитайте настоящий пункт выдачи и зарегистрированных участников. cat показывает файл, не редактируя его:
cat desk.tsv
cat members.tsv
Здесь пять полей с разделителем-табуляцией: ID, название, состояние enum, заёмщик и примечание. Этот контролируемый формат допускает пробелы и текст UTF-8 внутри полей, но не табуляции или переводы строки. T24 уже выдан M03; T25 выдан M02 и имеет примечание Cafe workshop. T23 находится на обслуживании. Эти факты должны сохраниться при загрузке. Не редактируйте напрямую desk.tsv, members.tsv или папку reference.
Прочитайте подготовленный код хранения:
cat Store.java
Store — граница постоянного хранения: записи становятся объектами в load, а объекты — записями в save. Files.readAllLines явно читает UTF-8. fields(line) проверяет формат и возвращает поля от f[0] до f[4]. Найдите вызов new Tool(...): сейчас он подставляет Tool.State.AVAILABLE и "-" для каждой строки. Предскажите последствия для заёмщика T24 и состояния обслуживания T23. Цикл, список, вспомогательные методы разбора и проверки уже подготовлены; сохраните их. Переписывать их реализацию на HashSet не нужно.
Перед редактированием сделайте резервную копию только исходника:
cp Store.java work/Store-before-load.java.txt
nano Store.java
Как и в первой работе, Ctrl+W ищет, Enter подтверждает поиск, стрелки перемещают курсор, а Backspace исправляет символы. Найдите Tool tool = new Tool, чтобы перейти к этому единственному вызову конструктора. Измените аргументы состояния и заёмщика, чтобы получилось:
Tool tool = new Tool(f[0], f[1], Tool.State.valueOf(f[2]), f[3], f[4]);
Tool.State.valueOf(f[2]) преобразует сохранённое имя enum в его значение; f[3] восстанавливает сохранённого заёмщика. Сохраните аргументы ID, названия и примечания, окружающий цикл и все вспомогательные методы. Вы сопоставляете существующую информацию, а не создаёте заново доступный инструмент. Сохраните Ctrl+O, Enter, затем выйдите Ctrl+X. Чтобы отменить несохранённую ошибочную правку, используйте Ctrl+X, N. Для исправления ошибки компиляции снова откройте файл и найдите вызов. Если намеренно хотите начать эту правку заново, cp work/Store-before-load.java.txt Store.java восстанавливает только исходный файл; после этого повторите сопоставление. Никогда не запускайте setup повторно ради отмены правок.
Здесь throws IOException объявляет возможность ошибки доступа к файлу. При отсутствующих или неверно оформленных входных данных цикл команд выводит Cannot continue и останавливается. Это проблема файла, а не отклонённая выдача. Исправьте указанный путь или сопоставление в исходнике; не очищайте и не переписывайте исходные записи ради устранения ошибки.
Скомпилируйте сохранённый исходник и запустите настоящий пункт выдачи. В отличие от демонстрации, не указывайте --memory: после завершения сохранения на следующем шаге пункт будет сохранять допустимые изменения. Синтаксическая ошибка указывает файл и строку; исправьте её в nano и добейтесь успешной компиляции до запуска, не используя старые классы.
javac -encoding UTF-8 -d out *.java
java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv
Введите эти строки внутри пункта выдачи:
list
members
quit
Список должен сохранять T24 → M03, T25 → M02, состояние MAINTENANCE у T23 и все примечания. members показывает зарегистрированные ID. Открытие и просмотр списка не должны перезаписывать файл. quit возвращает в оболочку. Следующий шаг завершит реальное сохранение; одного сообщения об успехе недостаточно для доказательства постоянного хранения.
Сохраните допустимые изменения и снова откройте пункт выдачи
На этом шаге вы обеспечите сохранение одной новой выдачи и одного допустимого возврата после реального завершения процесса.
Начните в оболочке на той же вкладке Terminal. Сохранение сериализует каждый текущий объект, включая неизменённые выдачи и записи об обслуживании. row(tool) соединяет пять полей табуляциями. Цикл добавляет все строки в список; Files.write записывает их в UTF-8. Цикл команд вызывает save только после нормального завершения метода предметной области. Отклонённое действие не должно записывать файл данных, даже перезаписывая идентичное содержимое.
Прочитайте каркас обработки команд, чтобы связать это правило с границей хранения:
cat Desk.java
Найдите found.borrow(c[2]), found.giveBack(c[2]) и следующий за ними Store.save(path, tools). Исключение предметной области пропускает вызов сохранения и превращается в обычный отказ. Сохраните этот подготовленный порядок; запись в обработчике отказа нарушила бы контракт.
Сделайте резервную копию только исходника, сохранив исправленный загрузчик:
cp Store.java work/Store-before-save.java.txt
nano Store.java
Нажмите Ctrl+W, найдите TODO: write all rows, затем Enter. Прочитайте цикл прямо над ним: он собирает одну сериализованную строку для каждого инструмента, включая незатронутые выдачи. Стрелками перейдите к концу комментария и удалите его символы клавишей Backspace. Введите запись с тем же отступом. Замените только комментарий TODO этой реальной записью после цикла, перед закрывающей скобкой метода:
Files.write(path, rows, StandardCharsets.UTF_8);
path — выбранный файл пункта выдачи; rows — полный сериализованный список, а не только последний изменённый объект. Явная кодировка сохраняет текстовую кодировку каждого поля. Сохраните исправленный метод load, цикл строк и все вспомогательные методы. Сохраните Ctrl+O, Enter, Ctrl+X. Ctrl+X, N отменяет несохранённую ошибочную правку. Сохранённую ошибку исправьте, снова открыв исходник; cp work/Store-before-save.java.txt Store.java — необязательный откат только исходника с сохранением вашего загрузчика. После него снова добавьте запись. Не сбрасывайте файл пункта выдачи и не запускайте setup повторно.
Снова скомпилируйте сохранённый исходный код:
javac -encoding UTF-8 -d out *.java
java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv
Внутри пункта выдачи введите следующее:
borrow T21 M01
borrow T21 M02
return T24 M01
borrow T23 M01
borrow TYPO M01
return T24 M03
list
quit
T21 выдаётся M01. Повторная выдача, возврат неправильным заёмщиком, выдача инструмента на обслуживании и ID с опечаткой намеренно отклоняются. Успешен только возврат T24 участником M03. T22 остаётся доступным, T23 — на обслуживании, T25 — выданным M02 с исходным примечанием. После отказа из-за неизвестного ID цикл команд остаётся рабочим; исправьте ID вместо перезапуска или сброса.
Теперь запустите новый процесс Java с тем же файлом:
java -Dfile.encoding=UTF-8 -cp out Desk desk.tsv
list
quit
T21 должен по-прежнему быть BORROWED участником M01, а T24 — AVAILABLE с заёмщиком -. Если это не так, проверьте, что скомпилирован текущий Store.java и запуск выполнен без --memory. Не редактируйте итоговые записи, имитируя сохранённую выдачу. Если принятое действие уже сохранено, не повторяйте его только потому, что теперь оно отклоняется: list показывает текущее реальное положение дел.
Вернувшись в оболочку, прочитайте фактически сохранённый результат:
cat desk.tsv
Связи в записях должны совпадать со списком нового процесса. Сохраните все ID, названия, участников, состояние обслуживания, незатронутые выдачи и примечания. Изменяются только состояние/заёмщик T21 и состояние/заёмщик T24. Этот небольшой компонент записи заменяет файл при успешном сохранении; он не обеспечивает одновременный доступ, восстановление после сбоя или атомарную транзакцию. При ошибке записи остановитесь и изучите её, прежде чем продолжать.
Резюме
Вы сопоставили записи UTF-8 с объектами Java, сохранили каждую текущую запись после допустимого перехода и заново открыли пункт выдачи в новом процессе. Существующие выдачи, обслуживание и примечания остались целыми, а отклонённые операции ничего не записывали в хранилище.



