¿Justificación para el diseño de la interfaz pública de BytearRayOutputStream?

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

  •  27-10-2019
  •  | 
  •  

Pregunta

Hay muchas bibliotecas de Java Standard y terceros que en su API pública, hay métodos para escribir o leer desde Stream. Un ejemplo es javax.imageio.ImageIO.write() eso toma OutputStream para escribirle el contenido de una imagen procesada. Otro ejemplo es yo texteo Biblioteca de procesamiento de PDF que toma OutputStream para escribirle el PDF resultante. El tercer ejemplo es Amazons3 Java API, que toma InputStream Entonces eso lo leerá y creará archivo en Thir Almacenamiento S3.

El problema se aza cuando quieres combinar dos de estos. Por ejemplo, tengo una imagen como BufferedImage para el cual tengo que usar ImageIO.write para impulsar el resultado en OutputStream. Pero no hay directo Manera de empujarlo a Amazon S3, como lo requiere S3 InputStream.
Hay pocas formas de resolver esto, pero el tema de esta pregunta es el uso de ByteArrayOutputStream.

La idea detrás ByteArrayOutputStream es usar una matriz de bytes intermidias envuelta en Input/Output Stream Para que el tipo que quiere escribir en la transmisión de salida escriba en la matriz y al tipo que quiere leer, leerá la matriz.

Me pregunto es por qué ByteArrayOutputStream no permite ningún acceso a la matriz de bytes sin copiarlo, por ejemplo, para proporcionar un InputStream que tiene acceso directo a él. La única forma de acceder a él es llamar toByteArray(), que hará una copia de la matriz interna (la estándar). Lo que significa, en mi ejemplo de imagen, tendré Tres Copias de la imagen en la memoria:

  • Primero es el real BufferedImage,
  • segundo es el interno array del OutputStream y
  • tercera es la copia producida por toByteArray() para que pueda crear elInputStream.

¿Cómo se justifica este diseño?

  • ¿Ocultar implementación? Solo proporcionar getInputStream(), y la implementación permanece oculta.
  • ¿Multi-subprocesos? ByteArrayOutputStream No es adecuado para el acceso por múltiples hilos de todos modos, por lo que esto no puede serlo.

Además, hay segundo sabor de ByteArrayOutputStream, proporcionado por Apache's comunes-io Biblioteca (que tiene una implementación interna diferente). Pero ambos tienen exactamente lo mismo público interfaz que no proporciona una forma de acceder a la matriz de bytes sin copiarla.

¿Fue útil?

Solución

Afortunadamente, la matriz interna es protected, para que puedas subclase y envolver un ByteArrayInputStream A su alrededor, sin ninguna copia.

Otros consejos

Me pregunto por qué BytearRayOutputStream no permite ningún acceso a la matriz de bytes sin hacer frente, por ejemplo, para proporcionar un InputStream que tenga acceso directo a ella.

Puedo pensar en cuatro razones:

  • La implementación actual utiliza una sola matriz de bytes, pero también podría implementarse como una lista vinculada de matrices de bytes, diferiendo la creación de la matriz final hasta que la aplicación lo solicite. Si la aplicación pudiera ver el búfer de byte real, lo haría tener ser una sola matriz.

  • Contrariamente a su comprensión ByteArrayOutputStream es hilo seguro y es Adecuado para su uso en aplicaciones multiproceso. Pero si se proporcionó acceso directo a la matriz de bytes, es difícil ver cómo eso podría sincronizarse sin crear otros problemas.

  • La API necesitaría ser más complicada porque la aplicación también necesita saber dónde está la marca actual de agua del tampón actual y si la matriz de bytes es (todavía) la matriz de bytes en vivo. (Los ByteArrayOutputStream La implementación ocasionalmente necesita reasignar la matriz de bytes ... y eso dejará la aplicación que contiene una referencia a una matriz que ya no es la formación.)

  • Cuando expone la matriz de bytes, permite que una aplicación modifique el contenido de la matriz, que podría ser problemático.


¿Cómo se justifica este diseño?

El diseño está diseñado para casos de uso más simples que el suyo. Las bibliotecas de clase Java SE no tienen como objetivo admitir todos los casos de uso posibles. Pero no evitan que usted (o una biblioteca de terceros) proporcione otras clases de transmisión para otros casos de uso.


La conclusión es que los diseñadores de Sun decidieron no exponer la matriz de bytes para ByteArrayOutputStream, y (en mi opinión) es poco probable que cambies de opinión.

(Y si quieres intentarlo, este no es el lugar correcto para hacerlo.

  • Intente enviar un RFE a través de la base de datos de errores.
  • O desarrolle un parche que agrega la funcionalidad y envíela al equipo OpenJDK a través de los canales relevantes. Aumentaría sus posibilidades si incluía pruebas y documentación unitarias integrales).

Es posible que tenga más éxito convencer a los desarrolladores de Apache Commons IO de la rectitud de sus argumentos, siempre que pueda encontrar un diseño de API que no sea demasiado peligroso.

Alternativamente, no hay nada que le impida implementar su propia versión de propósito especial que exponga sus estructuras de datos internos. El código se gpl'ed para que pueda copiarlo ... sujeto a las reglas Normales de GPL sobre la distribución del código.

Creo que el comportamiento que estás buscando es un Tubo. Un bytearRayOutputStream es solo una salida de salida, no una secuencia de entrada/salida. No fue diseñado para lo que tienes en mente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top