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