csv로 저장할 model의 field는 얼마든지 바뀔 수 있으므로 reflection을 사용해보도록 하자.
`getClass().getDeclaredFields()`이면 model class에 선언한 field들을 가져올 수 있다.
## BOM(Byte Order Marker)?
해당 문서가 어떤 Charset으로 되어 있는지 판별하기 위해 사용되는 Marker이다.
몇가지 타입이 있는데 자세한건 검색해보도록 하자.
## java BOM 지원
java reader들은 BOM를 지원하지 않기 때문에,
쓰기 할때는 BOM을 추가, 읽을 때는 BOM을 삭제해줘야 한다.
BOM을 반영해주지 않으면 charset 때문에 읽기 곤란한 문서와 만나게 된다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CSVWriter { | |
private static final String UTF8_BOM = "\uFEFF"; | |
public void convert(HttpServletResponse response, List<?> datas, String name) { | |
write(response, transform(datas), name); | |
} | |
private List<String[]> transform(List<?> objects) { | |
List<String[]> dataToWrite = new ArrayList<>(); | |
if (objects.size() == 0) { | |
return dataToWrite; | |
} | |
dataToWrite.add(makeHeader(objects.get(0).getClass())); | |
int i; | |
Field[] fields; | |
String[] columns; | |
for (Object dto : objects) { | |
i = 0; | |
fields = dto.getClass().getDeclaredFields(); | |
columns = new String[fields.length]; | |
for (Field field : fields) { | |
field.setAccessible(true); | |
try { | |
columns[i] = field.get(dto) == null ? "" : String.valueOf(field.get(dto)); | |
} catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} | |
++i; | |
} | |
dataToWrite.add(columns); | |
} | |
return dataToWrite; | |
} | |
private String[] makeHeader(Class title) { | |
Field[] fields = title.getDeclaredFields(); | |
String[] columns = new String[fields.length]; | |
int i = 0; | |
for (Field field : fields) { | |
columns[i] = field.getName(); | |
++i; | |
} | |
return columns; | |
} | |
private void write(HttpServletResponse response, List<String[]> datas, String name) { | |
response.addHeader("Content-disposition", "attachment;filename=" + name + ".csv"); | |
response.setContentType("text/plain"); | |
response.setCharacterEncoding("UTF-8"); | |
try ( | |
OutputStream outputStream = response.getOutputStream(); | |
CSVWriter writer = new CSVWriter(new OutputStreamWriter(outputStream)) | |
) { | |
//add BOM | |
outputStream.write(UTF8_BOM.getBytes()); | |
writer.writeAll(datas); | |
response.flushBuffer(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
} | |
private String removeUTF8BOM(String s) { | |
if (s.startsWith(UTF8_BOM)) { | |
s = s.substring(1); | |
} | |
return s; | |
} | |
} |