Java中与平台相关的编码问题
在对从AIX移动到LINUX服务器的一段java代码中的文件生成问题进行故障排除时注意到了这种行为Java中与平台相关的编码问题,java,encoding,Java,Encoding,在对从AIX移动到LINUX服务器的一段java代码中的文件生成问题进行故障排除时注意到了这种行为 Charset.defaultCharset(); 在AIX上返回ISO-8859-1,在Linux上返回UTF-8,在我的windows 7上返回windows-1252。话虽如此,我还是想弄清楚为什么在Linux机器上,nlength=24(每个字母数字字符3个字节),而在AIX和Windows上是8 String inString = "ABC12345"; byte[]
Charset.defaultCharset();
在AIX上返回ISO-8859-1
,在Linux上返回UTF-8
,在我的windows 7上返回windows-1252
。话虽如此,我还是想弄清楚为什么在Linux机器上,nlength
=24(每个字母数字字符3个字节),而在AIX和Windows上是8
String inString = "ABC12345";
byte[] ebcdicByte = new byte[inString.length()];
System.out.println("Length:"+inString.getBytes("Cp1047").length);
ebcdicByte = inString.getBytes("Cp1047").);
String ebcdicString = new String( ebcdicByte);
int nlength = ebcdicString.getBytes().length;
你对事物的理解是错误的 这是Java 有
字节
s。有char
s。还有默认的编码
当从byte
s转换为char
s时,您必须
当从char
s转换为byte
s时,您必须
当然,除了非常有限的字符集之外,您永远不会有1-1个字符字节的映射
如果您发现编码/解码有问题,原因很简单:在代码的某个地方(幸运的话,只有一个地方;如果不幸运的话,有几个地方),您没有指定解码和编码时要使用的字符集
还请注意,默认情况下,失败时的编码/解码行为会将其转换为不可映射的字符
/字节
序列
所有这些都表明:一个
字符串
没有编码。当然,它是一系列的char
s,而char
是一个基本类型;但它也可能是一个信鸽流,两个基本过程保持不变:你需要从字节解码,你需要编码到字节;如果任一部分失败,则以无意义的字节序列/突变信鸽结束。必须在倒数第二行指定字符集
String ebcdicString = new String( ebcdicByte,"Cp1047");
如前所述,编码/解码时始终必须指定字符集。基于fge的答案 您的观察是因为
新字符串(ebcdicByte)
和ebcdicString.getBytes()
使用平台的默认字符集
ISO-8859-1和windows-1252是单字节字符集。在这些字符集中,一个字节总是代表一个字符。因此,在AIX和Windows中,当您执行新建字符串(ebcdicByte)
时,总会得到一个字符计数与字节数组长度相同的字符串。类似地,将字符串转换回字节将使用一对一映射
但在UTF-8中,一个字符不一定对应一个字节。在UTF-8中,字节0到127是字符的单字节表示,但所有其他值都是多字节序列的一部分
然而,不仅仅是具有高位集的任何字节序列都是有效的UTF-8序列。如果给UTF-8解码器的字节序列不是正确编码的UTF-8字节序列,则认为其格式不正确<代码>新字符串只会将格式错误的序列映射到一个特殊的默认字符,通常是“�" ('\ufffd'
)。可以通过显式创建自己的CharsetDecoder并调用其方法来更改该行为,而不仅仅是依赖新字符串(字节[])
因此,ebcdicByte
数组包含“ABC12345”的EBCDIC表示:
所有这些都不是有效的UTF-8字节序列,因此ebcdicString
最终为“\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd\ufffd”
,即”��������“
您的最后一行代码调用了
ebcdicString.getBytes()
,它同样没有指定字符集,这意味着将使用默认字符集。使用UTF-8,“�“被编码为三个字节,EF BF BD。由于在ebcdicString
中有八个字节,所以得到的是3×8=24个字节。我喜欢你如此容易理解地解释事情
C1 C2 C3 F1 F2 F3 F4 F5