Scala - 从 ISO-8859-1 转换为 UTF-8 会给外来字符带来陌生感
Posted
技术标签:
【中文标题】Scala - 从 ISO-8859-1 转换为 UTF-8 会给外来字符带来陌生感【英文标题】:Scala - Converting from ISO-8859-1 to UTF-8 gives foreign character strangeness 【发布时间】:2013-02-06 03:30:36 【问题描述】:这是我的问题;我有一个已转换为字节数组的 InputStream,但在运行时我不知道 InputStream 的字符集。我最初的想法是在 UTF-8 中做所有事情,但我发现编码为 ISO-8859-1 并具有外来字符的流存在奇怪的问题。 (那些疯狂的瑞典人)
这是有问题的代码:
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
我错过了什么?
【问题讨论】:
如果您不知道InputStream
中编码的(表面上的)字符的编码,则无法将其转换为字符。就是这么简单。而且...为什么您会期望编码为 ISO-8859-1,然后从 UTF-8 解码适用于任意字符?
Nit: new String("\u00F6")
具有预期的值与编码无关 ..
在运行时确定编码是Content-Type
标头及其各自的charset
参数存在的原因
这不仅仅是一个瑞典字母,也是一个德语变音符号。 :)
要特别清楚,是 "utf-8"
arg(在 new String("\u00F6".getBytes("iso-8859-1"), "utf-8")
中)导致问题 - 调用 System.out.println(new String("\u00F6".getBytes("iso-8859-1")));
会很好地打印 ö
【参考方案1】:
并非所有字节序列都是有效的 UTF-8 字符。某些字节序列无效,并且通过将 \u00F6
转换为其等效的 latin-1 字符,您生成了无效的 UTF-8。
【讨论】:
【参考方案2】:您应该让数据源告诉您编码,但如果这不能发生,您也可以 如果不是 UTF-8,则需要拒绝或猜测编码。
对于西方语言,猜测 ISO-8859-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());
所有这些样板都是为了获取编码异常并能够多次读取相同的数据。
您也可以使用Mozilla Chardet,它使用更复杂 如果不是 UTF-8,则使用启发式方法确定编码。但它并不完美,例如我记得它在 Windows-1252 中检测芬兰文本 作为希伯来语 Windows-1255。
还要注意,任意二进制数据在 ISO-8859-1 中都是有效的,所以这就是为什么你首先检测 UTF-8(如果它毫无例外地通过 UTF-8,它就是 UTF-8,这非常像)并且这就是为什么您无法在 ISO-8859-1 之后尝试检测其他任何内容的原因。
【讨论】:
以上是关于Scala - 从 ISO-8859-1 转换为 UTF-8 会给外来字符带来陌生感的主要内容,如果未能解决你的问题,请参考以下文章
C# 将字符串从 UTF-8 转换为 ISO-8859-1 (Latin1) H
iconv 中的输出缓冲区为空,同时从 ISO-8859-1 转换为 UTF-8