바이트 ED 95 9C EA B8 80을 UTF-8, EUC-KR, CP949 세 가지로 각각 디코딩해보고 어떤 인코딩일 때 정상적으로 "한글"이 나오는지 확인하는 코드를 작성하세요.
byte[] b = {(byte)0xED,(byte)0x95,(byte)0x9C,
(byte)0xEA,(byte)0xB8,(byte)0x80};
for (Charset cs : List.of(StandardCharsets.UTF_8,
Charset.forName("EUC-KR"), Charset.forName("MS949"))) {
System.out.println(cs.name() + ": " + new String(b, cs));
}UTF-8 로 디코딩할 때만 "한글"이 정상적으로 나옵니다. EUC-KR·CP949 는 3바이트 단위를 2바이트씩 잘못 읽어 다른 글자나 대체 문자가 나옵니다.
문자열 리스트를 CSV 파일로 쓰는 메서드에 boolean withBom 매개변수를 추가해, true일 때만 UTF-8 BOM 을 파일 맨 앞에 쓰도록 하세요.
static void writeCsv(Path file, List<String> lines, boolean withBom)
throws IOException {
try (OutputStream out = Files.newOutputStream(file)) {
if (withBom) {
out.write(new byte[]{(byte)0xEF,(byte)0xBB,(byte)0xBF});
}
for (String line : lines) {
out.write((line + "\n").getBytes(StandardCharsets.UTF_8));
}
}
}Excel 로 열 CSV 는 withBom=true, 다른 프로그램이 파싱할 CSV 는 withBom=false로 호출을 나눠 쓰면 됩니다.
String과 int maxBytes를 받아, UTF-8 기준 바이트 길이가 maxBytes를 넘으면 IllegalArgumentException을 던지는 validateByteLength 메서드를 작성하세요.
static void validateByteLength(String value, int maxBytes) {
int len = value.getBytes(StandardCharsets.UTF_8).length;
if (len > maxBytes) {
throw new IllegalArgumentException(
"바이트 길이 초과: " + len + " > " + maxBytes);
}
}DB insert 전 검증 로직에 그대로 끼워 넣을 수 있고, Main.truncateByBytes와 짝을 이뤄 "자를지 거부할지"를 상황에 맞게 고를 수 있습니다.
업로드된 파일명을 저장하기 전에 항상 NFC 로 정규화하는 normalizeFileName(String rawName) 메서드를 작성하세요.
static String normalizeFileName(String rawName) {
return Normalizer.normalize(rawName, Normalizer.Form.NFC);
}업로드 컨트롤러의 파일 저장 로직 맨 앞에서 이 메서드를 거치게 하면, macOS 에서 온 NFD 파일명과 Windows/Linux 의 NFC 파일명이 하나로 통일됩니다.
문자열에서 EUC-KR 로 인코딩할 수 없는 문자(확장 한글 등)만 골라 ?로 치환하는 sanitizeForEucKr(String s) 메서드를 작성하세요. 힌트: 한 글자씩 canEncode로 검사합니다.
static String sanitizeForEucKr(String s) {
Charset eucKr = Charset.forName("EUC-KR");
StringBuilder sb = new StringBuilder();
s.codePoints().forEach(cp -> {
String ch = new String(Character.toChars(cp));
sb.append(eucKr.newEncoder().canEncode(ch) ? ch : "?");
});
return sb.toString();
}레거시 EUC-KR 전문으로 나가기 직전, 확장 한글이 포함된 값을 통째로 실패시키지 않고 ?로 대체해 전송을 계속하고 싶을 때 씁니다.