java中长度未知的字节数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/664389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 17:36:58  来源:igfitidea点击:

Byte array of unknown length in java

javabufferbyte

提问by jbu

I am constructing an array of bytes in java and I don't know how long the array will be.

我正在用 java 构造一个字节数组,我不知道该数组有多长。

I want some tool like Java's StringBuffer that you can just call .append(byte b) or .append(byte[] buf) and have it buffer all my bytes and return to me a byte array when I'm done. Is there a class that does for bytes what StringBuffer does for Strings? It does not look like the ByteBuffer class is what I'm looking for.

我想要一些像 Java 的 StringBuffer 这样的工具,你可以调用 .append(byte b) 或 .append(byte[] buf) 并让它缓冲我所有的字节并在我完成后返回给我一个字节数组。是否有一个类可以像 StringBuffer 对字符串那样处理字节?它看起来不像 ByteBuffer 类是我正在寻找的。

Anyone have a good solution?

有人有好的解决方案吗?

采纳答案by Clint

Try ByteArrayOutputStream. You can use write( byte[] )and it will grow as needed.

试试ByteArrayOutputStream。您可以使用write( byte[] ),它会根据需要增长。

回答by Micer

Just to extend the previous answer, you can use ByteArrayOutputStreamand it's method public void write(byte[] b, int off, int len), where parameters are:

只是为了扩展上一个答案,您可以使用ByteArrayOutputStream及其方法public void write(byte[] b, int off, int len),其中参数是:

b - the data

off - the start offset in the data

len - the number of bytes to write

b - 数据

off - 数据中的起始偏移量

len - 要写入的字节数

If you want to use it as a "byte builder" and insert byte by byte, you can use this:

如果要将其用作“字节构建器”并逐字节插入,则可以使用以下命令:

byte byteToInsert = 100;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(new byte[]{byteToInsert}, 0, 1);

Then you can use baos.toString()method to convert the array to string. The advantage is when you need to set up encoding of input, you can simply use i.e.:

然后您可以使用baos.toString()方法将数组转换为字符串。优点是当您需要设置输入编码时,您可以简单地使用 ie:

baos.toString("Windows-1250")

回答by RickHigh

Let's see. There is the ByteBuffer class in Java.

让我们来看看。Java 中有 ByteBuffer 类。

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html

It has bulk methods that transfer contiguous sequences of bytes from a byte array to hardware buffers. It would do the trick.

它具有将连续字节序列从字节数组传输到硬件缓冲区的批量方法。它会成功。

It also has absolute and relative get and put methods that read and write byte[]s and other primitives to / for the byte buffer.

它还具有绝对和相对 get 和 put 方法,可以为字节缓冲区读取和写入 byte[] 和其他原语到 / 。

It also has methods for compacting, duplicating, and slicing a byte buffer.

它还具有压缩、复制和切片字节缓冲区的方法。

// Creates an empty ByteBuffer with a 1024 byte capacity
ByteBuffer buf = ByteBuffer.allocate(1024);

// Get the buffer's capacity
int capacity = buf.capacity(); // 10

buf.put((byte)0xAA); // position=0

// Set the position
buf.position(500);

buf.put((byte)0xFF);

// Read the position 501
int pos = buf.position(); 

// Get remaining byte count
int remaining = buf.remaining(); (capacity - position)

It also has a bulk put to put an array, which is pretty close to the append you were asking for:

它还有一个用于放置数组的批量放置,这与您要求的附加非常接近:

public final ByteBuffer put(byte[] src)

See: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#put(byte[])

请参阅:http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#put(byte[])

I wrote my own little lib for manipulating byte arrays. :)

我编写了自己的小库来操作字节数组。:)

You can add them like so

你可以像这样添加它们

byte [] a = ...
byte [] b = ...
byte [] c = ...

a = add(a, b);
a = add(a, c);

this would give you all of the contents of b, and c after the contents for a.

这将在 a 的内容之后为您提供 b 的所有内容和 c。

If you wanted to grow a by 21, you could do the following:

如果您想将 a 增加 21,您可以执行以下操作:

a = grow( letters,  21);

If you wanted to double the size of a, you could do the following:

如果您想将 a 的大小加倍,您可以执行以下操作:

a = grow( letters,  21);

See...

看...

https://github.com/RichardHightower/boon/blob/master/src/main/java/org/boon/core/primitive/Byt.java

https://github.com/RichardHightower/boon/blob/master/src/main/java/org/boon/core/primitive/Byt.java

    byte[] letters =
            arrayOfByte(500);

    assertEquals(
            500,
            len(letters)
    );

Create

创建

    byte[] letters =
            array((byte)0, (byte)1, (byte)2, (byte)3);

    assertEquals(
            4,
            len(letters)
    );

Index

指数

    byte[] letters =
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d');

    assertEquals(
            'a',
            idx(letters, 0)
    );


    assertEquals(
            'd',
            idx(letters, -1)
    );


    assertEquals(
            'd',
            idx(letters, letters.length - 1)
    );


    idx(letters, 1, (byte)'z');

    assertEquals(
            (byte)'z',
            idx(letters, 1)
    );

Contains

包含

    byte[] letters =
            array((byte)'a',(byte) 'b', (byte)'c', (byte)'d');


    assertTrue(
            in((byte)'a', letters)
    );

    assertFalse(
            in((byte)'z', letters)
    );

Slice:

片:

    byte[] letters =
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d');


    assertArrayEquals(
            array((byte)'a', (byte)'b'),
            slc(letters, 0, 2)
    );

    assertArrayEquals(
            array((byte)'b', (byte)'c'),
            slc(letters, 1, -1)
    );

    //>>> letters[2:]
    //['c', 'd']
    //>>> letters[-2:]
    //['c', 'd']

    assertArrayEquals(
            array((byte)'c', (byte)'d'),
            slc(letters, -2)
    );


    assertArrayEquals(
            array((byte)'c', (byte)'d'),
            slc(letters, 2)
    );


    //>>> letters[:-2]
    //     ['a', 'b']
    assertArrayEquals(
            array((byte)'a', (byte)'b'),
            slcEnd(letters, -2)
    );


    //>>> letters[:-2]
    //     ['a', 'b']
    assertArrayEquals(
            array((byte)'a',(byte) 'b'),
            slcEnd(letters, 2)
    );

Grow

生长

    byte[] letters =
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e');

    letters = grow( letters,  21);


    assertEquals(
            'e',
            idx(letters, 4)
    );


    assertEquals(
            'a',
            idx(letters, 0)
    );




    assertEquals(
            len(letters),
            26
    );


    assertEquals(
            '
    letters =  shrink ( letters, 23 );

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c'),
            letters

    );
', idx(letters, 20) );

Shrink:

收缩:

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'),
            copy(array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'))

    );

Copy:

复制:

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'),
            add(array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'), (byte)'f') );

Add:

添加:

    assertArrayEquals(
            array(     (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'),
            add( array((byte)'a', (byte)'b', (byte)'c', (byte)'d'), array((byte)'e', (byte)'f') )

    );

The add actually adds them together by using System.arraycopy (considering Unsafe, but not yet).

添加实际上是通过使用 System.arraycopy 将它们添加在一起(考虑到不安全,但还没有)。

Add one array to another:

将一个数组添加到另一个数组:

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'),
            insert( array((byte)'a', (byte)'b', (byte)'d', (byte)'e', (byte)'f', (byte)'g'), 2, (byte)'c' )

    );

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'),
            insert( array((byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'), 0, (byte)'a' )

    );

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'),
            insert( array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'g'), 5, (byte)'f' )

    );

Insert:

插入:

public static byte[] grow(byte [] array, final int size) {
    Objects.requireNonNull(array);

    byte [] newArray  = new byte[array.length + size];
    System.arraycopy(array, 0, newArray, 0, array.length);
    return newArray;
}



public static byte[] grow(byte [] array) {
    Objects.requireNonNull(array);

    byte [] newArray  = new byte[array.length *2];
    System.arraycopy(array, 0, newArray, 0, array.length);
    return newArray;
}


public static byte[] shrink(byte[] array, int size) {
    Objects.requireNonNull(array);

    byte[] newArray = new byte[array.length - size];

    System.arraycopy(array, 0, newArray, 0, array.length-size);
    return newArray;
}




public static byte[] copy(byte[] array) {
    Objects.requireNonNull(array);
    byte[] newArray = new byte[array.length];
    System.arraycopy(array, 0, newArray, 0, array.length);
    return newArray;
}


public static byte[] add(byte[] array, byte v) {
    Objects.requireNonNull(array);
    byte[] newArray = new byte[array.length + 1];
    System.arraycopy(array, 0, newArray, 0, array.length);
    newArray[array.length] = v;
    return newArray;
}

public static byte[] add(byte[] array, byte[] array2) {
    Objects.requireNonNull(array);
    byte[] newArray = new byte[array.length + array2.length];
    System.arraycopy(array, 0, newArray, 0, array.length);
    System.arraycopy(array2, 0, newArray, array.length, array2.length);
    return newArray;
}



public static byte[] insert(final byte[] array, final int idx, final byte v) {
    Objects.requireNonNull(array);

    if (idx >= array.length) {
        return add(array, v);
    }

    final int index = calculateIndex(array, idx);

    //Object newArray = Array.newInstance(array.getClass().getComponentType(), array.length+1);
    byte [] newArray = new byte[array.length+1];

    if (index != 0) {
        /* Copy up to the location in the array before the index. */
        /*                 src     sbegin  dst       dbegin   length of copy */
        System.arraycopy( array,   0,      newArray, 0,       index );
    }


    boolean lastIndex = index == array.length -1;
    int remainingIndex = array.length - index;

    if (lastIndex ) {
        /* Copy the area after the insert. Make sure we don't write over the end. */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + 1, remainingIndex );

    } else {
        /* Copy the area after the insert.  */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + 1, remainingIndex );

    }

    newArray[index] = v;
    return  newArray;
}


public static byte[] insert(final byte[] array, final int fromIndex, final byte[] values) {
    Objects.requireNonNull(array);

    if (fromIndex >= array.length) {
        return add(array, values);
    }

    final int index = calculateIndex(array, fromIndex);

    //Object newArray = Array.newInstance(array.getClass().getComponentType(), array.length+1);
    byte [] newArray = new byte[array.length +  values.length];

    if (index != 0) {
        /* Copy up to the location in the array before the index. */
        /*                 src     sbegin  dst       dbegin   length of copy */
        System.arraycopy( array,   0,      newArray, 0,       index );
    }


    boolean lastIndex = index == array.length -1;

    int toIndex = index + values.length;
    int remainingIndex = newArray.length - toIndex;

    if (lastIndex ) {
        /* Copy the area after the insert. Make sure we don't write over the end. */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + values.length, remainingIndex );

    } else {
        /* Copy the area after the insert.  */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + values.length, remainingIndex );

    }

    for (int i = index, j=0; i < toIndex; i++, j++) {
        newArray[ i ] = values[ j ];
    }
    return  newArray;
}

Here is a peek at a few of the methods:

以下是其中一些方法的概览:

    ByteBuf buf = new ByteBuf();
    buf.add(bytes("0123456789\n"));
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456END\n");

More....

更多的....

回答by RickHigh

I wrote one that is really easy to use and avoids a lot of byte array buffer copying.

我写了一个真的很容易使用并且避免了大量的字节数组缓冲区复制。

It has one method called add.

它有一种方法叫做 add。

You can add strings, bytes, byte, long, int, double, float, short, and chars to it.

您可以向其中添加字符串、字节、字节、长整型、整数、双精度、浮点数、短整型和字符。

The API is easy to use and somewhat fail safe. It does not allow you to copy the buffer around and does not promote having two readers.

该 API 易于使用且具有一定的故障安全性。它不允许您复制缓冲区,也不提倡拥有两个读者。

It has a bounds check mode and a I KNOW WHAT I AM DOING MODE with no bounds checking.

它有一个边界检查模式和一个我知道我在做什么模式,没有边界检查。

The bounds check mode auto-grows it so there is no hassle.

边界检查模式会自动增长它,所以没有麻烦。

https://github.com/RichardHightower/boon/wiki/Auto-Growable-Byte-Buffer-like-a-ByteBuilder

https://github.com/RichardHightower/boon/wiki/Auto-Growable-Byte-Buffer-like-a-ByteBuilder

Here is a complete step by step guide on how to use it. It is on github.

这是有关如何使用它的完整分步指南。它在github上。

Java Boon - Auto Growable Byte Buffer like a ByteBuilder

Java Boon - 像 ByteBuilder 一样自动增长的字节缓冲区

Have you ever wanted an easy to use buffer array that grow automatically and/or you can give it a fix size and just add stuff to it? I have. I wrote one too.

您是否曾经想要一个易于使用的自动增长的缓冲区数组和/或您可以给它一个固定大小并只添加内容?我有。我也写了一篇。

Look.. I can write strings to it (it converts them to UTF-8).

看..我可以向它写入字符串(它将它们转换为 UTF-8)。

    String out = new String(buf.readAndReset(), 0, buf.len());
    assertEquals(66, buf.len());
    assertTrue(out.endsWith("END\n"));

Then later I can read the String out of the buffer:

然后我可以从缓冲区中读取字符串:

    ByteBuf buf = ByteBuf.createExact(66);
    buf.add(bytes("0123456789\n"));
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456END\n");
    assertEquals(66, buf.len());

I never have to set the size of the array. It will auto-grow as needed in an efficient manner.

我永远不必设置数组的大小。它将根据需要以有效的方式自动增长。

If I know exactly how large my data is going to be than I can save some bounds checking by using createExact.

如果我确切地知道我的数据有多大,那么我可以使用createExact保存一些边界检查。

    ByteBuf buf = ByteBuf.createExact(22);
    buf.add(bytes("0123456789\n"));
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456END\n");

If I use create exact, then I am saying... hey.. I know exactly how big it can grow to and it will never go over this number and if it does...you can hit me over the head with a sack of rocks!

如果我使用创建精确,那么我会说......嘿......我确切地知道它可以增长到多大并且它永远不会超过这个数字,如果它确实......你可以用麻袋打我的头岩石!

The following hits you over the head with a sack of rocks! THROWS AN EXCEPTION!!!!

以下是一袋石头击中你的头!抛出异常!!!!

    ByteBuf buf = ByteBuf.createExact(8);

    //add the double
    buf.add(10.0000000000001);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    worked |= idxDouble(bytes, 0) == 10.0000000000001 || die("Double worked");

It works with doubles.

它适用于双打。

    ByteBuf buf = ByteBuf.createExact(8);

    //add the float
    buf.add(10.001f);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    worked |= buf.len() == 4 || die("Float worked");


    //read the float
    float flt = idxFloat(bytes, 0);

    worked |= flt == 10.001f || die("Float worked");

It works with float.

它适用于浮动。

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the int to the array
    buf.add(99);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;


    //Read the int back
    int value = idxInt(bytes, 0);

    worked |= buf.len() == 4 || die("Int worked length = 4");
    worked |= value == 99 || die("Int worked value was 99");

It works with int.

它与 int 一起使用。

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the char to the array
    buf.add('c');

    byte[] bytes = buf.readAndReset();
    boolean worked = true;


    //Read the char back
    int value = idxChar(bytes, 0);

    worked |= buf.len() == 2 || die("char worked length = 4");
    worked |= value == 'c' || die("char worked value was 'c'");

It works with char.

它适用于字符。

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the short to the array
    buf.add((short)77);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;


    //Read the short back
    int value = idxShort(bytes, 0);

    worked |= buf.len() == 2 || die("short worked length = 2");
    worked |= value == 77 || die("short worked value was 77");

It works with short.

它适用于短。

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the byte to the array
    buf.add( (byte)33 );

    byte[] bytes = buf.readAndReset();
    boolean worked = true;


    //Read the byte back
    int value = idx(bytes, 0);

    worked |= buf.len() == 1 || die("byte worked length = 1");
    worked |= value == 33 || die("byte worked value was 33");

It even works with bytes.

它甚至适用于字节。

    boolean worked = true;
    ByteBuf buf = ByteBuf.create(1);

    //Add the various to the array
    buf.add( (byte)  1 );
    buf.add( (short) 2 );
    buf.add( (char)  3 );
    buf.add(         4 );
    buf.add( (float) 5 );
    buf.add( (long)  6 );
    buf.add( (double)7 );

    worked |= buf.len() == 29 || die("length = 29");


    byte[] bytes = buf.readAndReset();

    byte myByte;
    short myShort;
    char myChar;
    int myInt;
    float myFloat;
    long myLong;
    double myDouble;

You can add all sorts of primitives to your byte array.

您可以将各种原语添加到您的字节数组中。

    myByte    =   idx       ( bytes, 0 );
    myShort   =   idxShort  ( bytes, 1 );
    myChar    =   idxChar   ( bytes, 3 );
    myInt     =   idxInt    ( bytes, 5 );
    myFloat   =   idxFloat  ( bytes, 9 );
    myLong   =    idxLong   ( bytes, 13 );
    myDouble  =   idxDouble ( bytes, 21 );

    worked |= myByte   == 1 || die("value was 1");
    worked |= myShort  == 2 || die("value was 2");
    worked |= myChar   == 3 || die("value was 3");
    worked |= myInt    == 4 || die("value was 4");
    worked |= myFloat  == 5 || die("value was 5");
    worked |= myLong   == 6 || die("value was 6");
    worked |= myDouble == 7 || die("value was 7");

Now we just verify that we can read everything back.

现在我们只需验证我们可以读回所有内容。

 byte[] bytes = buf.readAndReset() 

Once you call

一旦你打电话

ByteBuf buf2 = new ByteBuf.create(bytes); 

then you are saying that you are done with the ByteBuffer!

那么你是说你已经完成了 ByteBuffer!

Once you ask for the bytes, it becomes useless as it sets the internal byte array to nothing.

一旦您要求字节,它就变得无用,因为它将内部字节数组设置为空。

When you call readAndReset, it is giving you its buffer. Here is my internal state, you can have it, but I am going to set it to null so nobody else uses it.

当您调用 readAndReset 时,它会为您提供缓冲区。这是我的内部状态,你可以拥有它,但我要将它设置为 null 以便其他人使用它。

It is ok. Just create another if you are sure only one instance at a time is using the buffer (byte []).

没关系。如果您确定一次只有一个实例正在使用缓冲区(字节 []),则只需创建另一个实例。

You can even use the buffer you were just using as in

您甚至可以使用刚才使用的缓冲区

ByteBuf buf2 = new ByteBuf.create( copy(bytes) ); 

This is because no buffer gets copied. ByteBuf writes to the buffer you give it. If you want another copy to be given to ByteBuf then do this:

这是因为没有缓冲区被复制。ByteBuf 写入您提供的缓冲区。如果您希望将另一个副本提供给 ByteBuf,请执行以下操作:

##代码##

This is boon after all. :)

这毕竟是福音。:)

Come check out boon. You get the above class and idx, and idxInt and idxLong for free!

来看看恩惠。您可以免费获得上述类和 idx,以及 idxInt 和 idxLong!

https://github.com/RichardHightower/boon/

https://github.com/RichardHightower/boon/