Подтвердить что ты не робот

Рост ByteBuffer

Кто-нибудь видел реализацию java.nio.ByteBuffer, которая будет динамически расти, если вызов putX() переполняет емкость?

Причина, по которой я хочу это сделать, двояка:

  • Я не знаю, сколько места мне нужно заблаговременно.
  • Я бы предпочел не делать новый ByteBuffer.allocate(), а затем массив put() при каждом пробеге.
4b9b3361

Ответ 1

Для работы асинхронного ввода-вывода у вас должна быть непрерывная память. В C вы можете попытаться перераспределить массив, но в Java вы должны выделить новую память. Вы можете написать ByteArrayOutputStream, а затем преобразовать его в ByteBuffer в момент, когда вы будете готовы отправить его. Недостатком является то, что вы копируете память, и один из ключей к эффективному IO уменьшает количество копий памяти.

Ответ 2

ByteBuffer не может работать таким образом, поскольку его концепция дизайна должна быть просто представлением определенного массива, к которому вы также можете обратиться напрямую. Он не мог попытаться поменять этот массив для большего массива без каких-либо странностей.

То, что вы хотите использовать, - DataOutput. Самый удобный способ - использовать (до выпуска) библиотеку Guava:

ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.write(someBytes);
out.writeInt(someInt);
// ...
return out.toByteArray();

Но вы также можете создать DataOutputStream из ByteArrayOutputStream вручную и просто иметь дело с ложными IOExceptions, связав их с AssertionErrors.

Ответ 3

Посмотрите на Mina IOBuffer https://mina.apache.org/mina-project/userguide/ch8-iobuffer/ch8-iobuffer.html, который является заменой (он обертывает ByteBuffer)

Однако я предлагаю вам выделить больше, чем вам нужно, и не беспокойтесь об этом слишком много. Если вы выделяете буфер (esp прямой буфер), OS дает ему виртуальную память, но при использовании фактически использует только физическую память. Виртуальная память должна быть очень дешевой.

Ответ 4

Возможно, стоит взглянуть на Netty DynamicChannelBuffer. Вещи, которые мне удобны:

  • slice(int index, int length)
  • неподписанные операции
  • разделенные индексы писателя и читателя

Ответ 5

Другой вариант - использовать прямую память с большим буфером. Это потребляет виртуальную память, но использует только столько физической памяти, сколько вы используете (на странице, которая обычно равна 4K)

Итак, если вы выделяете буфер объемом 1 Мбайт, он составляет 1 МБ виртуальной памяти, но единственная ОС предоставляет физические страницы для приложения, которое на самом деле использует.

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

Ответ 6

Вектор допускает непрерывный рост

Vector<Byte> bFOO = new Vector<Byte>(); bFOO.add((байт) 0x00); `

Ответ 7

Чтобы сериализовать что-то, вам понадобится объект в записи. Что вы можете сделать, это поместить ваш объект в коллекцию объектов, а после этого сделать цикл для получения итератора и поместить их в массив байтов. Затем вызовите ByteBuffer.allocate(byte[].length). Это то, что я сделал, и это сработало для меня.