Обоснование проектирования общественного интерфейса BytearrayOutputStream?
-
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 - это просто выходной поток, а не поток ввода/вывода. Это не было предназначено для того, что вы имеете в виду.