2013-02-06 6 views
3

여기 내 문제가 있습니다. 바이트 배열로 변환 한 InputStream이 있지만 런타임에 InputStream의 문자 집합을 알 수 없습니다. 필자의 원래 생각은 UTF-8로 모든 것을 처리하는 것이지만 ISO-8859-1로 인코딩 된 스트림에 이상한 문제가 발생하고 외래 문자가 있습니다. (그 미친 스웨덴)스칼라 - ISO-8859-1에서 UTF-8로 변환하면 외래 문자가 이상합니다

가 여기에 문제의 코드입니다 :

IOUtils.toString(inputstream, "utf-8") 
// Fails on iso8859-1 foreign characters 

이 시뮬레이션은, 내가 가진 : 나는 무엇을

new String("\u00F6") 
// Returns ö as expected, since the default encoding is UTF-8 

new String("\u00F6".getBytes("utf-8"), "utf-8") 
// Also returns ö as expected. 

new String("\u00F6".getBytes("iso-8859-1"), "utf-8") 
// Returns \uffff, the unknown character 

를 놓친 거지?

+2

'InputStream' 내에 인코딩 된 (표면 문자) 문자의 인코딩을 모른다면 문자로 변환 할 수 없습니다. 그것은 아주 간단합니다. 그리고 ... 왜 ISO-8859-1로 인코딩 한 다음 UTF-8에서 디코딩하면 임의의 문자로 작동 할 것이라고 기대하십니까? –

+0

Nit :'new String ("\ u00F6")'값을 예상대로 가지고 있으면 인코딩 할 때 * nothing *이됩니다 .. –

+1

런타임시 인코딩을 결정하는 것이'Content-Type' 헤더와 각각의'charset' 매개 변수입니다 exist –

답변

1

인코딩 소스를 알려주는 데이터 소스가 있어야하지만, 그렇지 않으면 인코딩을 거부하거나 UTF-8이 아니면 인코딩을 추측해야합니다.

ByteBuffer bytes = ByteBuffer.wrap(IOUtils.toByteArray(inputstream)); 
CharBuffer chars; 

try { 
    try { 
     chars = Charset.forName("UTF-8").newDecoder().decode(bytes); 
    } catch (MalformedInputException e) { 
     throw new RuntimeException(e); 
    } catch (UnmappableCharacterException e) { 
     throw new RuntimeException(e); 
    } catch (CharacterCodingException e) { 
     throw new RuntimeException(e); 
    } 
} catch (RuntimeException e) { 
    chars = Charset.forName("ISO-8859-1").newDecoder().decode(bytes); 
} 
System.out.println(chars.toString()); 

이 모든 상용구 인코딩 예외를 받고 읽을 수입니다 : 서양 언어의

은 ISO-8859-1을 추측하는 것은이 UTF-8은 아마 대부분의 시간을 작동하는 것입니다 아니라면 동일한 데이터를 여러 번

보다 정교한 인공 지능을 사용하는 Mozilla Chardet을 사용하여 UTF-8이 아닌 인코딩을 결정할 수도 있습니다. 하지만 완벽하지는 않습니다. 예를 들어 Windows에서 핀란드어 텍스트를 감지 한 경우를 기억합니다.-1252 히브리어 Windows-1255.

ISO-8859-1에서 임의의 바이너리 데이터가 유효하므로 UTF-8을 먼저 감지합니다 (예외없이 UTF-8을 전달하면 UTF-8이됩니다.) ISO-8859-1 이후에 다른 것을 탐지하려고 시도하지 않는 이유입니다.

4

모든 바이트 시퀀스가 ​​유효한 UTF-8 문자는 아닙니다. 일부 바이트 시퀀스는 유효하지 않으며 \u00F6을 해당 라틴어 -1 문자로 변환하면 유효하지 않은 UTF-8이 생성됩니다.