Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
理解java ByteBuffer_Java_Bytebuffer - Fatal编程技术网

理解java ByteBuffer

理解java ByteBuffer,java,bytebuffer,Java,Bytebuffer,我一直在试图理解Java ByteBuffer是如何工作的。我的目标是写一个字符串到ByteBuffer,然后读回。我想了解ByteBuffer属性(如限制、容量、剩余容量、位置)是如何因读/写操作而受到影响的 下面是我的测试程序(为了简洁起见删除了导入语句) } 输出 init: ByteBuffer [limit=1000, capacity=1000, position=0, remaining=1000] write: ByteBuffer [limit=1000, capacity=1

我一直在试图理解Java ByteBuffer是如何工作的。我的目标是写一个字符串ByteBuffer,然后读回。我想了解
ByteBuffer
属性(如
限制、容量、剩余容量、位置)是如何因读/写操作而受到影响的

下面是我的测试程序(为了简洁起见删除了导入语句)

}

输出

init: ByteBuffer [limit=1000, capacity=1000, position=0, remaining=1000]
write: ByteBuffer [limit=1000, capacity=1000, position=0, remaining=1000]
data read: 
read: ByteBuffer [limit=0, capacity=1000, position=0, remaining=0]
正如您所看到的,在调用
readBuffer()
之后没有数据,如果在写操作和读操作之后出现不同的字段,则值没有变化

更新

下面是我最初试图理解的工作代码

// retrieve the screenshot
            // (this method - via ByteBuffer - seems to be the fastest)
            ByteBuffer bytes = ByteBuffer.allocate (ss.width * ss.height * ss.bpp / 8);
            is = new BufferedInputStream(is);   // buffering is very important apparently
            is.read(bytes.array());             // reading all at once for speed
            bytes.position(0);                  // reset position to the beginning of ByteBuffer
请帮助我理解这一点

谢谢



您没有在
writeBuffer()
方法中写入任何内容


您可以使用类似于
字节的内容。put(b)
您没有在
writeBuffer()方法中写入任何内容


您可以使用类似于
字节的内容。放入(b)
您的缓冲区从未被填满
bytes.array()
仅检索备份字节数组。如果对此写入任何内容,则
ByteBuffer
字段(当然数组本身除外)不受影响。所以位置保持在零

in.read(bytes.array())
中执行的操作与
byte[]tmp=bytes.array()
后接
in.read(tmp)
相同。对
tmp
变量的更改不能反映在
bytes
实例中。后备数组已更改,这可能意味着
ByteBuffer
的内容也已更改。但是进入后备字节数组的偏移量(包括位置和限制)不是

您应该只使用任何
put
方法(不带索引)来填充
ByteBuffer
,例如


我将提供一个代码片段,让您思考如何处理字符串、编码以及字符和字节缓冲区:

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.StandardCharsets;

public class TestBuffer {

    private static final String testStr = "Stackoverflow is a great place to discuss tech stuff!";
    private static final boolean END_OF_INPUT = true;

    private ByteBuffer bytes = ByteBuffer.allocate(1000);

    public TestBuffer() {

        System.out.println("init   : " + bytes.toString());
    }

    public static void main(String a[]) {
        TestBuffer buf = new TestBuffer();
        buf.writeBuffer();
        buf.readBuffer();
    }

    // write testStr to buffer
    private void writeBuffer() {
        CharBuffer testBuffer = CharBuffer.wrap(testStr);
        CharsetEncoder utf8Encoder = StandardCharsets.UTF_8.newEncoder();
        CoderResult result = utf8Encoder.encode(testBuffer, bytes, END_OF_INPUT);
        if (result.isError()) {
            bytes.clear();
            throw new IllegalArgumentException("That didn't go right because " + result.toString());
        }
        if (result.isOverflow()) {
            bytes.clear();
            throw new IllegalArgumentException("Well, too little buffer space.");
        }
        System.out.println("written: " + bytes.toString());
        bytes.flip();
    }

    // read buffer data back to byte array and print
    private void readBuffer() {
        byte[] b = new byte[bytes.remaining()];
        bytes.get(b);
        System.out.println("data   : " + new String(b, StandardCharsets.UTF_8));
        System.out.println("read   : " + bytes.toString());
        bytes.clear();
    }
}
请注意,缓冲区和流实际上是处理顺序数据的两种不同方式。如果你想同时使用这两种方法,你可能太聪明了

您也可以在不使用
CharBuffer
ByteBuffer
的情况下,使用
byte[]
缓冲区和由



Android的那段代码完全滥用了ByteBuffer的
。它应该只创建一个
字节[]
并包装它,设置容量限制。无论您做什么,都不要将其作为处理
ByteBuffer
的示例。它使我厌恶地流泪。这样的代码是一个等待发生的错误。

您的缓冲区永远不会被填满
bytes.array()
仅检索备份字节数组。如果对此写入任何内容,则
ByteBuffer
字段(当然数组本身除外)不受影响。所以位置保持在零

in.read(bytes.array())
中执行的操作与
byte[]tmp=bytes.array()
后接
in.read(tmp)
相同。对
tmp
变量的更改不能反映在
bytes
实例中。后备数组已更改,这可能意味着
ByteBuffer
的内容也已更改。但是进入后备字节数组的偏移量(包括位置和限制)不是

您应该只使用任何
put
方法(不带索引)来填充
ByteBuffer
,例如


我将提供一个代码片段,让您思考如何处理字符串、编码以及字符和字节缓冲区:

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.StandardCharsets;

public class TestBuffer {

    private static final String testStr = "Stackoverflow is a great place to discuss tech stuff!";
    private static final boolean END_OF_INPUT = true;

    private ByteBuffer bytes = ByteBuffer.allocate(1000);

    public TestBuffer() {

        System.out.println("init   : " + bytes.toString());
    }

    public static void main(String a[]) {
        TestBuffer buf = new TestBuffer();
        buf.writeBuffer();
        buf.readBuffer();
    }

    // write testStr to buffer
    private void writeBuffer() {
        CharBuffer testBuffer = CharBuffer.wrap(testStr);
        CharsetEncoder utf8Encoder = StandardCharsets.UTF_8.newEncoder();
        CoderResult result = utf8Encoder.encode(testBuffer, bytes, END_OF_INPUT);
        if (result.isError()) {
            bytes.clear();
            throw new IllegalArgumentException("That didn't go right because " + result.toString());
        }
        if (result.isOverflow()) {
            bytes.clear();
            throw new IllegalArgumentException("Well, too little buffer space.");
        }
        System.out.println("written: " + bytes.toString());
        bytes.flip();
    }

    // read buffer data back to byte array and print
    private void readBuffer() {
        byte[] b = new byte[bytes.remaining()];
        bytes.get(b);
        System.out.println("data   : " + new String(b, StandardCharsets.UTF_8));
        System.out.println("read   : " + bytes.toString());
        bytes.clear();
    }
}
请注意,缓冲区和流实际上是处理顺序数据的两种不同方式。如果你想同时使用这两种方法,你可能太聪明了

您也可以在不使用
CharBuffer
ByteBuffer
的情况下,使用
byte[]
缓冲区和由



Android的那段代码完全滥用了ByteBuffer的
。它应该只创建一个
字节[]
并包装它,设置容量限制。无论您做什么,都不要将其作为处理
ByteBuffer
的示例。它使我厌恶地流泪。像这样的代码是一个等待发生的错误。

虽然这个问题很久以前就已经得到了回答,但让我补充一些信息。在这里

writeBuffer()
readBuffer()
方法分别存在两个问题,导致您无法获得预期的结果

1)
writeBuffer()
method
正如上面Maarten Bodewes就bytebuffer数组的性质所解释的那样,您不能直接使用
bytebuffer.array()
来读取数据库中的流

或者,如果希望继续测试InputStream和ByteBuffer之间的关系作为示例(这也是服务器端应用程序处理传入消息的常见做法),则需要额外的字节数组

2)
readBuffer()
方法 原始代码很适合使用额外的字节数组来检索bytebuffer中的上下文以进行打印

然而,这里的问题是
flip()
position()
方法使用不当

  • 只有在您想将bytebuffer的状态
    存储上下文
    更改为
    导出上下文
    之前,才应该调用
    flip()
    方法。所以这里的这个方法应该出现在
    bytes.get(b)行的前面取而代之。在提供的示例中,在行
    byte[]b=newbyte[bytes.position()]之前调用此方法为时尚早
    ,因为
    flip()
    方法将更改字节的位置标志
    import java.io.BufferedInputStream;
    import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.nio.ByteBuffer;
    
    public class TestBuffer {
    
        private ByteBuffer bytes;
        private String testStr = "Stackoverflow is a great place to discuss tech stuff!";
    
        public TestBuffer() {
            bytes = ByteBuffer.allocate(1000);
            System.out.println("init: " + printBuffer());
        }
    
        public static void main(String a[]) {
            TestBuffer buf = new TestBuffer();
            try {
                buf.writeBuffer();
            } catch (IOException e) {
                e.printStackTrace();
            }
            buf.readBuffer();
        }
    
        // write testStr to buffer
        private void writeBuffer() throws IOException {
            byte[] b = testStr.getBytes();
            BufferedInputStream in = new BufferedInputStream(new ByteArrayInputStream(b));
            // in.read(bytes.array());
            byte[] dst = new byte[b.length];
            in.read(dst);
            bytes.put(dst);
            in.close();
            System.out.println("write: " + printBuffer());
        }
    
        // read buffer data back to byte array and print
        private void readBuffer() {
            //bytes.flip();
            byte[] b = new byte[bytes.position()];
            //bytes.position(0);
            int pos = bytes.position();
            bytes.flip();   // bytes.rewind(); could achieve the same result here, use which one depends on whether:
                            // (1) reading to this bytebuffer is finished and fine to overwrite the current context in this bytebuffer afterwards: can use flip(); or 
                            // (2) just want to tentatively traverse this bytebuffer from the begining to current position, 
                            //      and keep writing to this bytebuffer again later from current position.      
            bytes.get(b);
            bytes.position(pos);
            System.out.println("data read: " + new String(b));
            System.out.println("read: " + printBuffer());
        }
    
        public String printBuffer() {
            return "ByteBuffer [limit=" + bytes.limit() + ", capacity=" + bytes.capacity() + ", position="
                    + bytes.position() + ", remaining=" + bytes.remaining() + "]";
        }
    
    }