You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中CharSequence转UTF-8 byte[]方法及编码长度异常问题

代码无法运行&长度异常的核心原因

直接导致编译失败的错误

代码在Java 16环境下跑不起来和版本兼容无关,是本身存在3个基础语法/API调用错误:

  • 导入语句写法错误:java.nio.charset是包名不是类名,原代码写的import java.nio.charset;无法导入Charset类,正确写法是import java.nio.charset.Charset;或者批量导入包下所有类import java.nio.charset.*;
  • 异常未声明:checkEquals方法中直接抛出受检异常Exception,但方法签名没有声明throws Exception,所有调用该方法的上层方法也没有做异常捕获或声明,会被编译器直接拦截。
  • 调用不存在的方法:main方法中调用了未定义的test()方法,实际应该直接调用编写的charSequenceToUtf8方法。

10个'A'返回11字节数组的原因

修完上述编译错误后出现的长度不符问题,是NIO Buffer的典型误用:
Charset.encode()返回的ByteBuffer会预分配一块大于等于实际编码结果长度的内存作为后备数组,byteBuffer.length()返回的是当前有效数据的长度(即limit和position的差值),但调用byteBuffer.array()会返回整个后备数组——这个数组的长度是缓冲区的总容量(capacity),通常比有效数据长度大,未使用的位置默认填充0值。
测试2-9个'A'时刚好缓冲区预分配容量和有效数据长度相等,所以没暴露问题;当输入10个'A'时缓冲区预分配了11字节容量,最后1字节的默认0值被当成有效数据读出,才会得到长度11、末尾多0的结果。
核心误区:永远不要假设ByteBuffer的array()方法返回的数组长度等于有效编码结果长度。
额外说明:代码里写死断言编码后字节长度等于字符长度,这个逻辑本身就不成立——UTF-8是变长编码,ASCII字符确实占1字节,但中文、emoji等字符占2-4字节不等,这个断言只在纯ASCII输入下偶然成立。

正确的CharSequence转UTF-8 byte[]实现

根据需求选对应写法即可:

写法1:最简洁无坑(日常开发推荐)

不需要手动操作NIO缓冲区,Java 7+全版本兼容:

import java.nio.charset.StandardCharsets;

public static byte[] charSequenceToUtf8(final CharSequence input) {
    if (input == null) {
        return new byte[0];
    }
    return input.toString().getBytes(StandardCharsets.UTF_8);
}

注意不要用重载的getBytes(String charsetName)方法传"UTF-8"字符串,避免拼写错误抛出受检异常,直接用StandardCharsets里预定义的常量即可。

写法2:避免中间String对象的NIO实现

如果不想通过toString()生成中间String对象,手动操作NIO时一定要注意只截取有效数据段,不要直接返回整个后备数组:

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;

public static byte[] charSequenceToUtf8(final CharSequence input) {
    if (input == null) {
        return new byte[0];
    }
    CharBuffer charBuffer = CharBuffer.wrap(input);
    ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(charBuffer);
    // 仅复制缓冲区中实际存储有效数据的片段
    byte[] result = Arrays.copyOfRange(
            byteBuffer.array(),
            byteBuffer.position(),
            byteBuffer.limit()
    );
    // 清空缓冲区释放引用
    byteBuffer.clear();
    charBuffer.clear();
    return result;
}

内容的提问来源于stack exchange,提问作者Ian Boyd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 00:30:57