별다른 라이브러리를 사용하지 않고 JDK 만 이용해서 파일읽고쓰기 기능 구현
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Getter
@NoArgsConstructor
public class CsvSheet {
public static final String DELIMITER = ",";
public static final String SUFFIX_LINE_OF_END = "\n";
private Row header;
private List<Row> rows = new ArrayList<>();
public CsvSheet registerHeader(Row header) {
this.header = header;
return this;
}
public boolean hasHeader() {
return Objects.nonNull(this.header);
}
public CsvSheet addRow(Row row) {
this.rows.add(row);
return this;
}
public List<String> getHeadlessRows() {
return rows.stream().map(Row::getStringRow).collect(Collectors.toList());
}
public List<String> getTotalRows() {
if (hasHeader()) {
List<String> list = new ArrayList<>();
list.add(header.getStringRow());
list.addAll(getHeadlessRows());
return list;
}
return getHeadlessRows();
}
public CsvSheet addRows(List<Row> rows) {
this.rows.addAll(rows);
return this;
}
@NoArgsConstructor
public static class Row<T> {
private List<Cell<T>> cells = new ArrayList<>();
public Row(T... objs) {
this.cells = Stream.of(objs)
.map(Cell::new)
.collect(Collectors.toList());
}
public Row addCell(Object value) {
this.cells.add(new Cell(value));
return this;
}
public String getStringRow() {
return cells.stream().map(Cell::getStringValue)
.collect(Collectors.joining(DELIMITER, "", SUFFIX_LINE_OF_END));
}
}
@Getter
public static class Cell<T> {
private T value;
public Cell(T value) {
this.value = value;
}
public String getStringValue() {
return getValue().toString();
}
}
}
import lombok.extern.slf4j.Slf4j;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
@Slf4j
public class CsvFileWriter {
public static final String FILE_EXTENSION = "csv";
public void write(String fileName, CsvSheet csvSheet) {
String csvFileName = getSourceFile(fileName);
log.info("Generate csv file: {}", csvFileName);
File file = new File(csvFileName);
if (!file.exists()) {
create(file, csvSheet);
}
append(csvFileName, csvSheet);
}
private void append(String csvFileName, CsvSheet csvSheet) {
try (FileWriter fw = new FileWriter(csvFileName, true)) {
StringBuilder stringBuilder = new StringBuilder();
for (String strRow : csvSheet.getHeadlessRows()) {
stringBuilder.append(strRow);
}
fw.write(stringBuilder.toString());
fw.flush();
} catch (IOException e) {
log.error("CSV file append exception", e);
throw new IllegalStateException("CSV file append exception", e);
}
}
private void create(File file, CsvSheet csvSheet) {
try (FileWriter fw = new FileWriter(file)) {
if (csvSheet.hasHeader()) {
fw.write(csvSheet.getHeader().getStringRow());
} else {
fw.write("\n");
}
} catch (IOException e) {
log.error("CSV File Create Exception", e);
throw new IllegalStateException("CSV File Create Exception", e);
}
}
public void delete(String fileName) throws IOException {
String csvFileName = getSourceFile(fileName);
log.info("Generate csv file: {}", csvFileName);
Files.delete(Paths.get(fileName));
}
private String getSourceFile(String fileName) {
return String.format("%s.%s", fileName, FILE_EXTENSION);
}
}
import lombok.extern.slf4j.Slf4j;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@Slf4j
public class CsvFileReader {
public CsvSheet read(String fileName) {
File file = new File(fileName);
if (!file.exists()) {
throw new IllegalArgumentException(String.format("요청하신 CSV 파일(이름: %s)이 존재하지 않습니다.", fileName));
}
CsvSheet csvSheet = new CsvSheet();
try (FileReader filereader = new FileReader(file);
BufferedReader bufReader = new BufferedReader(filereader)) {
int rowCount = 0;
String line;
while ((line = bufReader.readLine()) != null) {
if (rowCount == 0) {
CsvSheet.Row header = new CsvSheet.Row(line.split(CsvSheet.DELIMITER));
csvSheet.registerHeader(header);
} else {
csvSheet.addRow(new CsvSheet.Row(line.split(CsvSheet.DELIMITER)));
}
rowCount++;
}
} catch (Exception e) {
throw new IllegalArgumentException("CSV 파일을 읽던 중 오류가 발생했습니다.", e);
}
return csvSheet;
}
}
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class CsvSheetTest {
@Test
@DisplayName("CsvSheet - 헤더없음")
void test01() {
//expect
CsvSheet csvSheet = new CsvSheet();
//then
assertThat(csvSheet.hasHeader()).isFalse();
assertThat(csvSheet.getRows()).isEmpty();
assertThat(csvSheet.getTotalRows()).isEmpty();
}
@Test
@DisplayName("CsvSheet - 헤더확인")
void test02() {
//given
CsvSheet csvSheet = new CsvSheet();
//when
CsvSheet.Row header = new CsvSheet.Row("header1", "header2", "header3");
csvSheet.registerHeader(header);
//when
assertThat(csvSheet.hasHeader()).isTrue();
assertThat(csvSheet.getTotalRows()).hasSize(1);
assertThat(csvSheet.getTotalRows().get(0)).isEqualTo("header1,header2,header3\n");
}
@Test
@DisplayName("CsvSheet - 본문추가")
void test03() {
//given
CsvSheet csvSheet = new CsvSheet();
//when
CsvSheet.Row row1 = new CsvSheet.Row("row1-1", "row1-2", "row1-3");
CsvSheet.Row row2 = new CsvSheet.Row("row2-1", "row2-2", "row2-3");
CsvSheet.Row row3 = new CsvSheet.Row("row3-1", "row3-2", "row3-3");
List<CsvSheet.Row> rows = Arrays.asList(row1, row2, row3);
csvSheet.addRows(rows);
assertThat(csvSheet.hasHeader()).isFalse();
assertThat(csvSheet.getTotalRows()).hasSize(3);
assertThat(csvSheet.getTotalRows().get(0)).isEqualTo("row1-1,row1-2,row1-3\n");
assertThat(csvSheet.getTotalRows().get(1)).isEqualTo("row2-1,row2-2,row2-3\n");
assertThat(csvSheet.getTotalRows().get(2)).isEqualTo("row3-1,row3-2,row3-3\n");
}
}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class CsvFileWriterTest {
CsvFileWriter csvFileWriter;
private String fileName;
@BeforeEach
void setUp() {
fileName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
csvFileWriter = new CsvFileWriter();
}
@AfterEach
void tearDown() {
File csvFile = new File(String.format("%s.%s", fileName, "csv"));
csvFile.delete();
}
@Test
@DisplayName("CsvFileWriter - 파일생성")
void test01() {
//given
CsvSheet csvSheet = new CsvSheet();
//when
csvFileWriter.write(fileName, csvSheet);
//then
File csvFile = new File(String.format("%s.%s", fileName, "csv"));
assertThat(csvFile.exists()).isTrue();
}
@Test
@DisplayName("CsvFileWriter - 본문작성")
void test02() throws IOException {
//given
CsvSheet csvSheet = new CsvSheet();
CsvSheet.Row header = new CsvSheet.Row("header1", "header2", "header3");
csvSheet.registerHeader(header);
CsvSheet.Row row1 = new CsvSheet.Row("row1-1", "row1-2", "row1-3");
CsvSheet.Row row2 = new CsvSheet.Row("row2-1", "row2-2", "row2-3");
CsvSheet.Row row3 = new CsvSheet.Row("row3-1", "row3-2", "row3-3");
List<CsvSheet.Row> rows = Arrays.asList(row1, row2, row3);
csvSheet.addRows(rows);
//when
csvFileWriter.write(fileName, csvSheet);
File csvFile = new File(String.format("%s.%s", fileName, "csv"));
assertThat(csvFile.exists()).isTrue();
List<String> strRows = readFile(csvFile);
assertThat(strRows).hasSize(4);
assertThat(strRows.get(0)).isEqualTo("header1,header2,header3");
assertThat(strRows.get(1)).isEqualTo("row1-1,row1-2,row1-3");
assertThat(strRows.get(2)).isEqualTo("row2-1,row2-2,row2-3");
assertThat(strRows.get(3)).isEqualTo("row3-1,row3-2,row3-3");
}
private List<String> readFile(File csvFile) throws IOException {
List<String> strRows = new ArrayList<>();
try (FileReader filereader = new FileReader(csvFile);
BufferedReader bufReader = new BufferedReader(filereader)) {
String line;
while ((line = bufReader.readLine()) != null) {
strRows.add(line);
}
} catch (Exception e) {
throw e;
}
return strRows;
}
@Test
@DisplayName("CsvFileWriter - 붙여쓰기 확인")
void test03() throws IOException {
//given
CsvSheet csvSheet = new CsvSheet();
CsvSheet.Row header = new CsvSheet.Row("header1", "header2", "header3");
csvSheet.registerHeader(header);
CsvSheet.Row row1 = new CsvSheet.Row("row1-1", "row1-2", "row1-3");
CsvSheet.Row row2 = new CsvSheet.Row("row2-1", "row2-2", "row2-3");
CsvSheet.Row row3 = new CsvSheet.Row("row3-1", "row3-2", "row3-3");
List<CsvSheet.Row> rows = Arrays.asList(row1, row2, row3);
csvSheet.addRows(rows);
csvFileWriter.write(fileName, csvSheet);
CsvSheet otherCsvSheet = new CsvSheet();
CsvSheet.Row row4 = new CsvSheet.Row("row4-1", "row4-2", "row4-3");
CsvSheet.Row row5 = new CsvSheet.Row("row5-1", "row5-2", "row5-3");
CsvSheet.Row row6 = new CsvSheet.Row("row6-1", "row6-2", "row6-3");
List<CsvSheet.Row> otherRows = Arrays.asList(row4, row5, row6);
otherCsvSheet.addRows(otherRows);
csvFileWriter.write(fileName, otherCsvSheet);
File csvFile = new File(String.format("%s.%s", fileName, "csv"));
assertThat(csvFile.exists()).isTrue();
List<String> strRows = readFile(csvFile);
assertThat(strRows).hasSize(7);
assertThat(strRows.get(0)).isEqualTo("header1,header2,header3");
assertThat(strRows.get(1)).isEqualTo("row1-1,row1-2,row1-3");
assertThat(strRows.get(2)).isEqualTo("row2-1,row2-2,row2-3");
assertThat(strRows.get(3)).isEqualTo("row3-1,row3-2,row3-3");
assertThat(strRows.get(4)).isEqualTo("row4-1,row4-2,row4-3");
assertThat(strRows.get(5)).isEqualTo("row5-1,row5-2,row5-3");
assertThat(strRows.get(6)).isEqualTo("row6-1,row6-2,row6-3");
}
}
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class CsvFileReaderTest {
CsvFileWriter csvFileWriter;
CsvFileReader csvFileReader;
private String fileName;
@BeforeEach
void setUp() {
fileName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
csvFileWriter = new CsvFileWriter();
csvFileReader = new CsvFileReader();
writeDummyData();
}
private void writeDummyData() {
CsvSheet csvSheet = new CsvSheet();
CsvSheet.Row header = new CsvSheet.Row("header1", "header2", "header3");
csvSheet.registerHeader(header);
CsvSheet.Row row1 = new CsvSheet.Row("row1-1", "row1-2", "row1-3");
CsvSheet.Row row2 = new CsvSheet.Row("row2-1", "row2-2", "row2-3");
CsvSheet.Row row3 = new CsvSheet.Row("row3-1", "row3-2", "row3-3");
List<CsvSheet.Row> rows = Arrays.asList(row1, row2, row3);
csvSheet.addRows(rows);
csvFileWriter.write(fileName, csvSheet);
}
@AfterEach
void tearDown() {
File csvFile = new File(String.format("%s.%s", fileName, "csv"));
csvFile.delete();
}
@Test
@DisplayName("CsvFileReader - 존재하지 않는 파일 읽기 오류 발생")
void test01() {
assertThatThrownBy(() -> csvFileReader.read("NONE-EXIST-FILE"))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("요청하신 CSV 파일(이름: NONE-EXIST-FILE)이 존재하지 않습니다.");
}
@Test
@DisplayName("CsvFileReader - 정상 파일읽기")
void test02() {
//expect
CsvSheet csvSheet = csvFileReader.read(String.format("%s.%s", fileName, "csv"));
//then
assertThat(csvSheet.hasHeader()).isTrue();
assertThat(csvSheet.getHeader().getStringRow()).isEqualTo("header1,header2,header3\n");
assertThat(csvSheet.getHeadlessRows()).hasSize(3);
assertThat(csvSheet.getHeadlessRows().get(0)).isEqualTo("row1-1,row1-2,row1-3\n");
assertThat(csvSheet.getHeadlessRows().get(1)).isEqualTo("row2-1,row2-2,row2-3\n");
assertThat(csvSheet.getHeadlessRows().get(2)).isEqualTo("row3-1,row3-2,row3-3\n");
}
}