자바 미니 프로젝트(깃허브 링크)를 진행하던 도중 한가지 문제가 발생하여서 글로 남기게 되었다. 그 문제는 아래와 같다.
문제가 있던 코드 깃커밋의 28번째 줄 부분을 살펴보도록 하자. 해당 클래스는 DAO(Data Access Object)로 DB(여기서는 RDBMS 대신 메모장을 DB의 형태로 사용하였다.)에 접근하는 역할을 한다. 여기서 메모장에 있는 것을 줄단위로 읽어야 할 때 다음과 같이 작성했었다.
...
try(BufferedReader br = new BufferedReader(new FileReader(file))) {
...
그리고 메모장으로 된 DB는 아래와 같이 구성되어 있었다.
admin,admin,admin,admin,admin
주재완,jjw05015,1234,jjw05015@gmail.com,010-1111-1111
김철수,id1234,pass1234,id1234@naver.com,010-2222-2222
...
다른 것은 크게 문제가 되지 않았으나, 제일 앞요소, 즉 name
을 가져올 때 한글이 깨지는 문제가 있었다. 이 문제는 Eclipse 에서는 발생하지 않았는데, vscode로 할 때는 발생하였기에 처음에는 vscode 문제로 치부하고 있었다.
우선, 같은 것이 Eclipse에서는 되고 vscode 에서 안된 원인을 알아본 결과, IDE 설정과 관련이 되어 있었다. 바로 이전에 Eclipse 에서 한글을 지원하는 UTF-8
설정을 모든 항목에 대해 완료했던 것이였다. vscode는 한글 관련해서 따로 건든적이 없기에 IDE 차원에서 다른 결과가 나온 것은 어느정도 납득이 되었다.
그러면 코드상에서는 어떻게 해야 될까?
우선 다음과 같이 Input & Output를 설정하였더니 해결하였다.
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "utf-8"));
달라진 점을 크게 정리하면 아래와 같다.
BufferedReader/BufferedWriter
안에 들어가는 인자로 원래는FileReader/Writer
를 바로 삽입하였다.
수정 후에는
InputStreamReader/OutputStreamWriter
를 삽입하였다.
다음에 이 안에 인자로Reader/Writer
대신Input/OutputStream
에 해당하는 객체를 넣고,charset
을UTF-8
로 설정하였다.
무슨 말인지 정리 한번 해보도록 하자. 설명의 편의를 위해 입력에 대해서만 설명하도록 하겠다. 출력은 어차피 반대로 하면 되니...
Oracle 문서에 따르면 생성자 중 하나가 다음과 같다.
BufferedReader(Reader in)
Creates a buffering character-input stream that uses a default-sized input buffer.
즉, 버퍼를 사용하여 문자를 입력받는 역할을 한다는 것을 알 수 있다. 버퍼의 사용 유무와 관련 되서는 추후 포스팅에서 게시할 예정이다.
그리고 기본적으로 Reader
형태의 자료형이 들어가는 것을 알 수 있다. 즉, FileReader
, InputStreamReader
등이 인자로 들어갈 수 있다는 것을 알 수 있다.
Oracle 문서에 따르면 모든 생성자의 형태는 다음과 같다.
FileReader(File file)
FileReader(FileDescriptor fd)
FileReader(String fileName)
직관적으로 봤을 때 당연히 파일 입출력과 관련있다는 것을 알 수 있어 별 문제가 없어 보인다. 하지만 중요한 것이 없다. 바로 한글을 다루는 인코딩 설정, UTF-8
설정을 할 수 있는 항목이 없다. 그냥 자바에 설정되어 있는 것을 따른다는 소리이다. 그러면 남은 후보는 InputStreamReader
가 있는데 과연 설정이 가능할지 확인해보자.
역시 Oracle 문서를 보도록 하자. 그런데 이런 항목이 눈에 띈다.
InputStreamReader(InputStream in, Charset cs)
Creates an InputStreamReader that uses the given charset.
우리가 원하는 인코딩, 즉 Charset
항목이 눈에 띈다. 여기에 "utf-8"
기입해주면 우리가 원하는 한글 입출력이 가능한 것이다!
또한 InputStream
을 받기 때문에 이 안에는 FileReader
가 아닌 InputStream
을 상속받는 FileInputStream
을 인자로 가져야한다는 사실을 기억해두자.
UTF-8
설정 잘 하도록 하고 가급적 이렇게 쓰자.
// 파일에서부터 입력받기
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
// 파일로 출력하기
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "utf-8"))