代码段:
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个字节,如果输入字符串只包含好的旧单字节字符,我最后得到奇数空字符。
我想知道这是否记录在哪里?
此页:
https://docs.oracle.com/javase/7/docs/api/java/nio/charset/Charset.html#encode(java.lang.String)
没有提供有关此类行为的线索。
P上。 S.我是否正确无论如何,上述代码段最好由以下代码替换:
s.getBytes(StandardCharsets.UTF_8)
我从其来源看到的还会修剪结果以避免那些空字符?
然后,java.nio.charset.Charset编码(字符串s)应该用于什么?
答案 0 :(得分:8)
Charset.encode()
,而在于Buffer.array()
。如果您打印Charset.forName("UTF-8").encode(s)
,您会发现输出为
java.nio.HeapByteBuffer[pos=0 lim=10 cap=11]
ByteBuffer的长度限制为10,字符串的长度为 capacity 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)
当你call .array()
时,它将返回整个后备数组,因此即使包含超出限制的内容也是如此。
提取Java字节数组的实际方法是the .get()
method:
ByteBuffer buf = Charset.forName("UTF-8").encode(s);
byte[] encoded = new byte[buf.limit()];
buf.get(encoded);
System.out.println(Arrays.toString(encoded));
这看起来像一团糟?因为“nio”表示 N 强烈 I / O 。创建Buffer类型,以便它可以轻松地包装C数组。它使得与本机代码交互(例如读/写文件或发送/接收网络数据)非常有效。这些NIO API通常直接使用Buffer
,而不会在其间构建任何byte[]
。如果您只使用Buffer
,则不需要存在中间的两行:)。
如果整个操作都在Java中,那么只需调用s.getBytes(StandardCharsets.UTF_8)
。
答案 1 :(得分:0)
如果您只想查看编码为UTF8的String的字节数组,那么只需使用getBytes(Charset charset)方法。它可能看起来像这样:
AddCommentMessage
您将看到每个字符有2个字节。您的输出符合String hello = "qwertyuiop";
byte[] helloBytes_UTF_8 = hello.getBytes(StandardCharsets.UTF_8);
字符集。如果你想用不同的编码玩更多,那么我建议使用一个带有一些工具的小型开源库,其中一个允许你将字符串转换为UNICODE(UTF-8)表示并返回。 Open Source Java library with stack trace filtering, Silent String parsing Unicode converter and Version comparison。本文介绍了库以及如何使用它。您也可以下载源代码和javadoc。特别要查找段落" 字符串Unicode转换器"。使用此类,您将字符串StandardCharsets.ISO_8859_1
转换为:"qwertyuiop"
\ u符号后面的每四个数字代表十六进制表示的2个字节(一个字符)。