我从文件中读取byte[]
并将其转换为String
:
byte[] bytesFromFile = Files.readAllBytes(...);
String stringFromFile = new String(bytesFromFile, "UTF-8");
我想将此与我从网络服务获得的另一个byte[]
进行比较:
String stringFromWebService = webService.getMyByteString();
byte[] bytesFromWebService = stringFromWebService.getBytes("UTF-8");
因此,我从文件中读取byte[]
并将其转换为String
,然后从我的网络服务获得String
并将其转换为byte[]
。然后我做了以下测试:
// works!
org.junit.Assert.assertEquals(stringFromFile, stringFromWebService);
// fails!
org.junit.Assert.assertArrayEquals(bytesFromFile, bytesFromWebService);
为什么第二个断言失败?
答案 0 :(得分:1)
其他答案涵盖了文件未UTF-8
编码的可能事实,从而导致所描述的症状。
但是,我认为最有趣的方面不是byte[]
断言失败,而是字符串值相同的assert
传递 即可。我不是百分之百确定这是为什么,但我认为通过源代码进行以下拖网可能会给我们答案:
new String(bytesFromFile, "UTF-8");
的工作原理 - 我们看到构造函数调用StringCoding.decode()
UTF-8
字符集,则拨打StringDecoder.decode()
CharsetDecoder.decode()
来决定如果角色不可映射该怎么办(如果出现非UTF-8
字符,我认为会是这种情况)在这种情况下,它使用操作defined by
private CodingErrorAction unmappableCharacterAction
= CodingErrorAction.REPORT;
这意味着它仍然是reports the character it has decoded,即使它在技术上是不可映射的。
我认为这意味着即使代码获得了一个无法映射的字符,它也会替代其最佳猜测 - 因此我猜测它的最佳猜测是正确的,因此String
表示相同比较,但byte[]
不再相同。
catch
中CharacterCodingException
的{{1}}块表示:
StringCoding.decode()
答案 1 :(得分:0)
我完全不明白,但这就是我得到的东西:
问题是数据包含一些字节,这些字节不是有效的UTF-8字节,我通过以下检查知道:
// returns false for my data!
public static boolean isValidUTF8(byte[] input) {
CharsetDecoder cs = Charset.forName("UTF-8").newDecoder();
try {
cs.decode(ByteBuffer.wrap(input));
return true;
}
catch(CharacterCodingException e){
return false;
}
}
当我将编码更改为ISO-8859-1
时,一切正常。奇怪的事情(我还不明白)是为什么我的转换(new String(bytesFromFile, "UTF-8");
)不会抛出任何异常(比如我的isValidUTF8
方法),尽管数据不是有效的UTF-8。
但是,我想我会转到另一个并在Base64字符串中对byte[]
进行编码,因为我不希望编码更麻烦。
答案 2 :(得分:0)
您的代码中的真正问题是您不知道真正的文件编码是什么。 当您从Web服务中读取字符串时,您会得到一系列字符;当您将字符串从字符转换为字节时,转换是正确的,因为您指定了如何使用特定编码转换字节数(" UFT-8")。当您阅读文本文件时,您遇到了另一个问题。您有一个需要转换为字符的字节序列。为了正确地执行它,您必须知道如何将字符转换为字节,即文件编码是什么。对于文件(除非指定),它是一个平台常量;在Windows上,文件以win1252编码(非常接近ISO-8859-1);它取决于linux / unix,我认为UTF8是默认的。
顺便说一下,Web服务调用在引擎盖下进行了第二次操作; http调用使用标题taht定义如何编码字符,即如何从套接字读取字节然后转换为字符。因此,调用SOAP Web服务会返回一个xml(可以编组到Java对象中),并且所有编码操作都已正确完成。
因此,如果您必须从文件中读取字符,则必须面对编码问题;你可以按照你的说法使用BASE64,但是你失去了文本文件的一个主要好处:人类可读,易于调试和开发。