Обоснование проектирования общественного интерфейса BytearrayOutputStream?

StackOverflow https://stackoverflow.com/questions/6325596

  •  27-10-2019
  •  | 
  •  

Вопрос

Есть много стандартных Java и сторонних библиотек, которые в их публичном API есть методы для написания или чтения от StreamАнкет Один пример javax.imageio.ImageIO.write() это берет OutputStream написать содержание обработанного изображения в него. Другой пример ITEXT PDF -обработка библиотеки, которая берет OutputStream написать полученный PDF. Третий пример - Amazon3 Java API, который берет InputStream так что это будет читать и создаст файл в THIR S3 хранение.

Проблема, когда вы хотите объединить два из них. Например, у меня есть изображение как BufferedImage для чего я должен использовать ImageIO.write Чтобы подтолкнуть результат в OutputStream. Анкет Но нет непосредственный способ подтолкнуть его к Amazon S3, как требуется S3 InputStream.
Есть несколько способов решить это, но предметом этого вопроса является использование ByteArrayOutputStream.

Идея ByteArrayOutputStream это использование межпрерывного байтового массива, завернутого в Input/Output Stream Так что парень, который хочет написать в выходной поток, напишет на массив, и парню, который хочет прочитать, прочитал массив.

Я удивляюсь, почему ByteArrayOutputStream не допускает никакого доступа к байтовому массиву без копирования, например, для предоставления InputStream Это имеет прямой доступ к нему. Единственный способ получить доступ к нему - это позвонить toByteArray(), это сделает копию внутреннего массива (стандартный). Что означает, в примере моего изображения я буду три Копии изображения в памяти:

  • Первый это фактическое BufferedImage,
  • второй внутренний array принадлежащий OutputStream а также
  • в третьих копия, произведенная toByteArray() Так что я могу создатьInputStream.

Как этот дизайн оправдан?

  • Скрытие реализации? Просто предоставьте getInputStream(), и реализация остается скрытой.
  • Многопоточное? ByteArrayOutputStream В любом случае не подходит для доступа несколькими потоками, так что это не может быть.

Более того, есть второй вкус ByteArrayOutputStream, предоставлено Apache's Commons-IO Библиотека (которая имеет другую внутреннюю реализацию). Но оба имеют одинаковое публичный Интерфейс, который не обеспечивает место для доступа к массиву байтов без его копирования.

Это было полезно?

Решение

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

Другие советы

Я удивляюсь, почему BytearrayOutputStream не допускает никакого доступа к массиву байтов, например, не справляясь, например, для предоставления входного потока, который имеет прямой доступ к нему.

Я могу вспомнить четыре причины:

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

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

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

  • Когда вы обнажаете массив байтов, вы позволяете приложению изменять содержимое массива, который может быть Проблема.


Как этот дизайн оправдан?

Дизайн адаптирован для более простых случаев использования, чем ваш. Библиотеки классов Java SE не стремятся поддерживать все возможные варианты использования. Но они не мешают вам (или сторонней библиотеке) предоставлять другие классы потоков для других случаев использования.


Суть в том, что дизайнеры Sun решили не выставлять байт ByteArrayOutputStream, и (IMO) вы вряд ли изменили их умы.

(И если вы хотите попробовать, это не подходящее место, чтобы сделать это.

  • Попробуйте отправить RFE через базу данных ошибок.
  • Или разработать патч, который добавляет функциональность и отправляйте его в команду OpenJDK через соответствующие каналы. Вы бы увеличили свои шансы, если вы включите всеобъемлющие модульные тесты и документацию.)

У вас может быть больший успех, убедившись, что разработчики Apache Commons IO в праве ваших аргументов при условии, что вы можете придумать дизайн API, который не слишком опасен.

В качестве альтернативы, ничто не помешает вам просто реализовать свою собственную версию специального назначения, которая раскрывает ее внутренние структуры данных. Код GPL'ed, так что вы можете скопировать его ... в зависимости от обычных правил GPL о распределении кода.

Я думаю, что поведение, которое вы ищете, является Трубка. Анкет BytearrayOutputStream - это просто выходной поток, а не поток ввода/вывода. Это не было предназначено для того, что вы имеете в виду.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top