Массив байтов неизвестной длины в java

Я создаю массив байтов в java, и я не знаю, как долго будет массив.

Мне нужен какой-то инструмент, такой как Java StringBuffer, который вы можете просто вызвать .append(byte b) или .append(byte [] buf), и он должен буферизировать все мои байты и вернуть мне массив байтов, когда закончите. Есть ли класс, который делает для байтов, что StringBuffer делает для строк? Это не похоже, что класс ByteBuffer - это то, что я ищу.

У кого-нибудь есть хорошее решение?

Ответы

Ответ 1

Попробуйте ByteArrayOutputStream. Вы можете использовать write( byte[] ), и он будет расти по мере необходимости.

Ответ 2

Чтобы продлить предыдущий ответ, вы можете использовать ByteArrayOutputStream и его метод public void write(byte[] b, int off, int len), где параметры:

b - данные

off - смещение начала в данных

len - количество байтов для записи

Если вы хотите использовать его как "построитель байтов" и вставить байтовый байт, вы можете использовать это:

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

Затем вы можете использовать метод baos.toString() для преобразования массива в строку. Преимущество заключается в том, когда вам нужно настроить кодировку ввода, вы можете просто использовать i.e.:

baos.toString("Windows-1250")

Ответ 3

Я написал один, который очень прост в использовании и позволяет избежать большого количества копий буфера массива.

Он имеет один метод, называемый add.

Вы можете добавить в него строки, байты, байты, длинные, int, double, float, short и chars.

API прост в использовании и несколько отказоустойчив. Это не позволяет вам копировать буфер вокруг и не способствует наличию двух считывателей.

У этого есть режим проверки границ, и я ЗНАЮ, ЧТО Я ЕСМЬ РЕЖИМ РАБОТЫ без проверки границ.

Режим проверки границ автоматически вырабатывает его, поэтому нет никаких проблем.

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

Ниже приведено полное пошаговое руководство по его использованию. Он находится на github.

Java Boon - автоматический растущий байт-буфер, как ByteBuilder

Вам когда-нибудь нужен простой в использовании буферный массив, который растет автоматически и/или вы можете дать ему размер исправления и просто добавить к нему материал? У меня есть. Я тоже написал.

Посмотрите.. Я могу написать строки к нему (он преобразует их в UTF-8).

    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");

Затем я могу прочитать строку из буфера:

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

Мне никогда не нужно устанавливать размер массива. Он будет автоматически расти по мере необходимости эффективным способом.

Если я точно знаю, насколько велики мои данные, я могу сэкономить некоторые проверки границ, используя createExact.

    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());

Если я использую создание точного, то я говорю... эй.. Я точно знаю, насколько большой он может вырасти, и он никогда не перейдет это число, и если это произойдет... ты можешь ударить меня по голове с мешком горных пород!

Следующие хиты над головой с мешком камней! ПРОТИВ ИСКЛЮЧЕНИЯ!!!!

    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");

Он работает с удвоениями.

    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");

Он работает с float.

    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");

Он работает с int.

    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");

Работает с char.

    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'");

Он работает с коротким.

    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");

Он работает даже с байтами.

    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");

Вы можете добавить всевозможные примитивы в ваш массив байтов.

    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;

Теперь мы просто проверим, что мы все можем прочитать.

    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");

Как только вы вызываете

 byte[] bytes = buf.readAndReset() 

тогда вы говорите, что вы закончили с ByteBuffer!

Как только вы запрашиваете байты, он становится бесполезным, так как он не устанавливает внутренний массив байтов.

Когда вы вызываете readAndReset, он предоставляет вам свой буфер. Вот мое внутреннее состояние, вы можете иметь его, но я собираюсь установить его равным нулю, чтобы никто его не использовал.

Это нормально. Просто создайте другой, если вы уверены, что только один экземпляр за раз использует буфер (byte []).

Вы даже можете использовать буфер, который вы использовали, как в

ByteBuf buf2 = new ByteBuf.create(bytes); 

Это происходит потому, что буфер не копируется. ByteBuf пишет буфер, который вы ему даете. Если вы хотите, чтобы другая копия была передана ByteBuf, сделайте следующее:

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

В конце концов, это благо.:)

Приходите проверить благо. Вы получаете вышеуказанные классы и idx, idxInt и idxLong бесплатно!

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

Ответ 4

Посмотрим. В Java есть класс ByteBuffer.

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

Он имеет массовые методы, которые передают непрерывные последовательности байтов из массива байтов в аппаратные буферы. Это сделало бы трюк.

Он также имеет абсолютные и относительные методы get и put, которые читают и записывают byte [] s и другие примитивы в/для байтового буфера.

Он также имеет методы для уплотнения, дублирования и нарезки байтового буфера.

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

// Get the buffer 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)

У него также есть массив, который помещает массив, который довольно близок к добавлению, которое вы запрашивали:

public final ByteBuffer put(byte[] src)

См: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#put (байт [])

Я написал свою собственную небольшую библиотеку для манипулирования байтовыми массивами.:)

Вы можете добавить их так:

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

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

это даст вам все содержимое b и c после содержимого для.

Если вы хотите увеличить на 21, вы можете сделать следующее:

a = grow( letters,  21);

Если вы хотите удвоить размер a, вы можете сделать следующее:

a = grow( letters,  21);

См...

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

    byte[] letters =
            arrayOfByte(500);

    assertEquals(
            500,
            len(letters)
    );

Создать

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

    assertEquals(
            4,
            len(letters)
    );

Индекс

    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)
    );

Содержит

    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(
            '\0',
            idx(letters, 20)
    );

Shrink:

    letters =  shrink ( letters, 23 );

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

    );

Копия:

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

    );

Добавить

    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') );

Добавление фактически добавляет их вместе, используя System.arraycopy(считая Unsafe, но еще не).

Добавьте один массив в другой:

    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') )

    );

Вставка:

    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' )

    );

Ниже приведено несколько способов:

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;
}

Подробнее....