Photo by Markus Spiske on Unsplash |
개요
Java로 BOM(Byte Order Mark)을 이용하여 파일의 문자 인코딩을 감지하는 것을 만들어 봤다. 이미 관련된 오픈소스들이 많기는 하다. 그래도 근래에 관련 정보들을 찾아봤으니, 간단하게라도 한 번 만들어 보는 게 의미가 있을 것 같아서 해봤다.Byte Order Mark
- UTF-8: EF BB BF
- UTF-16(BE): FE FF
- UTF-16(LE): FF FE
- UTF-32(BE): 00 00 FE FF
- UTF-32(LE): FF FE 00 00
- UTF-7:
- 2B 2F 76 38
- 2B 2F 76 39
- 2B 2F 76 2F
- 2B 2F 76 38 2D
- UTF-1: F7 64 4C
- UTF-EBCDIC: DD 73 66 73
- SCSU: 0E FE FF
- BOCU-1: FE EE 28
- GB-18030: 84 31 95 33
구현
단순하게 파일의 첫 4바이트를 읽어서 특정 BOM 규격과 일치하는지 확인했다.
public String getFileEncoding(File file) throws IOException { try { byte[] bytes = new byte[4]; InputStream is = new FileInputStream(file); is.read(bytes); byte[] in2Bytes = Arrays.copyOfRange(bytes, 0, 2); byte[] in3Bytes = Arrays.copyOfRange(bytes, 0, 3); byte[] in4Bytes = Arrays.copyOfRange(bytes, 0, 4); System.out.println("File: " + file.getName()); System.out.print("\t 2Bytes: "); for (byte b: in2Bytes) { System.out.printf("[%x %d] ", b, b); } System.out.println(); System.out.print("\t 3Bytes: "); for (byte b: in3Bytes) { System.out.printf("[%x %d] ", b, b); } System.out.println(); System.out.print("\t 4Bytes: "); for (byte b: in4Bytes) { System.out.printf("[%x %d] ", b, b); } System.out.println(); // 2Byte byte[] bUTF_16BE = new byte[]{(byte)0xFE, (byte)0xFF}; byte[] bUTF_16LE = new byte[]{(byte)0xFF, (byte)0xFE}; if (Arrays.equals(in2Bytes, bUTF_16BE)) return StandardCharsets.UTF_16BE.displayName(); if (Arrays.equals(in2Bytes, bUTF_16LE)) return StandardCharsets.UTF_16LE.displayName(); // 3Byte byte[] bUTF_8 = new byte[]{(byte)0xEF, (byte)0xBB, (byte)0xBF}; byte[] bUTF_7 = new byte[]{(byte)0x2B, (byte)0x2F, (byte)0x76}; byte[] bUTF_1 = new byte[]{(byte)0xF7, (byte)0x64, (byte)0x4C}; byte[] bSCSU = new byte[]{(byte)0x0E, (byte)0xFE, (byte)0xFF}; byte[] bBOCU_1 = new byte[]{(byte)0xFE, (byte)0xEE, (byte)0x28}; if (Arrays.equals(in3Bytes, bUTF_8)) return StandardCharsets.UTF_8.displayName(); if (Arrays.equals(in3Bytes, bUTF_7)) return "UTF-7"; if (Arrays.equals(in3Bytes, bUTF_1)) return "UTF_1"; if (Arrays.equals(in3Bytes, bSCSU)) return "SCSU"; if (Arrays.equals(in3Bytes, bBOCU_1)) return "BOCU_1"; // 4Byte byte[] bUTF_32BE = new byte[]{(byte)0x00, (byte)0x00, (byte)0xFE, (byte)0xFF}; byte[] bUTF_32LE = new byte[]{(byte)0xFF, (byte)0xFE, (byte)0x00, (byte)0x00}; byte[] bUTF_EBCDIC = new byte[]{(byte)0xDD, (byte)0x73, (byte)0x66, (byte)0x73}; byte[] bGB_18030 = new byte[]{(byte)0x84, (byte)0x31, (byte)0x95, (byte)0x33}; if (Arrays.equals(in4Bytes, bUTF_32BE)) return "UTF-32BE"; if (Arrays.equals(in4Bytes, bUTF_32LE)) return "UTF-32LE"; if (Arrays.equals(in4Bytes, bUTF_EBCDIC)) return "UTF-EBCDIC"; if (Arrays.equals(in4Bytes, bGB_18030)) return "GB_18030"; return "NULL"; } catch (FileNotFoundException e) { throw e; } catch (IOException e) { throw e; } }
0 댓글