Question

Il y a beaucoup de bibliothèques Java standard et 3e partie que dans leur API publique, il existe des méthodes pour l'écriture ou la lecture de Stream. Un exemple est javax.imageio.ImageIO.write() qui prend OutputStream pour écrire le contenu d'une image traitée à elle. Un autre exemple est iText pdf bibliothèque de traitement qui prend OutputStream pour écrire le pdf peut entraîner. Troisième exemple est AmazonS3 API Java, qui prend InputStream ce qui va le lire et de créer un fichier dans thir stockage S3 .

Le problème araises quand vous voulez combiner deux de ces derniers. Par exemple, j'ai une image BufferedImage pour laquelle je dois utiliser ImageIO.write pour pousser le résultat dans OutputStream. Mais il n'y a pas directement façon de le pousser à Amazon S3, S3 nécessite InputStream.
Il existe quelques moyens de nous en sortir, mais sous réserve de cette question est l'utilisation de ByteArrayOutputStream.

L'idée derrière ByteArrayOutputStream est d'utiliser un tableau d'octets intermidiate enveloppé dans Input/Output Stream de sorte que le gars qui veut écrire flux de sortie écrire sur le tableau et le gars qui veut lire, va lire le tableau.

Ma demande est pourquoi ByteArrayOutputStream ne permet pas d'accéder au tableau d'octets sans le copier, par exemple, de fournir un InputStream qui a un accès direct à elle. La seule façon d'y accéder est d'appeler toByteArray(), qui fera une copie du tableau interne (l'un standard). Ce qui signifie, dans mon exemple d'image, je vais avoir trois copies de l'image dans la mémoire:

  • Première est la BufferedImage réelle,
  • secondes est le array interne du OutputStream et
  • tiers est la copie produite par toByteArray() donc je peux créer la InputStream.

Comment cette conception est-elle justifiée?

  • la mise en œuvre Hiding? Il suffit de fournir getInputStream(), et les séjours de mise en œuvre cachés.
  • Multi-threading? ByteArrayOutputStream ne convient pas pour l'accès par plusieurs threads de toute façon, cela ne peut pas être.

De plus, il y a la deuxième saveur de ByteArrayOutputStream, fourni par Apache commons-io bibliothèque (qui a une autre implémentation interne). Mais les deux ont exactement les mêmes publique l'interface qui ne fournit pas moyen d'accéder au tableau d'octets sans le copier.

Était-ce utile?

La solution

Heureusement, le tableau interne est protected, de sorte que vous pouvez sous-classe, et envelopper un ByteArrayInputStream autour d'elle, sans aucune copie.

Autres conseils

Ma demande est pourquoi ByteArrayOutputStream ne permet pas d'accéder au tableau d'octets sans faire face, par exemple, de fournir un InputStream qui a un accès direct à elle.

Je peux penser à quatre raisons:

  • L'implémentation actuelle utilise un seul tableau d'octets, mais il pourrait également être mis en œuvre comme une liste chaînée de tableaux d'octets, de reporter la création du tableau finale jusqu'à ce que la demande demande. Si l'application pourrait voir le tampon d'octets réel, il serait Vous pour être un seul tableau.

  • Contrairement à votre compréhension ByteArrayOutputStream est thread en toute sécurité, et est adapté à une utilisation dans les applications multi-thread. Mais si un accès direct a été fourni au tableau d'octets, il est difficile de voir comment cela pourrait être synchronisé sans créer d'autres problèmes.

  • L'API devrait être plus compliqué, car l'application a également besoin de savoir où la marque tampon courant élevé de l'eau est et si le tableau d'octets est (encore) le tableau d'octets en direct. (La mise en œuvre de ByteArrayOutputStream a parfois besoin de réallouer le tableau d'octets ... et qui laissera la demande la tenue d'une référence à un tableau qui n'est plus le tableau ).

  • Lorsque vous exposez le tableau d'octets, vous autorisez une application de modifier le contenu du tableau, qui pourrait être problématique.


Comment cette conception est-elle justifiée?

La conception est adaptée à des cas d'utilisation que les vôtres plus simples. Les bibliothèques de classes Java SE ne visent pas à soutenir tous les cas d'utilisation possibles. Mais ils ne vous empêche pas (ou une bibliothèque 3ème partie) de fournir d'autres classes de flux pour d'autres cas d'utilisation.


L'essentiel est que le Soleil concepteurs ont décidé de ne pas exposer le tableau d'octets pour ByteArrayOutputStream et (OMI), vous ne sont pas susceptibles de changer d'avis.

(Et si vous voulez essayer, ce n'est pas le bon endroit pour le faire.

  • Essayez d'envoyer un RFE via la base de données de bogues.
  • Ou développer un patch qui ajoute la fonctionnalité et le soumettre à l'équipe OpenJDK via les canaux appropriés. Vous augmenterez vos chances si vous avez inclus des tests unitaires et documentation).

Vous pourriez avoir plus de succès à convaincre les développeurs Apache Commons IO de la justesse de vos arguments, à condition que vous pouvez venir avec un design API qui ne sont pas trop dangereux.

Sinon, il n'y a rien qui vous empêche de tout mettre en œuvre votre propre version à usage spécial qui expose ses structures de données internes. Le code est sous LPG et vous pouvez le copier ... sous réserve des règles de GPL normales sur la distribution de code.

Je pense que le comportement que vous recherchez est un tuyau . Un ByteArrayOutputStream est juste un OutputStream, pas d'entrée / flux de sortie. Il n'a pas été conçu pour ce que vous avez à l'esprit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top