Begründung für die Gestaltung der öffentlichen Schnittstelle von BytearrayoutputStream?

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

  •  27-10-2019
  •  | 
  •  

Frage

Es gibt viele Bibliotheken von Java -Standard- und Drittanbietern, die in ihrer öffentlichen API Methoden zum Schreiben oder Lesen von Stream. Ein Beispiel ist javax.imageio.ImageIO.write() das macht OutputStream Um den Inhalt eines verarbeiteten Bildes darauf zu schreiben. Ein anderes Beispiel ist ich schreibe PDF -Verarbeitungsbibliothek, die dauert OutputStream Um das resultierende PDF darauf zu schreiben. Das dritte Beispiel ist Amazons3 Java API, die nimmt InputStream Das wird es also lesen und Datei in drei erstellen S3 Speicher.

Das Problem birgt, wenn Sie zwei davon kombinieren möchten. Zum Beispiel habe ich ein Bild als BufferedImage für das ich verwenden muss ImageIO.write das Ergebnis vorantreiben OutputStream. Aber es gibt keinen Direkte Möglichkeit, es zu Amazon S3 zu bringen, wie S3 erfordert InputStream.
Es gibt nur wenige Möglichkeiten, dies auszuarbeiten, aber das Thema dieser Frage ist die Verwendung von ByteArrayOutputStream.

Die Idee dahinter ByteArrayOutputStream ist ein zwischenmidiates Byte -Array eingewickelt Input/Output Stream Damit der Typ, der zum Ausgabestream schreiben möchte, an das Array und den Typ, der lesen möchte, schreiben wird, wird das Array lesen.

Mein Wunder ist der Grund, warum ByteArrayOutputStream Ermöglicht keinen Zugriff auf das Byte -Array, ohne es zu kopieren, zum Beispiel, um eine bereitzustellen InputStream Das hat direkten Zugriff darauf. Die einzige Möglichkeit, darauf zuzugreifen, besteht darin, anzurufen toByteArray(), Dies erzeugt eine Kopie des internen Arrays (der Standard). Was bedeutet, dass ich in meinem Bildbeispiel haben werde, werde ich haben drei Kopien des Bildes im Speicher:

  • Zuerst ist das tatsächliche BufferedImage,
  • zweite ist der innere array des OutputStream und
  • dritte ist die Kopie von produziert von toByteArray() So kann ich das erstellenInputStream.

Wie ist dieses Design gerechtfertigt?

  • Implementierung verstecken? Nur geben getInputStream(), und die Implementierung bleibt versteckt.
  • Multi-Threading? ByteArrayOutputStream ist ohnehin nicht für den Zugriff für mehrere Threads geeignet, so dass dies nicht sein kann.

Darüber hinaus gibt es den zweiten Geschmack von ByteArrayOutputStream, bereitgestellt von Apache's Commons-io Bibliothek (mit einer anderen internen Implementierung). Aber beide haben genau das gleiche Öffentlichkeit Schnittstelle, die keinen Weg zum Zugriff auf das Byte -Array bietet, ohne es zu kopieren.

War es hilfreich?

Lösung

Zum Glück ist das interne Array protected, Sie können es subklassen und a einpacken ByteArrayInputStream um es herum, ohne kopieren.

Andere Tipps

Mein Wunder ist, warum BytearrayoutputStream keinen Zugriff auf das Byte -Array ermöglicht, ohne es zu bewältigen, um es beispielsweise einen InputStream zu liefern, der direkten Zugriff darauf hat.

Ich kann mir vier Gründe vorstellen:

  • Die aktuelle Implementierung verwendet ein einzelnes Byte -Array, könnte jedoch auch als verknüpfte Liste von Byte -Arrays implementiert werden, wodurch die Erstellung des endgültigen Arrays aufgeschoben wird, bis die Anwendung darum verlangt. Wenn die Anwendung den tatsächlichen Bytepuffer sehen könnte, würde dies haben ein einzelnes Array sein.

  • Entgegen Ihrem Verständnis ByteArrayOutputStream ist Faden sicher und ist Geeignet für die Verwendung in multi-thread-Anwendungen. Wenn das Byte -Array jedoch direkter Zugriff gewährt würde, ist es schwierig zu erkennen, wie dies ohne andere Probleme synchronisiert werden könnte.

  • Die API müsste komplizierter sein, da die Anwendung auch wissen muss, wo der aktuelle Puffer -Hochwassermarke ist und ob das Byte -Array (noch) das lebende Byte -Array ist. (Das ByteArrayOutputStream Die Implementierung muss gelegentlich das Byte -Array neu zuordnen ... und die Anwendung wird einen Verweis auf ein Array halten, das nicht mehr ist das Array.)

  • Wenn Sie das Byte -Array freilegen, erlauben Sie einer Anwendung, den Inhalt des Arrays zu ändern, das könnte sein problematisch.


Wie ist dieses Design gerechtfertigt?

Das Design ist auf einfachere Anwendungsfälle als Ihre zugeschnitten. Die Bibliotheken der Java SE-Klasse zielen nicht darauf ab, alle möglichen Anwendungsfälle zu unterstützen. Sie verhindern jedoch nicht, dass Sie (oder eine Bibliothek der Drittanbieter) andere Stream-Klassen für andere Anwendungsfälle anbieten.


Das Fazit ist, dass die Sun -Designer beschlossen, das Byte -Array nicht freizulegen ByteArrayOutputStream, und (IMO) ist es unwahrscheinlich, dass Sie ihre Meinung ändern.

(Und wenn Sie es versuchen möchten, ist dies nicht der richtige Ort, um dies zu tun.

  • Versuchen Sie, ein RFE über die Bugs -Datenbank einzureichen.
  • Oder entwickeln Sie einen Patch, der die Funktionalität hinzufügt, und senden Sie sie über die entsprechenden Kanäle an das OpenJDK -Team. Sie würden Ihre Chancen erhöhen, wenn Sie umfassende Unit -Tests und Dokumentation einfügen.)

Möglicherweise haben Sie mehr Erfolg, die Apache Commons IO -Entwickler von der Richtigkeit Ihrer Argumente zu überzeugen, sofern Sie ein API -Design entwickeln können, das nicht zu gefährlich ist.

Alternativ hindert Sie nichts daran, nur Ihre eigene spezielle Zweckversion zu implementieren, die seine internen Datenstrukturen enthüllt. Der Code ist gpl'ed, damit Sie ihn kopieren können ... vorbehaltlich der normalen GPL -Regeln zur Codeverteilung.

Ich denke, dass das Verhalten, das Sie suchen, a ist Rohr. Ein BytearrayoutputStream ist nur ein Ausgangsstream, kein Eingangs-/Ausgangsstrom. Es wurde nicht für das konzipiert, was Sie im Sinn haben.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top