# Техническое задание: чтение и дозапись `Student` в CSV ## Задача Реализовать два независимых класса для работы с объектами `Student` в формате CSV: - `StudentCsvWriter` — дозапись студентов в файл; - `StudentCsvReader` — последовательное чтение студентов из файла. Для работы с форматом CSV использовать готовую библиотеку для работы с CSV. Самостоятельно реализовывать парсинг CSV запрещено. Оба класса должны принимать **абсолютный путь к файлу**. Исключения `Student` и `StudentBuilder` не обрабатывать. --- # Формат CSV-файла Первая строка файла должна содержать заголовок: ```text groupNumber,averageGrade,recordBookNumber ``` Каждая следующая строка содержит данные одного студента: ```text groupNumber,averageGrade,recordBookNumber ``` Пример: ```text groupNumber,averageGrade,recordBookNumber A12,4.5,10001 B07,3.8,10002 C25,4.9,10003 ``` Для формирования и чтения CSV использовать стандартную библиотеку для работы с форматом CSV. --- # `StudentCsvWriter` ## Назначение Дозаписывать одного студента в указанный CSV-файл. ## Контракт Конструктор: ```java public StudentCsvWriter(String absoluteFilePath) ``` Метод: ```java public void write(Student student) throws IOException ``` ### Требования 1. Метод принимает одного `Student`. 2. Запись выполняется в режиме добавления. 3. Существующие записи не изменяются. 4. Если файл существует, заголовок повторно не записывается. 5. Если файл не существует, необходимо создать файл. 6. При создании нового файла имя должно соответствовать формату: ```text students-yyyy-MM-dd-HH-mm.csv ``` Например: ```text students-2026-08-28-20-45.csv ``` 1. Новый файл создаётся в директории, указанной абсолютным путём. 2. При создании нового файла сначала записывается заголовок. 3. При успешной записи метод завершается без исключения. 4. Метод не возвращает значение. 5. Исключения, связанные с записью файла, не обрабатывать внутри метода — они должны передаваться вызывающему коду. 6. Исключения `Student` и `StudentBuilder` также не обрабатывать. ## Невозможность записи Если студент не может быть записан, например: - отсутствуют права на запись; - невозможно создать файл; - файл недоступен; - произошла ошибка файловой системы; метод должен выбросить соответствующее исключение, например `IOException`. Запись не должна возвращать специальное значение вроде `0` для обозначения ошибки. --- # `StudentCsvReader` ## Назначение Последовательно читать студентов из CSV-файла. ## Контракт Класс должен реализовывать: ```java Iterator ``` Конструктор: ```java public StudentCsvReader(String absoluteFilePath) ``` Методы: ```java @Override public boolean hasNext() ``` ```java @Override public Student next() ``` ### Требования к `hasNext()` 1. Проверяет наличие следующей записи `Student`. 2. Заголовок CSV не считается записью. 3. Повторный вызов `hasNext()` не должен пропускать следующую запись. 4. После окончания файла метод возвращает `false`. ### Требования к `next()` 1. Возвращает следующего `Student`. 2. `Student` создаётся через существующий `StudentBuilder`. 3. При отсутствии следующего элемента выбрасывается: ```text NoSuchElementException ``` 1. Весь файл не должен предварительно загружаться в коллекцию. ## Невозможность прочитать студента Если следующую запись невозможно прочитать или преобразовать в `Student`, например: - некорректный формат CSV; - отсутствует обязательное поле; - значение невозможно преобразовать в нужный тип; - данные не проходят валидацию `Student`; исключение должно передаваться вызывающему коду. Исключения `Student` и `StudentBuilder` **не перехватывать и не обрабатывать**. Некорректные записи не должны молча пропускаться. --- # Общие требования 1. Оба класса принимают абсолютный путь к файлу. 2. Использовать готовую библиотеку для работы с CSV. 3. Не реализовывать собственный CSV-парсер. 4. Не использовать стандартные коллекции Java как основное хранилище студентов. 5. Не дублировать в этих классах валидацию `Student`. 6. Не дублировать логику создания `Student` вне `StudentBuilder`. 7. `StudentCsvWriter` отвечает только за запись. 8. `StudentCsvReader` отвечает только за чтение. --- # Примеры тестов ## `StudentCsvWriter` ### Создание нового файла Передать путь к несуществующему файлу и вызвать: ```java writer.write(student); ``` Проверить: - файл создан; - имя соответствует `students-yyyy-MM-dd-HH-mm.csv`; - присутствует заголовок; - студент записан; - метод завершился без исключения. ### Дозапись Создать файл с одним студентом и выполнить: ```java writer.write(student2); ``` Проверить, что: - первая запись сохранилась; - `student2` добавлен в конец; - заголовок присутствует только один раз. ### Несколько последовательных записей ```java writer.write(student1); writer.write(student2); writer.write(student3); ``` Проверить наличие трёх записей в правильном порядке. ### Невозможность записи Передать путь, по которому невозможно создать или открыть файл для записи. Проверить, что `write()` выбрасывает `IOException`. Не проверять специальное возвращаемое значение — метод ничего не возвращает. --- ## `StudentCsvReader` ### Чтение корректного файла Для файла: ```text groupNumber,averageGrade,recordBookNumber A12,4.5,10001 B07,3.8,10002 C25,4.9,10003 ``` Проверить: - `hasNext()` возвращает `true` до последнего студента; - `next()` возвращает студентов в правильном порядке; - после последнего студента `hasNext()` возвращает `false`. ### Повторный вызов `hasNext()` ```java reader.hasNext(); reader.hasNext(); Student student = reader.next(); ``` Проверить, что первый студент не был пропущен. ### `next()` после окончания файла После чтения всех студентов вызвать: ```java reader.next(); ``` Проверить выброс: ```text NoSuchElementException ``` ### Некорректная запись Передать файл: ```text groupNumber,averageGrade,recordBookNumber A12,4.5,10001 INVALID C25,4.9,10003 ``` Проверить, что ошибка при чтении некорректной записи передаётся вызывающему коду. ### Некорректные данные `Student` Передать данные, нарушающие ограничения `Student`. Проверить, что исключение от `Student` или `StudentBuilder` выходит наружу и не перехватывается `StudentCsvReader`. --- # Названия файлов ```text StudentCsvWriter.java StudentCsvReader.java ``` # Git Название ветки: ```text feature/csv-student-io ``` Conventional Commit: ```text feat: add csv student reader and writer ```