본문

JAVA에서 UTF-8 BOM 처리하여 파일 읽기/쓰기



파일을 정규식을 통하여 분리한 후에 SQL문으로 넣는 부분에서 계속 오류가 났다. 분명 SQL문상으로는 오류가 없는데, int형을 입력하는 부분에서 계속 ORA-1481 invalid number format model 이 발생하는 것이다. 자체 디버깅 모듈에서도 문제가 검출되지 않아 IDE에서 직접 디버깅을 하니 생각지 않던 문자가 들어가 있었다. 이 문자는 전혀 선택이 되지 않으며 어떤 형태도 띄지 않았는데, 직접 hex값을 보니 특정 값이 들어가 있는것을 확인할 수 있었다.

프로젝트의 모든 파일 처리가 UTF-8으로 되어있기에, 테스트용 텍스트파일도 UTF-8로 설정해주었는데,  이떄 문제가 발생한 것이다. 특히 윈도우 기본프로그램인 메모장에서 UTF-8형식으로 저장을 하는데 이떄 UTF-8이라는것을 나타내기 위하여 BOM(Byte Order Mark)를 파일의 가장 앞부분에 추가하는 것이다. UTF-8의 BOM은 EF BB BF 값으로 표현이 된다. (UTF-16등과같은 경우에는 다른 BOM을 사용한다.)

BOM을 제거한 후에 파일을 저장하기 위해서는 메모장이 아닌 Notepad++등과 같은 외부 텍스트 에디터의 옵션을 통하여 저장하면 된다. 특히 Notepad++에서는 인코딩->UTF-8(BOM 없음)으로 변환 을 누르면 파일에서 BOM이 제거가 된다.


*파일 읽기
그럼 파일 읽기는 어떻게 사용하면 될까? 아래 소스코드를 참조한다. 중요한 점이라면 UTF8_BOM과 파일을 읽을 때 그 줄이 파일의 가장 첫줄일 경우 substring(1)을 통하여 BOM을 제거한 문자열을 반환한다는 것이다.
(출처 : Handle UTF8 file with BOM - Real's Java How-to)

import java.io.*;

public class UTF8ToAnsiUtils {

    // FEFF because this is the Unicode char represented by the UTF-8 byte order mark (EF BB BF).
    public static final String UTF8_BOM = "\uFEFF";

    public static void main(String args[]) {
        try {
            if (args.length != 2) {
                System.out.println("Usage : java UTF8ToAnsiUtils utf8file ansifile");
                System.exit(1);
            }

            boolean firstLine = true;
            FileInputStream fis = new FileInputStream(args[0]);
            BufferedReader r = new BufferedReader(new InputStreamReader(fis, "UTF8"));
            FileOutputStream fos = new FileOutputStream(args[1]);
            Writer w = new BufferedWriter(new OutputStreamWriter(fos, "Cp1252"));
            for (String s = ""; (s = r.readLine()) != null;) {
                if (firstLine) {
                    s = UTF8ToAnsiUtils.removeUTF8BOM(s);
                    firstLine = false;
                }
                w.write(s + System.getProperty("line.separator"));
                w.flush();
            }

            w.close();
            r.close();
            System.exit(0);
        }

        catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    private static String removeUTF8BOM(String s) {
        if (s.startsWith(UTF8_BOM)) {
            s = s.substring(1);
        }
        return s;
    }
}


*파일 쓰기
파일쓰기도 마찬가지이다. 여기서도 중요한점은 BufferedWriter.write()를 통하여 가장 앞에 BOM을 입력해준다는 것이다.
(출처 : Java/자바] UTF-8 BOM 있는 유니코드 파일 출력/만들기 예제)

import java.io.*;

public class Foo {
  public static void main(String[] args) {

  try {
    BufferedWriter UniOutput = new BufferedWriter( new OutputStreamWriter( new FileOutputStream("out.txt"), "UTF8") );

    // UTF-8의 BOM인 "EF BB BF"를 UTF-16BE 로 변환하면;]
    UniOutput.write(65279);

    UniOutput.write("ABC가나다라");
    UniOutput.newLine();
    UniOutput.write("똠방각하");

    UniOutput.close();

  } catch (UnsupportedEncodingException e) {
      System.err.println(e);
      System.exit(1);
  } catch (IOException e) {
      System.err.println(e);
      System.exit(1);
  }

  }
}

댓글

Holic Spirit :: Tistory Edition

design by tokiidesu. powerd by kakao.