Байтовый массив неизвестной длины в java
Я строю массив байтов в java, и я не знаю, как долго массив будет.
Я хочу какой-то инструмент, как Java StringBuffer, который вы можете просто позвонить .добавить(байт, Б) или .добавьте (byte[] buf) и пусть он буферизует все мои байты и вернет мне массив байтов, когда я закончу. Есть ли класс, который делает для байтов то, что StringBuffer делает для строк? Не похоже, что класс ByteBuffer - это то, что я ищу.
У кого-нибудь есть хорошее решение?
4 ответа:
попробовать
ByteArrayOutputStream
. Вы можете использоватьwrite( byte[] )
и он будет расти по мере необходимости.
просто продлить предыдущий ответ, вы можете использовать ByteArrayOutputStream и это способ
public void write(byte[] b, int off, int len)
, где параметрами являются:б - данные
off-начальное смещение в данных
len-количество байтов для записи
если вы хотите использовать его в качестве "построителя байтов" и вставлять байт за байтом, вы можете использовать это:
byte byteToInsert = 100; ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos.write(new byte[]{byteToInsert}, 0, 1);
затем вы можете использовать
baos.toString()
метод преобразования массива в строка. Преимущество, когда вам нужно настроить кодировку ввода, вы можете просто использовать например:baos.toString("Windows-1250")
я написал один, который очень прост в использовании и позволяет избежать большого количества копирования буфера массива байтов.
он имеет один метод, называемый add.
вы можете добавить к нему строки, байты, байты, длинные, int, двойные, плавающие, короткие и символы.
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());
если я использую create exact, то я говорю... эй.. Я точно знаю, насколько большой он может вырасти, и он никогда не будет превышать это число, и если это произойдет...ты можешь ударить меня по голове мешком камней!
следующее бьет вас по голове мешком камней! БРОСАЕТ ИСКЛЮЧЕНИЕ!!!!
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");
он работает с плыть.
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, он дает вам свой буфер. Вот мое внутреннее состояние, вы можете иметь его, но я собираюсь установить его в null, чтобы никто больше не использовал его.
это нормально. Просто создайте другой, если вы уверены, что только один экземпляр одновременно использует буфер (байт.)][
вы даже можете использовать буфер, который вы только что использовали, как в
ByteBuf buf2 = new ByteBuf.create(bytes);
это потому, что буфер не копируется. ByteBuf пишет в буфер, который вы ему даете. Если вы хотите, чтобы другая копия была предоставлена ByteBuf, то сделайте это:
ByteBuf buf2 = new ByteBuf.create( copy(bytes) );
это все-таки благо. :)
проверить благом. Вы получаете выше класс и idx, и idxInt и idxLong для бесплатно!
давайте посмотрим. Существует класс ByteBuffer в Java.
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'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)
он также имеет массовый положить положить массив, который довольно близко к приложению вы просили:
public final ByteBuffer put(byte[] src)
посмотреть: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#put(байт[])
я написал свой собственный маленький lib для управления массивами байтов. :)
вы можете добавить их так
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) );
растут
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( '', 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') );
в добавить на самом деле добавляет их вместе с помощью системы.arraycopy (считая небезопасным, но пока нет).
добавить один массив в другой:
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; }
больше....