Java 将字符串转换为字节[]返回错误的值(编码?)
我从文件中读取Java 将字符串转换为字节[]返回错误的值(编码?),java,Java,我从文件中读取字节[],并将其转换为字符串: byte[] bytesFromFile = Files.readAllBytes(...); String stringFromFile = new String(bytesFromFile, "UTF-8"); 我想将其与从web服务获得的另一个字节[]进行比较: String stringFromWebService = webService.getMyByteString(); byte[] bytesFromWebService = s
字节[]
,并将其转换为字符串
:
byte[] bytesFromFile = Files.readAllBytes(...);
String stringFromFile = new String(bytesFromFile, "UTF-8");
我想将其与从web服务获得的另一个字节[]
进行比较:
String stringFromWebService = webService.getMyByteString();
byte[] bytesFromWebService = stringFromWebService.getBytes("UTF-8");
因此,我从文件中读取字节[]
并将其转换为字符串
,然后从web服务中获取字符串
,并将其转换为字节[]
。然后我进行以下测试:
// works!
org.junit.Assert.assertEquals(stringFromFile, stringFromWebService);
// fails!
org.junit.Assert.assertArrayEquals(bytesFromFile, bytesFromWebService);
为什么第二个断言失败了?我不完全理解,但下面是我得到的结果: 问题是,数据包含一些无效的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
时,一切正常。奇怪的是(a还不明白)为什么我的转换(newstring(bytesFromFile,“UTF-8”);
)没有抛出任何异常(比如我的isValidUTF8
方法),尽管数据不是有效的UTF-8
但是,我想我会换一种方式,将我的
字节[]
编码为Base64字符串,因为我不想在编码方面遇到更多麻烦。您代码中的真正问题是您不知道真正的文件编码是什么。
当您从web服务读取字符串时,您会得到一个字符序列;当您将字符串从字符转换为字节时,转换是正确的,因为您指定了如何使用特定编码(“UFT-8”)在字节中转换字符。当你阅读一个文本文件时,你会面临一个不同的问题。您有一个需要转换为字符的字节序列。为了正确地执行此操作,您必须知道如何将字符转换为字节,即文件编码是什么。对于文件(除非指定),它是一个平台常量;在windows上,文件用win1252编码(非常接近ISO-8859-1);取决于linux/unix,我认为UTF8是默认值
顺便说一句,web服务调用在引擎盖下执行了decond操作;http调用使用头taht定义字符的编码方式,即如何从套接字读取字节,然后转换为字符。因此,调用soapweb服务将返回一个xml(可以编组为Java对象),所有编码操作都已正确完成
因此,如果必须从文件中读取字符,则必须面对编码问题;您可以如您所述使用BASE64,但您失去了文本文件的一个主要优点:文本文件可读性强,易于调试和开发。其他答案涵盖了文件未经UTF-8编码,从而导致所述症状的可能事实 然而,我认为最有趣的方面不是
byte[]
断言失败,而是assert
字符串值相同的通过了。我不能百分之百确定这是为什么,但我认为下面对源代码的搜索可能会给我们答案:
- 看看如何工作-我们看到构造函数调用
- 如果提供了tht
字符集,则依次调用UTF-8
- 这将调用which来决定在角色不可映射时应该做什么(我猜如果出现非
角色,情况就是这样)UTF-8
- 在本例中,它使用一个动作
- 这意味着它仍然存在,即使它在技术上无法实现
- 我认为这意味着,即使代码获得了一个不可复制的字符,它也会替换它的最佳猜测-因此我猜测它的最佳猜测是正确的,因此在比较中,
表示是相同的,但字符串
不再相同字节[]
StringCoding.decode()
中CharacterCodingException
的catch
块表示:
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn't happen
如果您尝试转储每个数组,它们在什么点不同?它们在任何值和长度上都不同。他们完全不同。我假设它与编码有关,但我不明白…是否可能发布不同数据的样本(或具有相同问题的某些测试数据)?除非您的文件具有有效的UTF-8编码,否则失败的断言没有什么奇怪的。即使在完全有效的编码情况下,仍然可能存在差异(如字节顺序标记),这些差异可能存在于
字节
数组中,也可能不存在。字符串(byte[],String)是否可以用unicode替换字符替换无效字节?
} catch (CharacterCodingException x) {
// Substitution is always enabled,
// so this shouldn't happen