Как инициализировать ByteBuffer, если Вы не знаете сколько байтов выделять заранее?

Некоторые мысли:

  • дебаты между FP и императивным программированием (OO, структурированное, и т.д.), бушевал начиная с Lisp по сравнению с Фортраном. Я думаю, что Вы ставите превосходные вопросы, но распознаете, что они не являются особенно новыми.
  • Часть шумихи вокруг FP - то, что мы, кажется, распознаем, что параллелизм является очень трудным, и что блокировки и другие механизмы в OO (например, Java) являются всего одним решением. FP предлагает обновляющие кардинальные изменения с идеями, такими как Агенты и питание вычисления не сохраняющего состояние. Тем, которые борются с OO, среда кажется очень привлекательной.
  • Да, школы преподают FP. На самом деле Университет Уотерлу и другие предлагают Схему в первых классах года ( ссылка здесь ).
  • Относительно среднего программиста, я уверен, что те же аргументы были даны против C++ назад в начале 1990-х. И посмотрите, что произошло. , Если компании могут получить преимущество через технологию, можно держать пари, что люди получат обучение.

Нельзя сказать, что это - решенный вопрос, или что не будет обратной реакции через 3-5 лет (поскольку всегда существует). Однако тенденцию к FP имеет заслугу и стоит наблюдать.

12
задан Tony Stark 8 September 2009 в 20:21
поделиться

3 ответа

Зависит.

Библиотека

Преобразование форматов файлов обычно решенная проблема для большинства проблемных областей. Например:

  • Batik может перекодировать между различными форматами изображений (включая TIFF).
  • Apache POI может преобразовывать между форматами офисных электронных таблиц.
  • Flexmark может генерировать HTML из Markdown. 12125] Список длинный. Первый вопрос должен быть таким: «Какая библиотека может выполнить эту задачу?» Если производительность важна, ваше время, вероятно, лучше потратить на оптимизацию существующего пакета для удовлетворения ваших потребностей, чем на написание еще одного инструмента. (В качестве бонуса другие люди получают выгоду от централизованной работы.)


    Известные количества

    • Читаете файл? Выделить file.size () байт.
    • Копирование строки? Выделить string.length () байт.
    • Копирование TCP-пакета? Выделите, например, 1500 байт.

    Неизвестные количества

    Если количество байтов действительно неизвестно, вы можете сделать несколько вещей:

    • Сделать предположение.
    • Проанализировать примеры наборов данных в буфере; используйте среднюю длину.

    Пример

    Java StringBuffer , если не указано иное, использует начальный размер буфера для хранения 16 символов. После заполнения 16 символов выделяется новый, более длинный массив, а затем скопированы исходные 16 символов. Если бы StringBuffer имел начальный размер 1024 символа, то перераспределение не происходило бы так рано или так часто.

    Оптимизация

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

    Маловероятно, что это будет узким местом приложения.

7
ответ дан 2 December 2019 в 06:45
поделиться

Типы мест, в которых вы бы использовали ByteBuffer , обычно являются типами мест, в которых вы в противном случае использовали бы массив байтов (который также имеет фиксированный размер). При синхронном вводе-выводе вы часто используете байтовые массивы, при асинхронном вводе-выводе вместо них используются ByteBuffers.

Если вам нужно прочитать неизвестный объем данных с помощью ByteBuffer , рассмотрите возможность использования ] цикл с вашим буфером и добавляйте данные в ByteArrayOutputStream по мере его чтения. Когда вы закончите, вызовите toByteArray () , чтобы получить последний байтовый массив.

Каждый раз, когда вы не совсем уверены в размере (или максимальном размере) данного ввода, считайте цикл (возможно, используя ByteArrayOutputStream , но в противном случае просто обрабатывая данные как поток, как читается) - единственный способ справиться с этим. Без какого-либо цикла все оставшиеся данные, конечно, будут потеряны.

Например:

final byte[] buf = new byte[4096];
int numRead;

// Use try-with-resources to auto-close streams.
try(
  final FileInputStream fis = new FileInputStream(...);
  final ByteArrayOutputStream baos = new ByteArrayOutputStream()
) {
  while ((numRead = fis.read(buf)) > 0) {
    baos.write(buf, 0, numRead);
  }

  final byte[] allBytes = baos.toByteArray();

  // Do something with the data.
}
catch( final Exception e ) {
  // Do something on failure...
}

Если вместо этого вы хотите написать Java int s или другие вещи, не являющиеся исходными байтами, вы можете обернуть свой ByteArrayOutputStream в DataOutputStream :

ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);

while (thereAreMoreIntsFromSomewhere()) {
    int someInt = getIntFromSomewhere();
    dos.writeInt(someInt);
}

byte[] allBytes = baos.toByteArray();    
12
ответ дан 2 December 2019 в 06:45
поделиться

Идея в том, что это всего лишь буфер - не все данные. Это временное место для хранения данных, когда вы читаете кусок, обрабатываете его (возможно, записываете в другое место). Итак, выделите себе достаточно большой «кусок», и обычно это не будет проблемой.

Какую проблему вы ожидаете?

4
ответ дан 2 December 2019 в 06:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: