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

ByteBuffer::asCharBuffer返回的CharBuffer首字符为何总是空格?

问题解析:CharBuffer输出开头空格与长度异常的原因及解决办法

嘿,这可不是Java NIO类库的Bug,其实是你对UTF-16编码的**字节顺序标记(BOM)**特性不熟悉导致的,我来给你拆解清楚:

核心原因:UTF-16的BOM被当成了普通字符

当你执行"hello".getBytes(Charset.forName("UTF-16"))时,Java的UTF-16编码默认会在字节数组的开头添加字节顺序标记(BOM)——这是两个字节的0xFE 0xFF(对应大端字节序的标识),用来告诉后续解析器字节的排列顺序。

但当你把包含BOM的字节数组直接包装成ByteBuffer再转成CharBuffer时,CharBuffer会把开头的BOM字节解析成一个Unicode字符:\uFEFF(零宽无间断空格)。这个字符在控制台输出时通常会显示为一个空格,同时它也会被算入CharBuffer的长度中,所以你看到buffer.length()返回6(5个"hello"字符+1个BOM字符),输出开头就多了个空格。

解决办法

你可以通过两种方式解决这个问题:

1. 使用不带BOM的UTF-16编码变体

直接指定UTF-16BE(大端序)或UTF-16LE(小端序)编码,这些编码不会自动生成BOM:

public static void main(String[] args) { 
    byte[] byteArray = "hello".getBytes(Charset.forName("UTF-16BE")); 
    CharBuffer buffer = ByteBuffer.wrap(byteArray).asCharBuffer(); 
    System.out.println(buffer.length()); // 输出5
    for (int i = 0; i < buffer.length(); i++) { 
        System.out.print(buffer.get(i)); // 输出hello,无开头空格
    } 
}

2. 手动跳过BOM字节

如果你必须使用默认的UTF-16编码(带BOM),可以在包装ByteBuffer时跳过开头的2个BOM字节:

public static void main(String[] args) { 
    byte[] byteArray = "hello".getBytes(Charset.forName("UTF-16")); 
    // 跳过开头2个BOM字节,从索引2开始,长度为总长度减2
    CharBuffer buffer = ByteBuffer.wrap(byteArray, 2, byteArray.length - 2).asCharBuffer(); 
    System.out.println(buffer.length()); // 输出5
    for (int i = 0; i < buffer.length(); i++) { 
        System.out.print(buffer.get(i)); // 输出hello,无开头空格
    } 
}

内容的提问来源于stack exchange,提问作者Peter Enns

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:26:46