Массив байтов неизвестной длины в java
Вопрос
Я создаю массив байтов на Java, и я не знаю, какой длины будет этот массив.
Мне нужен какой-нибудь инструмент вроде Java StringBuffer, который вы можете просто вызвать .append(байт b) или .append(байт[] buf) и заставить его буферизировать все мои байты и вернуть мне массив байтов, когда я закончу.Есть ли класс, который делает для байтов то, что StringBuffer делает для строк?Не похоже, что класс ByteBuffer - это то, что я ищу.
У кого-нибудь есть хорошее решение?
Решение
Попробуй ByteArrayOutputStream
.Вы можете использовать write( byte[] )
и она будет расти по мере необходимости.
Другие советы
Просто чтобы расширить предыдущий ответ, вы можете использовать Поток вывода ByteArrayOutputStream и это метод public void write(byte[] b, int off, int len)
, где параметры являются:
b - данные
выкл . - начальное смещение в данных
len - количество байт для записи
Если вы хотите использовать его как "конструктор байтов" и вставлять байт за байтом, вы можете использовать это:
byte byteToInsert = 100;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(new byte[]{byteToInsert}, 0, 1);
Тогда вы можете использовать baos.toString()
способ преобразования массива в строку.Преимущество заключается в том, что когда вам нужно настроить кодировку входных данных, вы можете просто использовать, т.е.:
baos.toString("Windows-1250")
Я написал тот, который действительно прост в использовании и позволяет избежать большого количества копирования буфера байтового массива.
У него есть один метод, называемый add .
Вы можете добавить к нему строки, байты, byte, long, int, double, float, short и символы.
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"));
Мне никогда не нужно устанавливать размер массива.Он будет автоматически расти по мере необходимости эффективным способом.
Если я точно знаю, насколько большими будут мои данные, я могу сэкономить на некоторой проверке границ, используя Создать действие.
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");
Это работает с 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, он предоставляет вам свой буфер.Вот мое внутреннее состояние, вы можете использовать его, но я собираюсь присвоить ему значение null, чтобы никто другой им не пользовался.
Все в порядке.Просто создайте другой, если вы уверены, что буфер используется только одним экземпляром одновременно (byte []).
Вы даже можете использовать буфер, который вы только что использовали, как в
ByteBuf buf2 = new ByteBuf.create(bytes);
Это происходит потому, что ни один буфер не копируется.ByteBuf записывает данные в буфер, который вы ему предоставляете.Если вы хотите, чтобы другая копия была передана в ByteBuf, сделайте это:
ByteBuf buf2 = new ByteBuf.create( copy(bytes) );
В конце концов, это благо.:)
Приходи посмотреть на буна.Вы получаете вышеупомянутый класс и idx, а также idxInt и idxLong бесплатно!
Давайте посмотрим.В 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'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 (байт[])
Я написал свою собственную маленькую библиотеку для манипулирования байтовыми массивами.:)
Вы можете добавить их следующим образом
byte [] a = ...
byte [] b = ...
byte [] c = ...
a = add(a, b);
a = add(a, c);
это дало бы вам все содержимое b и c после содержимого для a.
Если бы вы хотели увеличить a на 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)
);
Нарезать:
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(
'\0',
idx(letters, 20)
);
Сжиматься:
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 (учитывая небезопасность, но пока нет).
Добавление одного массива в другой:
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;
}
Еще....