从US-ASCII编码的字符串获取UTF-8编码

时间:2015-12-02 14:19:42

标签: java utf-8 character-encoding

我有一个字符串“Château”,带有UTF-8编码&它被转换为US-ASCII格式为“Ch ?? teau”(在我的应用程序的底层库中)

现在,我希望从“U-ASCII”转换后的字符串“Ch ?? teau”中获取原始字符串“Château”。但是,我无法使用以下代码获得它。

StringBuilder masterBuffer = new StringBuilder();
byte[] rawDataBuffer = (Read from InputStream) // say here it is "Château"
String rawString = new String(rawDataBuffer, "UTF-8");
masterBuffer.append(rawString);
onMessageReceived(masterBuffer.toString().getBytes()) => Here, getBytes() uses the platform's default charset 'US-ASCII.

我的应用程序收到US-ASCII编码的字节数组。 在应用程序方面,即使我试图从中获取UTF-8字符串,也没用。 转换尝试仍然提供“Ch ?? teau”。

String asciiString = "Ch??teau";
String originalString = new String(asciiString.getBytes("UTF-8"), "UTF-8");
System.out.println("orinalString: " + originalString);

'originalString'的值仍然是“Ch ?? teau”。

这是正确的方法吗?

谢谢,

2 个答案:

答案 0 :(得分:3)

你做不到。您通过转换为US-ASCII丢失了信息。你无法找回失去的东西。

答案 1 :(得分:1)

您的代码正在接收UTF-8编码的字节数组,正确将其转换为Java String,但然后将该字符串转换为ASCII编码的字节数组。 ASCII不支持â字符,这就是它们被转换为?的原因。转换完成后,就不会再回头了。 ASCII是UTF-8的子集,ASCII中的?在UTF-8中也是?

解决方案是停止转换为ASCII以开始。您应该转换回UTF-8:

StringBuilder masterBuffer = new StringBuilder();
byte[] rawDataBuffer = ...; // Read from InputStream
String rawString = new String(rawDataBuffer, "UTF-8");
masterBuffer.append(rawString);
onMessageReceived(masterBuffer.toString().getBytes("UTF-8"));

至少就这种方式而言,对于真正的ASCII字符,接收器永远不会知道差异(因为ASCII是UTF-8的子集),并且非ASCII字符不会再丢失。接收器只需要知道期望UTF-8而不是ASCII。而且,您的代码将更具可移植性,因为您将不再依赖于特定于平台的默认字符集(并非所有平台都默认使用ASCII)。

当然,在您的示例中,您的StringBuilder是多余的,因为您没有向其添加任何其他内容,因此您可以将其删除:

byte[] rawDataBuffer = ...; // Read from InputStream
String rawString = new String(rawDataBuffer, "UTF-8");
onMessageReceived(rawString.getBytes("UTF-8"));

然后String也变得多余了:

byte[] rawDataBuffer = ...; // Read from InputStream
onMessageReceived(rawDataBuffer);

如果onMessageReceived()期望字节作为输入,为什么浪费开销将字节转换为字符串再次转换为字节?