Merge pull request into develop from feature/csv-student-io

This commit is contained in:
DELETED
2026-09-01 19:22:20 +04:00
committed by GitHub
5 changed files with 290 additions and 2 deletions
+6
View File
@@ -54,6 +54,12 @@
<version>3.1.5</version> <version>3.1.5</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.14.1</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
@@ -0,0 +1,88 @@
package ru.project.io;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import ru.project.collection.MyList;
import ru.project.student.Student;
public class StudentCsvWriter {
private static final String GROUP_NUMBER_HEADER = "groupNumber";
private static final String AVERAGE_GRADE_HEADER = "averageGrade";
private static final String RECORD_BOOK_NUMBER_HEADER = "recordBookNumber";
private final String absoluteFilePath;
public StudentCsvWriter(String absoluteFilePath) {
this.absoluteFilePath = absoluteFilePath;
}
public void write(Student student) throws IOException {
ensureFileExists();
boolean fileIsEmpty = isFileEmpty();
try (CSVPrinter printer = createPrinter()) {
if (fileIsEmpty) {
writeHeader(printer);
}
writeStudent(printer, student);
}
}
public void write(MyList<Student>[] students) throws IOException {
ensureFileExists();
boolean fileIsEmpty = isFileEmpty();
try (CSVPrinter printer = createPrinter()) {
if (fileIsEmpty) {
writeHeader(printer);
}
for (MyList<Student> studentList : students) {
for (int i = 0; i < studentList.size(); i++) {
writeStudent(printer, studentList.get(i));
}
}
}
}
private CSVPrinter createPrinter() throws IOException {
BufferedWriter writer =
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(absoluteFilePath, true), StandardCharsets.UTF_8));
return new CSVPrinter(writer, CSVFormat.DEFAULT);
}
private void writeHeader(CSVPrinter printer) throws IOException {
printer.printRecord(GROUP_NUMBER_HEADER, AVERAGE_GRADE_HEADER, RECORD_BOOK_NUMBER_HEADER);
}
private void writeStudent(CSVPrinter printer, Student student) throws IOException {
printer.printRecord(
student.getGroupNumber(), student.getAverageGrade(), student.getRecordBookNumber());
}
private void ensureFileExists() throws IOException {
File file = new File(absoluteFilePath);
if (!file.isFile()) {
throw new IOException("CSV file does not exist: " + absoluteFilePath);
}
}
private boolean isFileEmpty() {
return new File(absoluteFilePath).length() == 0;
}
}
@@ -1,7 +1,7 @@
package ru.project.search; package ru.project.search;
import ru.project.collection.MyLinkedList;
import ru.project.collection.MyList; import ru.project.collection.MyList;
import ru.project.collection.MyLinkedList;
import ru.project.student.Student; import ru.project.student.Student;
public class StudentSearchService { public class StudentSearchService {
@@ -0,0 +1,194 @@
package ru.project.io;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import ru.project.collection.MyLinkedList;
import ru.project.collection.MyList;
import ru.project.student.Student;
class StudentCsvWriterTest {
@TempDir Path tempDir;
@Test
void writeShouldWriteHeaderAndStudentToEmptyFile() throws Exception {
Path file = tempDir.resolve("students.csv");
Files.createFile(file);
Student student = new Student("A12", 4.5, 10001);
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
writer.write(student);
List<String> lines = Files.readAllLines(file);
assertEquals(List.of("groupNumber,averageGrade,recordBookNumber", "A12,4.5,10001"), lines);
}
@Test
void writeShouldAppendStudentToExistingFile() throws Exception {
Path file = tempDir.resolve("students.csv");
Files.write(file, List.of("groupNumber,averageGrade,recordBookNumber", "A12,4.5,10001"));
Student student = new Student("B07", 3.8, 10002);
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
writer.write(student);
List<String> lines = Files.readAllLines(file);
assertEquals(
List.of("groupNumber,averageGrade,recordBookNumber", "A12,4.5,10001", "B07,3.8,10002"),
lines);
}
@Test
void writeShouldNotCreateMissingFile() {
Path file = tempDir.resolve("students.csv");
Student student = new Student("A12", 4.5, 10001);
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
assertThrows(IOException.class, () -> writer.write(student));
assertFalse(Files.exists(file));
}
@Test
void writeShouldAppendSeveralStudentsInOrder() throws Exception {
Path file = tempDir.resolve("students.csv");
Files.createFile(file);
Student student1 = new Student("A12", 4.5, 10001);
Student student2 = new Student("B07", 3.8, 10002);
Student student3 = new Student("C25", 4.9, 10003);
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
writer.write(student1);
writer.write(student2);
writer.write(student3);
List<String> lines = Files.readAllLines(file);
assertEquals(
List.of(
"groupNumber,averageGrade,recordBookNumber",
"A12,4.5,10001",
"B07,3.8,10002",
"C25,4.9,10003"),
lines);
}
@Test
void writeArrayShouldAppendStudentsFromAllListsInOrder() throws Exception {
Path file = tempDir.resolve("students.csv");
Files.createFile(file);
Student student1 = new Student("A12", 4.5, 10001);
Student student2 = new Student("B07", 3.8, 10002);
Student student3 = new Student("C25", 4.9, 10003);
Student student4 = new Student("D15", 4.2, 10004);
Student student5 = new Student("E20", 3.6, 10005);
MyList<Student> firstList = new MyLinkedList<>();
firstList.add(student1);
firstList.add(student2);
MyList<Student> secondList = new MyLinkedList<>();
secondList.add(student3);
MyList<Student> thirdList = new MyLinkedList<>();
thirdList.add(student4);
thirdList.add(student5);
@SuppressWarnings("unchecked")
MyList<Student>[] students = new MyList[] {firstList, secondList, thirdList};
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
writer.write(students);
List<String> lines = Files.readAllLines(file);
assertEquals(
List.of(
"groupNumber,averageGrade,recordBookNumber",
"A12,4.5,10001",
"B07,3.8,10002",
"C25,4.9,10003",
"D15,4.2,10004",
"E20,3.6,10005"),
lines);
}
@Test
void writeArrayShouldSkipEmptyLists() throws Exception {
Path file = tempDir.resolve("students.csv");
Files.createFile(file);
Student student = new Student("A12", 4.5, 10001);
MyList<Student> emptyList = new MyLinkedList<>();
MyList<Student> nonEmptyList = new MyLinkedList<>();
nonEmptyList.add(student);
@SuppressWarnings("unchecked")
MyList<Student>[] students = new MyList[] {emptyList, nonEmptyList, new MyLinkedList<>()};
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
writer.write(students);
List<String> lines = Files.readAllLines(file);
assertEquals(List.of("groupNumber,averageGrade,recordBookNumber", "A12,4.5,10001"), lines);
}
@Test
void writeEmptyArrayShouldNotModifyFile() throws Exception {
Path file = tempDir.resolve("students.csv");
List<String> initialContent =
List.of("groupNumber,averageGrade,recordBookNumber", "A12,4.5,10001");
Files.write(file, initialContent);
@SuppressWarnings("unchecked")
MyList<Student>[] students = new MyList[0];
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
writer.write(students);
assertEquals(initialContent, Files.readAllLines(file));
}
@Test
void writeEmptyArrayShouldNotCreateMissingFile() {
Path file = tempDir.resolve("students.csv");
@SuppressWarnings("unchecked")
MyList<Student>[] students = new MyList[0];
StudentCsvWriter writer = new StudentCsvWriter(file.toAbsolutePath().toString());
assertThrows(IOException.class, () -> writer.write(students));
assertFalse(Files.exists(file));
}
}
@@ -3,8 +3,8 @@ package ru.project.search;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import ru.project.collection.MyLinkedList;
import ru.project.collection.MyList; import ru.project.collection.MyList;
import ru.project.collection.MyLinkedList;
import ru.project.student.Student; import ru.project.student.Student;
class StudentSearchTest { class StudentSearchTest {