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 会给外来字符带来陌生感的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法从 UTF8 转换为 ISO-8859-1?

将字符串从 UTF-8 转换为 ISO-8859-1

C# 将字符串从 UTF-8 转换为 ISO-8859-1 (Latin1) H

iconv 中的输出缓冲区为空,同时从 ISO-8859-1 转换为 UTF-8

使用 NSString 将 UTF-8 编码转换为 ISO 8859-1 编码

如何将字符串(例如“iso-8859-1”)转换为其对应的 String.Encoding?