[Java] FileReader/FileWriter 한글 입출력 깨짐

주재완·2024년 1월 31일
0

Java

목록 보기
9/13
post-thumbnail

Introduction

자바 미니 프로젝트(깃허브 링크)를 진행하던 도중 한가지 문제가 발생하여서 글로 남기게 되었다. 그 문제는 아래와 같다.

문제가 있던 코드 깃커밋의 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 문제로 치부하고 있었다.

문제 해결

IDE 차원

우선, 같은 것이 Eclipse에서는 되고 vscode 에서 안된 원인을 알아본 결과, IDE 설정과 관련이 되어 있었다. 바로 이전에 Eclipse 에서 한글을 지원하는 UTF-8 설정을 모든 항목에 대해 완료했던 것이였다. vscode는 한글 관련해서 따로 건든적이 없기에 IDE 차원에서 다른 결과가 나온 것은 어느정도 납득이 되었다.

그러면 코드상에서는 어떻게 해야 될까?

IO에서 인코딩 설정

우선 다음과 같이 Input & Output를 설정하였더니 해결하였다.

  • Input
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
  • Ouput
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true), "utf-8"));

달라진 점을 크게 정리하면 아래와 같다.

BufferedReader/BufferedWriter 안에 들어가는 인자로 원래는 FileReader/Writer를 바로 삽입하였다.

수정 후에는 InputStreamReader/OutputStreamWriter를 삽입하였다.
다음에 이 안에 인자로 Reader/Writer 대신 Input/OutputStream에 해당하는 객체를 넣고, charsetUTF-8로 설정하였다.

무슨 말인지 정리 한번 해보도록 하자. 설명의 편의를 위해 입력에 대해서만 설명하도록 하겠다. 출력은 어차피 반대로 하면 되니...

BufferedReader

Oracle 문서에 따르면 생성자 중 하나가 다음과 같다.

BufferedReader(Reader in)
Creates a buffering character-input stream that uses a default-sized input buffer.

즉, 버퍼를 사용하여 문자를 입력받는 역할을 한다는 것을 알 수 있다. 버퍼의 사용 유무와 관련 되서는 추후 포스팅에서 게시할 예정이다.

그리고 기본적으로 Reader 형태의 자료형이 들어가는 것을 알 수 있다. 즉, FileReader, InputStreamReader 등이 인자로 들어갈 수 있다는 것을 알 수 있다.

FileReader

Oracle 문서에 따르면 모든 생성자의 형태는 다음과 같다.

FileReader(File file)
FileReader(FileDescriptor fd)
FileReader(String fileName)

직관적으로 봤을 때 당연히 파일 입출력과 관련있다는 것을 알 수 있어 별 문제가 없어 보인다. 하지만 중요한 것이 없다. 바로 한글을 다루는 인코딩 설정, UTF-8 설정을 할 수 있는 항목이 없다. 그냥 자바에 설정되어 있는 것을 따른다는 소리이다. 그러면 남은 후보는 InputStreamReader가 있는데 과연 설정이 가능할지 확인해보자.

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"))

출처

profile
언제나 탐구하고 공부하는 개발자, 주재완입니다.

0개의 댓글

관련 채용 정보