작성
·
99
·
수정됨
0
public static void main(String[] args) throws IOException {
String writeString = "가나다ABC";
System.out.println("writeString = " + writeString);
// 파일에 쓰기
var fw = new FileWriter(FILE_NAME, StandardCharsets.UTF_8);
fw.write(writeString);
fw.close();
// 파일에서 읽기
var content = new StringBuilder();
var fr = new FileReader(FILE_NAME);
int ch;
while ((ch = fr.read()) != -1) {
char ch1 = (char) ch;
System.out.println("ch1 = " + ch1);
content.append(ch1);
}
fr.close();
System.out.println("readString = " + content);
}
질문1) 예제의 코드에서 char ch1 = (char) ch;
로 캐스팅하는부분이 궁금해요
인코딩이 UTF-8 이니 최대 3바이트까지 쓸 수 있는데 이것을 2바이트만쓰는 char 로 캐스팅할 수 있는 이유는 무엇인가요?
가~다
는 자바의 기본인코딩타입인 UTF-16 에서 2바이트로 표현할 수 있기 때문일까요?
fr.read()
는 2바이트로 표현해야하는것이 아니라면 해당문자열까지 읽고, 반환하는것으로보이는데 맞는걸까요?
확인해보니 이모지같은경우에는 UTF-16 에서는 두 바이트로 표현이힘들어서 깨지는것을 확인했습니다!
질문2) 위의 가정이 맞다면 Reader, Writer 은 항상 JVM이 관리하는 UTF-16 으로 읽는과정이 있으니 byte 단위로 읽는 Stream 보다 성능적으로 느릴 것 같은데 맞을까요?
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
이석준님, UTF-8 문자열을 char
타입으로 변경하는 것에 대해 문의주셨군요. 질문에 대해 하나씩 답변드리겠습니다.
질문 1) char ch1 = (char) ch;
로 캐스팅하는 부분
UTF-8 인코딩에서 글자 하나를 나타내기 위해 1바이트에서 4바이트까지 사용될 수 있지만, 코드에서 사용하신 Reader는 기본적으로 UTF-16으로 변환하여 읽어옵니다. 이때, UTF-8
인코딩된 데이터가 Java 내부에서는 UTF-16
으로 변환되어 char
로 처리됩니다.
말씀하신 것처럼, 한글 가~다
와 같은 문자들은 UTF-16
에서 2바이트로 표현할 수 있기 때문에 char
로 변환이 가능한 것입니다.
fr.read()
메서드는 캐릭터 하나를 읽고, 이는 자동적으로 UTF-8에서 UTF-16으로 변환됩니다. 따라서 내부적으로 유니코드 문자 단위로 처리가 되는 것이 맞습니다.
이모지와 같이 UTF-16에서 서러게이트 페어로 표현되어야 하는 문자는 두 바이트로 처리되기 때문에, 단일 char
로 처리하기 곤란해집니다. 이에 따라 깨지는 현상을 보신 것으로 보입니다.
질문 2) JVM이 관리하는 UTF-16으로 읽는 Reader, Writer와 Stream의 성능 차이
하지만, Reader와 Writer는 문자열 데이터를 더 직관적으로 다루기 위해 설계되어 있어, 유니코드 문자 기반의 입출력 작업에서는 자연스러운 선택입니다. 성능 차이는 코드 설계 및 데이터 크기 등에 의존할 수 있기 때문에 실제 사용 시 이러한 측면을 함께 고려하는 것이 좋습니다.
추가 정보는 Spring Boot Reference Documentation에서 IO와 관련된 유틸리티와 통합에 관한 자료를 참고하실 수 있습니다.
도움이 되셨길 바랍니다. 다른 질문이 있으시면 언제든지 문의해주세요. 감사합니다!