【问题标题】:Java Byte Buffer behaviorJava 字节缓冲区行为
【发布时间】:2014-07-12 09:44:51
【问题描述】:

我只是在玩 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 开始给出位置,那么它可以工作,为什么?

【问题讨论】:

  • 它不打印任何东西...如果我这样做 byteBuffer.flip() 然后它会打印一些垃圾值。
  • 你能发布你的实际代码示例吗?这显然不能编译。
  • 一定是import问题。让我添加 java.nio.ByteBuffer 导入..
  • 您的buf 变量更改了名称,而您缺少() - 没问题,请查看stackoverflow.com/questions/17912640/… 并在缓冲区中执行flip()
  • 已更正..谢谢。我在这个窗口中输入了代码,所以习惯于输入 IDE :(

标签: java nio


【解决方案1】:

在您的代码和您完成该任务的方法中存在一些问题:

  1. put() 没有显式索引的方法将更新缓冲区位置。经过四次 put 操作后,缓冲区位置为 4。
  2. asCharBuffer() 重用原始缓冲区的内容,从原始缓冲区中的当前位置开始,即 4,并且原始缓冲区没有从该位置开始的实际数据。
  3. 在一系列put 操作之后尝试执行get 操作之前,flip() 确实是正确的操作,但是:
  4. 在 Java 中,char 是一个 2 字节值,这意味着您原来的 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() );

【讨论】:

    【解决方案2】:

    问题是 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"
     }
    }
    

    【讨论】:

    • 虽然此代码可能适用于 ASCII 值,但您会丢失高值(应该是位移)
    • 它们实际上是,但char 始终是两个字节。这意味着当它们转换回char时,H字节和E字节将组合在一起形成一个字符,产生他所看到的随机垃圾。
    • @Dave True,但我要的是最小的 ASCII 示例 :)
    • @EvanKnowles 作为奥列格的答案更详尽,选择它作为答案。感谢您的帮助:)
    猜你喜欢
    • 1970-01-01
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多