2012-11-05 8 views
5

Ich habe eine Methode, die eine InputStream (von Binärdaten) akzeptiert und es in XML serialisiert. Um dies zu tun, wird der Stream mit einem Base64-Encoder und einem Reader umwandelt, um es in Zeichendaten umzuwandeln. Da jedoch die InputStream als ein Parameter übergeben wird, würde ich es als einen schädlichen Nebeneffekt betrachten, den Stream zu schließen, und der Vertrag für Reader.close() sagt, dass es genau das tun würde. Wenn ich den Leser nicht schließen, warnt der Compiler mir, dass ich einIst es möglich, einen Reader zu schließen, ohne den Stream zu schließen?

Ressourcenleck: Leser nie

So geschlossen sind, habe ich ein @SuppressWarnings("resource") den Leser Erklärung hinzufügen kann, ist aber das Richtige zu tun? Fehle ich etwas? Hier

ist der eigentliche Code:

/** 
* Writes base64 encoded text read from the binary stream. 
* 
* @param binaryStream 
*   The binary stream to write from 
* @return <code>this</code> XmlWriter (for chaining) 
* @throws IOException 
*/ 
public XmlWriter binary(InputStream binaryStream) throws IOException { 
    Reader reader = new InputStreamReader( 
      new Base64InputStream(binaryStream, true, base64LineLength, base64LineSeparator.getBytes(charset))); 
    int bufferSize = 2048; 
    int charsRead; 
    char[] buffer = new char[bufferSize]; 
    while ((charsRead = reader.read(buffer, 0, bufferSize)) >= 0) { 
     writer.write(buffer, 0, charsRead); 
    } 

    return this; 
} 
+0

Was ist Ihr Ziel, die Strom offen halten zu wollen? Sie können es jederzeit wieder öffnen. – mabako

+0

Gibt es eine Möglichkeit, Ihren Code zu ändern, um einen Reader für den InputStream zu erstellen, und ihn an Methoden zu übergeben, die einen Reader benötigen? Auf die eine oder andere Art sollten der Reader und der Eingabestrom zusammen geschlossen werden. –

+0

@ mabako, es ist nicht wirklich ein Wunsch, den Stream offen zu halten, ist es eher eine Verantwortung Sache. Ich versuche alles zu schließen, wo es geöffnet ist. Wenn die Binärmethode den Stream schließt und etwas außerhalb dieses Aufrufs versucht, etwas damit zu tun, könnte dies durch eine Ausnahme geschehen, die der Benutzer nicht erwartet hat. – Lucas

Antwort

1

Wenn Sie ein glücklicher Java 7 Benutzer, versuchen Sie dies:

try(InputStream binaryStream = /* ... */) { 
    xmlWriter.binary(binaryStream); 
} 

und Strom wird für Sie geschlossen. Wenn Sie Java 7 nicht verwenden können, stimme ich zu, dass es nicht die Verantwortung der binary() Methode zu close() der Stream ist. Ignorieren Sie einfach die Warnung und lassen Sie keine Werkzeuge Ihr Design fahren. Das ist gut.

Als letzten Ausweg können Sie eine leichte Reader Wrapper Ignoring close() schreiben, aber ich rate es nicht, da es macht den Programmablauf härter.

lassen sich auch Apache Commons IO helfen Ihnen bei IOUtils.copy():

public XmlWriter binary(InputStream binaryStream) throws IOException { 
    Reader reader = new InputStreamReader( 
      new Base64InputStream(binaryStream, true, base64LineLength, base64LineSeparator.getBytes(charset))); 
    IOUtils.copy(reader, writer); 
    return this; 
} 
+0

Ich verstehe Ihr erstes Segment nicht, da das nur zeigt, was ich gerade mache, das heißt, den 'InputStream' im Aufrufer der binären Methode zu schließen, nicht in der Methode selbst. Ich benutze Java 6, habe aber nur den Abschluss in einem Endblock. Ich könnte einen Wrapper schreiben, ja, aber das scheint weniger korrekt zu sein als die '@SuppressWarnings (" resource ")'.Gute Vorschläge für IOUtils, normalerweise mache ich sowas, nur dass es eine Low-Level-Bibliothek ist und ich so wenig Abhängigkeiten wie möglich haben wollte. – Lucas

+0

@Lucas: Du hast Recht, der erste Teil meiner Antwort wiederholt nur deine Herangehensweise - was ich richtig fand. Beachten Sie, dass die Bibliothek 'IOUtils.copy()' den 'Reader' nach dem Kopieren auch nicht schließt. Ich möchte nur sagen: Es ist das Werkzeug, das falsch ist, nicht du. –

0

Dies ist ein vielleicht ein „Feature“ in der Art und Weise Base64InputStream Arbeit, auch wenn Sie die Länge angeben, zu lesen, wird es den zugrunde liegenden Stream schließen, wenn Sie es schließen wenn du eindeutig beabsichtigst, den ganzen Strom nicht zu lesen.

Sie könnten den binaryStream in einen InputStream umbrechen, der den Abschluss ignoriert, oder Sie könnten die Warnung wie gewohnt unterdrücken.

+0

Gute Vorschlag auf dem Wrapper, aber das scheint weniger korrekt als die '@SuppressWarnings (" Ressource ")'. – Lucas

Verwandte Themen