繁体   English   中英

Java 字节缓冲区行为

[英]Java Byte Buffer behavior

我只是在玩 Java ByteBuffers,不明白为什么输出不正确。

import java.nio.ByteBuffer;

public class TestBuffers {
    public static void main(String[] args) {
        ByteBuffer byteBuffer = ByteBuffer.allocate(100);
        byteBuffer.put((byte)'H').put((byte)'e').put((byte)'l').put((byte)'l');
        System.out.println(byteBuffer.asCharBuffer().toString()); // should print "Hell"
    }
}

上面的程序应该打印“Hell”,但它没有。 但是如果我在put()调用中从 1 开始给出位置,那么它就起作用了,为什么?

您的代码和执行该任务的方法存在一些问题:

  1. 没有显式索引的put()方法将更新缓冲区位置。 在四次放置操作之后,缓冲区位置为 4。
  2. asCharBuffer()重用原始缓冲区的内容,从原始缓冲区中的当前位置开始,即 4 并且原始缓冲区没有从该位置开始的实际数据。
  3. 在一系列put操作之后尝试执行get操作之前, flip()确实是正确的操作,但是:
  4. 在 Java 中, char是一个两字节值,这意味着你原来的 4 字节缓冲区将被解释为一个 2 字符缓冲区,例如第一个字符的值将是( char ) ( ( ( ( byte ) 'H' ) << 8 ) + ( byte ) 'e' )

除此之外, ByteBuffer行为完全符合预期并在其 javadoc 中记录。

解决编码问题的示例:

ByteBuffer byteBuffer = ByteBuffer.allocate( 100 );
byteBuffer
        // explicitly converting each char into 2 bytes
        .put( ( byte ) ( 'H' >>> 8 ) ).put( ( byte ) 'H' ) 
        .put( ( byte ) ( 'e' >>> 8 ) ).put( ( byte ) 'e' )
        .put( ( byte ) ( 'l' >>> 8 ) ).put( ( byte ) 'l' )
        .put( ( byte ) ( 'l' >>> 8 ) ).put( ( byte ) 'l' )
        .put( ( byte ) ( 'o' >>> 8 ) ).put( ( byte ) 'o' );
// flipping the buffer to be able access the current content via get operations
byteBuffer.flip();
// reinterpreting the byte sequence as a char sequence
CharBuffer charBuffer = byteBuffer.asCharBuffer();
System.out.println( charBuffer.toString() );

问题是 char 是 16 位,而 byte 是 8 位。 当你投射时,你会丢失一些信息。 您需要为每个字符插入两个字节,然后翻转缓冲区,如下所示:

import java.nio.ByteBuffer;

public class TestBuffers {
  ByteBuffer byteBuffer = ByteBuffer.allocate(100);

  byteBuffer.put((byte) ('H' & 0xFF00)).put((byte) ('H' & 0x00FF)).put((byte) ('E' & 0xFF00))
    .put((byte) ('E' & 0x00FF)).put((byte) ('L' & 0xFF00)).put((byte) ('L' & 0x00FF))
    .put((byte) ('L' & 0xFF00)).put((byte) ('L' & 0x00FF));
  byteBuffer.flip();
  System.out.println(byteBuffer.asCharBuffer().toString()); // should print "Hell"
 }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM