View

어쩌다 보니 풀스택 개발자로 달리고 있는 나. csv 파일을 읽어서 데이터를 가공하고 db에 저장하는 기능을 만들어야 했다.

 

하지만 csv 파일마다 인코딩이 전부 제각각이라는 문제에 직면했다.

 

예를 들어, csv 파일을 메모장으로 만드는 경우 기본적으로 UTF-8로 저장된다. (사용자 설정에 따라 다를 수도 있다) 하지만 .csv 파일은 엑셀 프로그램이 깔려 있는 경우 일반적으로 엑셀로 열리기도 하는데, UTF-8로 저장된 csv 파일을 엑셀로 열었을 경우 한글이 전부 깨진다!

그제서야 부랴부랴 엑셀에서 잘 보일 수 있도록 ANSI로 인코딩을 해서 업로드를 하면 백단에서 다 깨진다!

 

어찌저찌 긴급 처치를 해도 일어날 수 있는 모든 상황에서 한글이 예쁘게 보일 수 있는 방법은 없다고 판단...

파일 입력과 동시에 코드 내에서 charset을 파악하고 그에 맞는 디코딩을 할 수 있으면 좋겠다고 생각했다.


https://blog.naver.com/PostView.nhn?blogId=senshig&logNo=222248682359&parentCategoryNo=&categoryNo=78&viewDate=&isShowPopularPosts=true&from=search

 

[JAVA] CSV 파일 읽어오기 한글깨짐 방지 인코딩 호환성 - 코드 리팩토링

[JAVA] CSV 파일 읽어오기 한글깨짐 방지 인코딩 호환성 - 코드 리팩토링 https://blog.naver.com/s...

blog.naver.com

 

참고한 블로그다.

 

한 마디로 요약하면 내가 원하는 방식인 파일의 charset을 파악하는 일을 해 주는 자바 라이브러리가 존재했다.

https://mvnrepository.com/artifact/com.googlecode.juniversalchardet/juniversalchardet/1.0.3 

진행하는 프로젝트가 마침 maven 프로젝트였기 때문에 dependency를 추가했고, charset을 체크하는 함수를 따로 config로 빼서 작성했다.

 

참고한 블로그 포스트와 다른 점은 springboot를 사용하여 파일 매개변수가 MultipartFile이라는 점이었다. (이 부분에서 MultipartFile이 SpringMVC에서 FileUpload 처리를 위해 제공하는 클래스이며, 사용하려면 MultipartResolver를 DispatcherServlet에 빈으로 등록해야 한다. 이 과정을 springboot는 자동으로 해준다. 라는 것을 알게 됐다)

 

이 라이브러리를 사용하여 charset을 알아내려면 입력이 File 객체여야 했는데, MultipartFile도 어쨌든 File의 연장선(?)이라 File 객체로 변환하는 것이 어렵지 않았다.

원래 MultipartFile에 transferTo() 메소드가 있는데, 이 메소드는 무슨 이유인지 먹히지 않아서 새롭게 File 객체를 생성해 인자로 받은 MulipartFile의 내용을 담는 식으로 변환했다.

File file = new File(multipartFile.getOriginalFilename());
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
fos.write(multipartFile.getBytes());

 

이 과정에서 FileInputStream과 FileOutputStream의 개념을 인지할 수 있었다. 간단하게 FIS는 File을 입력으로 받는 클래스고, FOS는 파일로 출력을 내보내는 클래스다.

(자바를 사용해 보긴 했지만.. 어쩌면 자바스크립트보다 오랜 시간 나와 함께 했지만.. 그렇게 열정적이지 않았기 때문에 대충대충 했어서 이런 것도 모른다 ㅎ)

아무튼 그래서 MultipartFile의 값으로 File 객체를 새로 만들 때는 FOS를 사용하고, 이제 그 안의 값을 읽어서 charset을 파악하고 싶을 때는 FIS를 사용하는 것이다.

 

그 이후에는 간단하다. 라이브러리의 UniversalDetector 객체를 생성하고, 해당 클래스의 getDetectedCharset() 메소드를 사용해 주면 된다. 그러면 Charset 객체가 return 된다. 이후 이 Charset을 InputStreamReader에게 넘겨 주면 된다.


이제 원래 로직이 돌아가던 서비스단에서 작성한 함수를 사용하면 쉽게 charset을 확인할 수 있다. 리턴된 Charset을 가지고 Charset.displayName()을 찍어 보면 우리가 알고 있는 UTF-8, EUC-KR 같은 이름들이 출력되는 걸 확인할 수 있다.

 

여기서 기록하고 싶었던 것이 나오는데, 바로 ANSI charset이다. 메모장에서 지원하는 인코딩 방식 중 ANSI 인코딩이 있고, 이 인코딩을 설정해야만 엑셀에서 한글이 깨지지 않게 열린다. 하지만 ANSI는 함수를 이용해 charset을 뽑아서 InputStreamReader로 넘겨 주어도 정상적으로 디코딩이 되지 않았다. EUC-KR과 UTF-8은 정상적으로 디코딩이 되는데, ANSI만 계속 깨져 나왔다.

 

해결 방법은 EUC-KR이었다. 메모장의 ANSI는 사실 windows-1252라는 charset이다. 일반적으로 MS-DOS의 기본 인코딩인 OEM-US 내지 영문 Windows의 기본 인코딩이라고 한다. 그리고 우리에게 익숙한 EUC-KR이 windows-1252를 한국에서 확장한 charset이다.

 

따라서 charset이 windows-1252로 들어오는 경우 EUC-KR로 디코딩을 해 주면 한글이 깨지지 않고 정상적으로 디코딩되는 것을 확인할 수 있었다.

Share Link
reply
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30