2013-02-03 151 views
1

我有一个“windows1255”编码的字符串,没有任何安全的方式,我可以将其转换为“UTF-8”编码问题

字符串,反之亦然?

一般是有一种安全的方式(意思是数据不会被损坏)在Java中

编码之间的转换?

 str.getBytes("UTF-8"); 
    new String(str,"UTF-8"); 

如果原始字符串未被编码为“UTF-8”,数据是否会被损坏?

+0

你可能有一个看看这个: http://stackoverflow.com/questions/4016671/how-to-parse-a-string-that-is-in -a-different-encoding-from-java – Danyel

回答

2

在Java中,您可以不使用正确编码的String对象作为UTF-16以外的任何其他对象 - 因为这是由规范定义的对象的唯一编码。当然,你可以做一些不喜欢的事情,比如把一个char []放在一个char []中,并且从中创建一个String,但是事情很快就会出错。

你可以用各种不同的方式编码byte [],并且可以使用带有字符集的构造函数以及与代码中的getBytes一起将它们转换为String。

因此,您可以使用String作为中间值进行转换。我不知道JDK有任何方法可以进行直接转换,但是在实践中该中间体可能不会太昂贵。

关于往返转换 - 通常不是真的,您可以在不丢失数据的情况下在编码之间进行转换。只有少数编码可以处理全部的Unicode字符(例如UTF系列,GB18030等) - 而许多遗留字符集仅编码一小部分子集。除非确定输入属于可表示集,否则无法安全地往返这些字符集而不会丢失数据。

1

字符串试图是一个抽象字符序列,它没有从其用户的视角 的任何编码。当然,它必须有一个内部编码,但这是一个实现细节。

将String编码为UTF-8是没有意义的,然后将结果解码为UTF-8。这将是任何操作,因为:

(new String(str.getBytes("UTF-8"), "UTF-8")).equals(str) == true; 

但也有情况下字符串抽象分崩离析和上面的将是一个“有损”的转换。由于内部的 实现细节,字符串可以包含不能用UTF-8(或任何编码 ,包括内部UTF-16编码*)表示的不成对的UTF-16替代品。所以它们会在编码中丢失,并且当你解码时,你会得到没有无效的不成对代理的原始字符串。

我可以从你的问题的唯一的事情是,你必须从解释二进制数据的Windows-1255,它应该在UTF-8已经解释的字符串结果。 要解决这个问题,您必须转到此源代码并明确使用UTF-8解码。

但是,如果你的字符串结果是错误解释,你不能真正做任何事情,因为很多字节在Windows-1255中没有任何表示,并且没有将其写入字符串。

如果不是的话,你可以完全恢复原来的预期的消息:

new String(str.getBytes("Windows-1255"), "UTF-8"); 

*这其实是错误的Java允许未成代理人在其字符串存在摆在首位因为它不是有效的UTF-16

+0

Ac通过几乎所有处理'char'或'Character'的方法,'String'确实向最终用户公开了UTF-16编码的事实。诸如'charAt'等方法,任何需要索引或长度的方法等,都暴露了“String”代码单元为UTF-16的事实。这很不幸,可能是UCS2扩展为UTF-16后,在Java中的这种行为已经正式化之后的结果。如果UCS2没有被取代,那么API将是干净的,不会暴露代理等。 – BeeOnRope

+0

@BeeOnRope是的,但只有在很少使用的辅助平面上才会显现。它仍然可以正常使用BMP,并且没有不成对的代理(请参阅答案中的脚注),这通常是99%的情况。 – Esailija

+0

当然,但我认为你编写的代码将API视为实际情况,并且涵盖了100%的情况,而不是99%的情况,并且交叉手指指出没有任何BMP字符出现。忽略它就像说你可以忽略UI中的RTL文本,夏令时,整数溢出等等,因为它不会发生超过1%的时间。 字符串,从根本上呈现一个UTF-16 API。大多数情况下,你可以把它看作Unicode并放弃它,但我绝对不会这样写代码,我绝不会声明“它从用户的角度来看没有任何编码” 。 – BeeOnRope