Files

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

Требования

  1. Метод принимает одного Student.
  2. Указанный файл должен уже существовать.
  3. Запись выполняется в режиме добавления.
  4. Существующие записи не должны изменяться.
  5. Заголовок CSV не должен записываться повторно.
  6. Если файл не существует, новый файл не создавать.
  7. Если файл не существует, метод должен выбросить IOException.
  8. При успешной записи метод завершается без исключения.
  9. Метод не возвращает значение.
  10. Исключения, связанные с записью файла, не обрабатывать внутри метода.
  11. Исключения 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;

Контракт

Метод должен:

  1. Принимать массив MyList<Student>.
  2. Последовательно обрабатывать все переданные коллекции.
  3. Записывать каждого студента в указанный CSV-файл.
  4. Сохранять порядок:
    • коллекций в массиве;
    • студентов внутри каждой MyList.
  5. Использовать тот же формат CSV и те же правила записи, что и write(Student).
  6. Работать только с уже существующим файлом.
  7. Не создавать файл, если он отсутствует.
  8. При отсутствии файла выбрасывать IOException.
  9. Не изменять переданные MyList<Student>.
  10. Не обрабатывать исключения, возникающие при создании или валидации Student.
  11. При ошибке записи прекращать операцию и передавать исключение вызывающему коду.

Пример

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()

  1. Проверяет наличие следующей записи Student.
  2. Заголовок CSV не считается записью.
  3. Повторный вызов hasNext() не должен пропускать следующую запись.
  4. После окончания файла метод возвращает false.

Требования к next()

  1. Возвращает следующего Student.
  2. Student создаётся через существующий StudentBuilder.
  3. При отсутствии следующего элемента выбрасывается:
NoSuchElementException
  1. Весь файл не должен предварительно загружаться в коллекцию.

Невозможность прочитать студента

Если следующую запись невозможно прочитать или преобразовать в Student, например:

  • некорректный формат CSV;
  • отсутствует обязательное поле;
  • значение невозможно преобразовать в нужный тип;
  • данные не проходят валидацию Student;

исключение должно передаваться вызывающему коду.

Исключения Student и StudentBuilder не перехватывать и не обрабатывать.

Некорректные записи не должны молча пропускаться.


Общие требования

  1. Оба класса принимают абсолютный путь к файлу.
  2. Использовать готовую библиотеку для работы с CSV.
  3. Не реализовывать собственный CSV-парсер.
  4. Не использовать стандартные коллекции Java как основное хранилище студентов.
  5. Не дублировать в этих классах валидацию Student.
  6. Не дублировать логику создания Student вне StudentBuilder.
  7. StudentCsvWriter отвечает только за запись.
  8. 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