不使用双缓冲从ByteBuffer读取字符串

3

有没有一种方法可以在不先将缓冲区内容读取到中间的byte[]char[]中的情况下从ByteBuffer构造一个String

类似于接受byte[]参数的字符串构造函数的API看起来是理想的:

public String(ByteBuffer buffer, int offset, int length, Charset charset)

...但是这样的东西并不存在。

我找到了如何将ByteBuffer转换为整数和字符串?,但它使用了一个辅助数组。

到目前为止我找到的最好的方法是将字节缓冲区作为CharBuffer进行投影,并调用toString()。但这不允许使用类似于UTF-8的压缩字符串。


你的ByteBuffer支持array()方法吗? - Patricia Shanahan
它是内存映射的,所以我认为不会。但这些都是我希望无论使用什么API都能理解的复杂性。 - Dilum Ranatunga
我对你想要实现的目标感到困惑。您可以使用array方法获取ByteBuffer的后备字节数组。除了不想依赖内部实现细节之外,您的最终目标是什么? - Perception
@Perception,“array”是一个可选操作,可能会抛出“UnsupportedOperationException - If this buffer is not backed by an accessible array”的异常。我猜如果ByteBuffer是一个1 GB的内存映射文件,那么确切的事情将会发生。 - Dilum Ranatunga
@DilumRanatunga - 你可能应该提到你正在使用的具体字节缓冲实现,或者你正在寻找一个通用解决方案。 - Perception
1
基于字节数组的ByteBuffer在各方面都没有什么意义(为什么不直接使用byte[]呢);因此可以合理地假设可能正在使用本机缓冲区。 - StaxMan
4个回答

3

1

这并不存在。

一个ByteBuffer不包含字符。在将它们转换为字符之前,必须将它们转换为字符。

此外,String必须在JVM内存中。ByteBuffer可以映射或直接,在两种情况下都在JVM之外。

为了将数据移动到JVM并将其转换为字符,必须使用辅助数组。


是的,但我不明白为什么String不能在构造函数中完成这个操作。为什么要在旨在高性能的API中强制执行额外的数组复制呢? - Dilum Ranatunga
在一个已经相当复杂的API中,这样做只会增加复杂度,而不会带来任何性能上的好处。 - Simon G.

1

java.lang.String是不可变和最终的,所以最终没有选择,只能提供它已经接受的数据格式。(当然,除了使用反射操纵其内部....)

你可以隐藏丑陋的细节,使用字符串构建器或其他东西的API,但在某个时候将会在内存中有两份数组副本,一个在构建器中,一个用于实际字符串。


在Sun JDK 1.6.0_u34中,例如,java.lang.String有一个包私有构造函数,如下所示:/* Package private constructor which shares value array for speed. */ String(int offset, int count, char value[]) { ... } 在我看来,java.lang中的API可以避免第二个数组... - Dilum Ranatunga
是的,所以如果你使用反射来覆盖对那个构造函数的访问权限,你可以像我之前提到的那样做 :) - Affe
LOL,点头。在这里反思会失去目的。但是包私有意味着同一包中的其他类可以使用构造函数而无需进行任何愚蠢的操作。这个API似乎明确留下来进行优化。我希望他们利用他们拥有的酷炫功能...... - Dilum Ranatunga
如果实际问题只是“为什么Sun没有做XYZ?”,除非一位前Sun工程师碰巧在阅读,否则我们无法提供权威答案.... :) - Affe

0

Stringchar 组成,而不是 byte。您需要一个字符集,用于将字节转换为字符,例如 UTF-8、UTF-16、ISO-8859-1、ISO-8859-5 等。

如果您不知道字符集,就无法确定字节代表的哪个字符


我同意。但这就是为什么我的梦想API需要一个字符集...请看我的原帖。 - Dilum Ranatunga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接