여전히 잘 모르겠다. 하지만 코딩은 할 수 있다 뭐 이런 얘기를 하고자 합니다.
나에게는 파일과 인코딩은 여전히 잘 모르는 분야 같아, 그냥 나만의 예제를 한 번 작성 해보고자 합니다.
이글을 쓰게 된 사건의 발단은
UNIX/LINUX 상에서 자바로 텍스트 파일, csv 파일에서 구분자 별로 글자들을 읽어서 데이터베이스에 저장하는 기능을
만들어 놓았는 데, 뭔가 한 번씩 오동작을 하고 있었으며, 정확하게는 인코딩 오류가 발생을 한다는 것이었습니다.
디버깅을 해 보았더니 다음 글자들을 읽어 들일 때마다 오류내고 있었죠.
쐑쐑버거
쉑쉑버거
쇅쇅버거
쑝쑝쑝
뚫훍뚤훍
글자들은 일반적으로 우리가 잘 쓰지 않는 것들이고 해당 글자의 범위도 일반적으로 쓰는 범위를
넘어가서 버린 듯한 모습...
그래서 이런 실험을 해보고자 합니다.
우선 다음과 같이 해당 글자들을 메모장을 열고서 복사해 넣고 다음 세가지 인코딩 타입으로 저장 해 봅시다.
그런 다음 파일을 읽어 들이는 코드를 다음과 같이 작성을 하겠습니다. 일반적으로 파일을 읽어 들일 때, 나는 #BufferedReader 를 많이 쓰는 데, #readLine() 메서드가 해당 클래스에 존재 해서 입니다. 몇 줄 안되는 코드를 적어 보면 다음과 같습니다.
public static void main(String[] args)
{
// ======UTF8========= //
System.out.println("======UTF8=========");
readFileFromUTF8Encoding();
System.out.println("======UTF8BOM=========");
readFileFromUTF8BOMEncoding();
System.out.println("======Ansi=========");
readFileFromAnsiEncoding();
}
private static void readFileFromAnsiEncoding() {
BufferedReader rdr = null;
try
{
rdr = new BufferedReader(
new InputStreamReader(
new FileInputStream(new File("C:\\DEV\\tmp\\encodingTest\\버거목록_ANSI.txt"))));
String line = null;
while((line = rdr.readLine()) != null)
{
System.out.println(line);
}
}
catch(IOException ie)
{
}
finally
{
if(rdr != null)
{
try
{
rdr.close();
}catch(IOException ie) {}
}
}
}
private static void readFileFromUTF8BOMEncoding() {
BufferedReader rdr = null;
try
{
rdr = new BufferedReader(
new InputStreamReader(
new FileInputStream(new File("C:\\DEV\\tmp\\encodingTest\\버거목록_UTF-8(BOM).txt"))));
String line = null;
while((line = rdr.readLine()) != null)
{
System.out.println(line);
}
}
catch(IOException ie)
{
}
finally
{
if(rdr != null)
{
try
{
rdr.close();
}catch(IOException ie) {}
}
}
}
private static void readFileFromUTF8Encoding() {
BufferedReader rdr = null;
try
{
rdr = new BufferedReader(
new InputStreamReader(
new FileInputStream(new File("C:\\DEV\\tmp\\encodingTest\\버거목록_UTF-8.txt"))));
String line = null;
while((line = rdr.readLine()) != null)
{
System.out.println(line);
}
}
catch(IOException ie)
{
}
finally
{
if(rdr != null)
{
try
{
rdr.close();
}catch(IOException ie) {}
}
}
}
실행 코드도 그림이 놓인 순서대로 넣어 보았습니다. 여기서 BOM 은 Byte Order Mark 를 뜻합니다.
출력은 다음과 같이 된다.
======UTF8=========
?릲?릲踰꾧굅
?뎾?뎾踰꾧굅
?뇚?뇚踰꾧굅
======UTF8BOM=========
癤우릲?릲踰꾧굅
?뎾?뎾踰꾧굅
?뇚?뇚踰꾧굅
======Ansi=========
쐑쐑버거
쉑쉑버거
쇅쇅버거
자 그럼 위의 코드는 당연히 UTF-8 인코딩 인 경우 깨져서 나올 것을 예상 했고, Ansi 의 경우에는 찾아보니 code page 만 맞으면 해당 지역의 글자가 나오는 것으로 확인 했습니다.
일반적으로 파일을 인터페이스로 쓰는 경우에는 여러가지 복잡한 이유로 UTF-8 을 선호하는 경향이 있으니, 위의 UTF-8 인코딩은 바로 잡아 봅시다.
readFileFromUTF8Encoding2 라는 메서드를 다음과 같이 만들고서,
private static void readFileFromUTF8Encoding2() {
DataInputStream din = null;
try
{
din = new DataInputStream(
new BufferedInputStream(
new FileInputStream(
new File("C:\\DEV\\tmp\\encodingTest\\버거목록_UTF-8.txt")
)
)
);
byte[] buf = new byte[1024];
StringBuffer stbuf = new StringBuffer();
while(din.read(buf, 0, 1024) != -1)
{
stbuf.append(new String(buf, "UTF-8").trim()).append("\r\n");
}
System.out.println(stbuf.toString());
}
catch(IOException ie)
{
}
finally
{
if(din != null)
{
try
{
din.close();
}catch(IOException ie) {}
}
}
}
다음 코드를 메인에다 추가해 줍니다.
public static void main(String[] args)
{
... 생략 ...
System.out.println("======UTF82=========");
readFileFromUTF8Encoding2();
}
결과는?
======UTF8=========
?릲?릲踰꾧굅
?뎾?뎾踰꾧굅
?뇚?뇚踰꾧굅
?몵?몵?몵
?슟?썚?슕?썚
======UTF8BOM=========
癤우릲?릲踰꾧굅
?뎾?뎾踰꾧굅
?뇚?뇚踰꾧굅
?몵?몵?몵
======Ansi=========
쐑쐑버거
쉑쉑버거
쇅쇅버거
쑝쑝쑝
뚫훍뚤훍
======UTF82=========
쐑쐑버거
쉑쉑버거
쇅쇅버거
쑝쑝쑝
뚫훍뚤훍
느낌 만으로 보자면 사실 다음 코드가 더 어울려 보이는 데...
while(din.read(buf, 0, 1024) != -1)
{
stbuf.append(new String(buf, "EUC-KR").trim()).append("\r\n");
}
자 그런 느낌으로 보자면 Ansi 문자열은 다음과 같은 코드가 작성이 되겠죠.
private static void readFileFromAnsiEncoding2() {
DataInputStream din = null;
try
{
din = new DataInputStream(
new BufferedInputStream(
new FileInputStream(new File("C:\\DEV\\tmp\\encodingTest\\버거목록_ANSI.txt"))
)
);
byte[] buf = new byte[1024];
StringBuffer stbuf = new StringBuffer();
while(din.read(buf, 0, 1024) != -1)
{
stbuf.append(new String(buf, "EUC-KR").trim()).append("\r\n");
}
System.out.println(stbuf.toString());
}
catch(IOException ie)
{
}
finally
{
if(din != null)
{
try
{
din.close();
}catch(IOException ie) {}
}
}
}
출력 결과를 확인해 보면...
======UTF8=========
?릲?릲踰꾧굅
?뎾?뎾踰꾧굅
?뇚?뇚踰꾧굅
?몵?몵?몵
?슟?썚?슕?썚
======UTF8BOM=========
癤우릲?릲踰꾧굅
?뎾?뎾踰꾧굅
?뇚?뇚踰꾧굅
?몵?몵?몵
======Ansi=========
쐑쐑버거
쉑쉑버거
쇅쇅버거
쑝쑝쑝
뚫훍뚤훍
======UTF82=========
쐑쐑버거
쉑쉑버거
쇅쇅버거
쑝쑝쑝
뚫훍뚤훍
======Ansi2=========
?q?q버거
쉑쉑버거
??많側?
????
뚫?a뚤?a
위의 출력 결과의 작은 결론은
내 운영체제인 윈도우 11 에서 메모장에 작성한 한글 파일을 Ansi 로 저장 한다면,
MS949 로 인코딩 되어 저장 된다.
라는 결론에 도달하게 됩니다.
위의 코드는 다음과 같이 수정하면 정상적인 출력이 나옵니다.
while(din.read(buf, 0, 1024) != -1)
{
stbuf.append(new String(buf, "MS949").trim()).append("\r\n");
}
그럼, 이 글의 첫 머리에서 시작했던 오류에 대한 의문점에 대한 답이 무엇일까요?
아래 글자들은 EUC-KR(완성형) 범위를 벗어 나는 것들이어서 "MS949"로 다시 디코딩을 해 주어야 한다는 것이고,
읽어 들일때는 대상 시스템의 인터페이스가 파일을 저장 할 때 어떤 인코딩 방식으로 저장 했느냐에 따라서, UTF-8 혹은 EUC-KR, MS949 등으로 로 읽어 들여야 할 것이다. 라는 것이죠.
쐑쐑버거
쇅쇅버거
쑝쑝쑝
뚫훍뚤훍
이상.
'프로그래밍' 카테고리의 다른 글
Win32 어셈블리 프로그래밍 - 3. 간단한 윈도우 (0) | 2022.04.04 |
---|---|
Win32 어셈블리 프로그래밍 - 2. 메시지 박스 (0) | 2022.04.04 |
Win32 어셈블리 프로그래밍 - 1. 기초 (0) | 2022.04.04 |
윈도우 실행 파일 oxc000007b 오류 (0) | 2022.04.01 |
내 PC OS 버전 확인 하기 (0) | 2022.04.01 |