Java 将字符串编码为UTF-8字节时添加的空字符?
代码片段:Java 将字符串编码为UTF-8字节时添加的空字符?,java,character-encoding,Java,Character Encoding,代码片段: public static void main(String[] args) { String s = "qwertyuiop"; System.out.println(Arrays.toString(Charset .forName("UTF-8") .encode(s) .array())); } 印刷品: [113, 119, 101, 114, 116, 121, 117, 105, 111, 112, 0] 这似
public static void main(String[] args) {
String s = "qwertyuiop";
System.out.println(Arrays.toString(Charset
.forName("UTF-8")
.encode(s)
.array()));
}
印刷品:
[113, 119, 101, 114, 116, 121, 117, 105, 111, 112, 0]
这似乎是因为,在java.nio.charset.CharsetEncoder类中,对于UTF-8,averageBytesPerChar变量似乎是1.1。因此,它分配11个字节,而不是10个,并且,如果输入字符串只包含好的旧单字节字符,我最终会得到那个奇怪的空字符
我想知道这是否在任何地方都有记录
本页:
对这种行为一无所知
另外,我是否正确地理解了,在任何情况下,上面的代码片段最好替换为:
s.getBytes(StandardCharsets.UTF_8)
我从它的源代码中看到,为了避免那些空字符,它还会修剪结果
那么,java.nio.charset.charset的编码(字符串s)应该是什么呢?问题不在于charset.encode()
,而在于Buffer.array()
。
如果您打印了Charset.forName(“UTF-8”).encode
,您会发现输出是
java.nio.HeapByteBuffer[pos=0 lim=10 cap=11]
ByteBuffer具有限制10(字符串长度)和容量11(缓冲区的总分配大小)。如果更改编码,则限制和容量可能会有更大的变化,例如:
System.out.println(Charset.forName("UTF-16").encode(s));
// java.nio.HeapByteBuffer[pos=0 lim=22 cap=41]
// (2 extra bytes because of the BOM, not null-termination)
当您选择时,它将返回整个备份阵列,因此即使超出限制的内容也将被包括在内
提取Java字节数组的实际方法是:
这看起来一团糟?因为“nio”的意思是NI/O。创建缓冲区类型是为了方便地包装C数组。它使得与本机代码的交互(如读/写文件或发送/接收网络数据)非常高效。这些NIOAPI通常直接使用缓冲区
,而不在缓冲区之间构建任何字节[]
。如果只使用缓冲区
,中间两行不需要存在:)
如果整个操作都在Java中,是的,只需调用
s.getBytes(StandardCharsets.UTF_8)
如果您只想查看编码为UTF8的字符串的字节数组,只需使用方法即可。它可能看起来像这样:
String hello = "qwertyuiop";
byte[] helloBytes_UTF_8 = hello.getBytes(StandardCharsets.UTF_8);
您将看到每个字符有2个字节。您的输出符合标准字符集.ISO_8859_1
字符集。如果您想更多地使用不同的编码,那么我建议使用一个带有一些UTIL的小型开源库,其中一个允许您将字符串共同转换为UNICODE(UTF-8)表示形式并返回。本文介绍了该库以及如何使用它。您还可以下载源代码和javadoc。特别要查找段落“字符串Unicode转换器””。使用该类,您将把字符串“qwertyuiop”
转换为:“\u0071\u0077\u0065\u0072\u0074\u0079\u0075\u0069\u006f\u0070”
\u符号后的每四位数字表示两个字节(一个字符),以十六进制表示
String hello = "qwertyuiop";
byte[] helloBytes_UTF_8 = hello.getBytes(StandardCharsets.UTF_8);