ByteBuffer.asCharBuffer() 使用什么字符集?

问题描述 投票:0回答:4

ByteBuffer.asCharBuffer() 使用什么字符集?它似乎在我的系统上将 3 个字节转换为 1 个字符。

相关说明,CharsetDecoder 与 ByteBuffer.asCharBuffer() 有何关系?

更新:关于我正在使用的 ByteBuffer 的实现,我正在调用

ByteBuffer.allocate(1024).asCharBuffer()
。我无法评论幕后使用的实现。

java nio
4个回答
3
投票

对于第一个问题 - 我相信它使用 Java 的本机字符编码(UTF-16)。


2
投票

据我了解,它没有任何用处。它只是假设它已经被正确解码为 Java 字符串,这意味着 UTF-16。这可以通过查看 HeapByteBuffer 的源代码来显示,其中返回的 charbuffer 最终调用(小端版本):

static private char makeChar(byte b1, byte b0) {
return (char)((b1 << 8) | (b0 & 0xff));
}

因此,这里处理的唯一事情是您负责的其余部分的字节序。这也意味着使用可以指定编码的 Decoder 类通常更有用。


0
投票

看jdk7,

jdk/src/share/classes/java/nio

  1. X-Buffer.java.template
    ByteBuffer.allocate()
    映射到
    Heap-X-Buffer.java.template
  2. Heap-X-Buffer.java.template
    ByteBuffer.asCharBuffer()
    映射到
    ByteBufferAs-X-Buffer.java.template
  3. ByteBuffer.asCharBuffer().toString()
    调用
    CharBuffer.put(CharBuffer)
    但我不知道这会导致什么

最终这可能会导致

Bits.makeChar()
,其定义为:

static private char makeChar(byte b1, byte b0) {
    return (char)((b1 << 8) | (b0 & 0xff));
}

但我不知道怎么办。


0
投票

我想扩展 @Petteri H 的答案。 确实,

asCharBuffer()
期望
ByteBuffer
已经是 UTF-16 编码的。不执行进一步的编码转换。您可以使用下面的代码运行实验。

首先,创建一个名为

test.txt
的纯文本文件,其中包含几行。

Hello World
Hi Moon
Howdy Jupiter

该文件默认采用 UTf-8 编码。我们预计这是一个问题,因为

CharBuffer
将读取两个连续的字节来构造一个字符并给你垃圾值。稍后我们会解决这个问题。

以下代码将简单地转储文件中的每个字符。注意:它将把每个双字节序列视为一个字符。

import java.io.RandomAccessFile;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
         try (var file = new RandomAccessFile("test.txt", "r")) {
            var mappedMemory = file.getChannel()
                    .map(FileChannel.MapMode.READ_ONLY, 0, file.length());
            var buff = mappedMemory.asCharBuffer();

            for (int i = 0; i < buff.length(); ++i) {
                var ch = buff.get(i);

                System.out.print(ch);
            }
         } catch (Exception e) {
            e.printStackTrace();
         }
    }
}

当您运行代码时,您将看到意外的字符:

䡥汬漠坯牬搊䡩⁍潯渊䡯睤礠䩵灩瑥爊

现在,让我们使用 UTF-16 对同一文件进行编码。

iconv -f utf-8 -t utf-16 test.txt > test-fixed.txt

将 Java 代码更改为

test-fixed.txt
。然后再次运行。

现在,您将看到正确的输出。

有趣的是,

CharBuffer
会跳过
test-fixed.txt
文件将具有的 BOM 标记。

© www.soinside.com 2019 - 2024. All rights reserved.