Frage

ich nur mit Java-Dateisystem API gespielt und kam mit der folgenden Funktion nach unten, verwendet, um binären Dateien zu kopieren. Die ursprüngliche Quelle stammte aus dem Internet, aber ich hinzugefügt try / catch / finally-Klauseln sicher sein, dass, sollte etwas nicht in Ordnung geschehen, würde die Buffer Streams geschlossen (und damit meine OS Ressourcen befreit), bevor die Funktion quiting.

ich beschnitten, um die Funktion nach unten um das Muster zu zeigen:

public static void copyFile(FileOutputStream oDStream, FileInputStream oSStream) throw etc...
{
   BufferedInputStream oSBuffer = new BufferedInputStream(oSStream, 4096);
   BufferedOutputStream oDBuffer = new BufferedOutputStream(oDStream, 4096);

   try
   { 
      try
      { 
         int c;

         while((c = oSBuffer.read()) != -1)  // could throw a IOException
         {
            oDBuffer.write(c);  // could throw a IOException
         }
      }
      finally
      {
         oDBuffer.close(); // could throw a IOException
      }
   }
   finally
   {
      oSBuffer.close(); // could throw a IOException
   }
}

Soweit ich es verstehe, kann ich nicht die zwei close() in der finally-Klausel setzen, weil der erste close() gut werfen konnte, und dann würde die zweite nicht ausgeführt werden.

ich weiß, C # hat die Entsorgen Muster, das dies mit dem using Stichwort betastet haben würde.

Ich weiß, noch besser ein C ++ Code etwas gewesen wäre, wie (unter Verwendung einer Java-ähnliche API):

void copyFile(FileOutputStream & oDStream, FileInputStream & oSStream)
{
   BufferedInputStream oSBuffer(oSStream, 4096);
   BufferedOutputStream oDBuffer(oDStream, 4096);

   int c;

   while((c = oSBuffer.read()) != -1)  // could throw a IOException
   {
      oDBuffer.write(c);  // could throw a IOException
   }

   // I don't care about resources, as RAII handle them for me
}

Ich bin etwas fehlt, oder muss ich wirklich nur hässlich und aufgeblähten Code in Java erzeugen Ausnahmen in der close() Methode eines Buffered-Stream zu behandeln?

(Bitte, sagen Sie mir, ich bin falsch irgendwo ...)

EDIT: Ist es mir, oder wenn Sie diese Seite aktualisieren, ich sah die beide Frage und alle von einem Punkt in ein paar Minuten verringert Antworten? Ist jemand sich zu viel zu genießen, während remaning anonym?

EDIT 2: McDowell bot eine sehr interessante Verbindung, die ich fühlte ich schon erwähnt, musste sich hier: http: //illegalargumentexception.blogspot .com / 2008/10 / java-how-not-to-make-mess-of-stream.html

EDIT 3: McDowell Link Folgen, ich auf einen Vorschlag getrommelt für Java 7 ein Muster ähnlich die C # Muster: http://tech.puredanger.com/java7/#resourceblock . Mein Problem ist explizit beschrieben. Offenbar auch mit dem Java 7 do, bleiben die Probleme.

War es hilfreich?

Lösung

Die try / finally Muster sind der richtige Weg 6-Streams in den meisten Fällen für Java zu handhaben und niedriger.

Einige befürworten lautlos schließen Ströme. Seien Sie vorsichtig, tun dies aus diesen Gründen: Java: wie nicht ein Chaos von Strom Handhabung

machen

Java 7 einleitet Try-with-Ressourcen :

/** transcodes text file from one encoding to another */
public static void transcode(File source, Charset srcEncoding,
                             File target, Charset tgtEncoding)
                                                             throws IOException {
    try (InputStream in = new FileInputStream(source);
         Reader reader = new InputStreamReader(in, srcEncoding);
         OutputStream out = new FileOutputStream(target);
         Writer writer = new OutputStreamWriter(out, tgtEncoding)) {
        char[] buffer = new char[1024];
        int r;
        while ((r = reader.read(buffer)) != -1) {
            writer.write(buffer, 0, r);
        }
    }
}

AutoCloseable Arten geschlossen werden automatisch :

public class Foo {
  public static void main(String[] args) {
    class CloseTest implements AutoCloseable {
      public void close() {
        System.out.println("Close");
      }
    }
    try (CloseTest closeable = new CloseTest()) {}
  }
}

Andere Tipps

Es gibt Probleme, aber der Code, den Sie auf dem Netz herumliegen gefunden ist wirklich schlecht.

, um die Pufferströme Schließen schließt den Strom unter. Sie wollen wirklich nicht, das zu tun. Alles, was Sie tun möchten, ist der Ausgangsstrom bündig. Auch gibt es keinen Sinn, bei der Angabe der zugrunde liegenden Ströme sind für Dateien. Leistung saugt, weil Sie kopieren ein Byte zu einem Zeitpunkt (eigentlich, wenn Sie java.io Gebrauch verwenden können, verwenden transferTo / transferFrom, die ein bisschen schneller noch ist). Während wir darüber sind, saugen die Variablennamen an. Also:

public static void copy(
    InputStream in, OutputStream out
) throw IOException {
    byte[] buff = new byte[8192];
    for (;;) {
        int len = in.read(buff);
        if (len == -1) {
            break;
        }
        out.write(buff, 0, len);
    }
}

Wenn Sie sich finden, mit Try-schließlich eine Menge, dann können Sie es mit dem „ausführen um“ ausklammern Idiom.

Meiner Meinung nach: Java sollte someway der Schließung Ressourcen am Ende des Umfangs hat. Ich schlage vor, das Hinzufügen private als einstelliger Postfix-Operator am Ende des einschließenden Blockes zu schließen.

Ja, das ist, wie Java funktioniert. Es gibt Steuer Inversion - der Benutzer des Objekts muss wissen, wie das Objekt zu bereinigen, anstatt das Objekt selbst nach selbst aufzuräumen. Dies führt leider zu viel Code Bereinigung in Ihrem Java-Code verstreut.

C # hat die „mit“ Keyword automatisch Dispose aufrufen, wenn ein Objekt den Gültigkeitsbereich verlässt. Java hat keine solche Sache.

Leider neigt diese Art von Code ein bisschen aufgebläht in Java zu erhalten.

By the way, wenn eine der Anrufe oSBuffer.read oder oDBuffer.write eine Ausnahme auslöst, dann wollen Sie wahrscheinlich, dass Ausnahme der Aufrufhierarchie durchdringen bis lassen.

einen unbewachten Anruf Mit () innerhalb einer endlich-Klausel schließen wird die ursprüngliche Ausnahme verursachen, indem sie durch die close () erzeugt ersetzt werden - nennen. Mit anderen Worten, in Ermangelung einer close () - Methode kann die ursprüngliche Ausnahme von Lese erzeugt verstecken () oder schreiben (). Also, ich glaube, Sie wollen Ausnahmen von close (), wenn und nur dann, wenn die anderen Methoden geworfen ignorieren nicht werfen.

ich in der Regel dieses Problem lösen, indem einen expliziten close-Aufruf einschließlich, innerhalb des inneren try:

  try {
    while (...) {
      read...
      write...
    }
    oSBuffer.close(); // exception NOT ignored here
    oDBuffer.close(); // exception NOT ignored here
  } finally {
    silentClose(oSBuffer); // exception ignored here
    silentClose(oDBuffer); // exception ignored here
  }
  static void silentClose(Closeable c)  {
    try {
      c.close();
    } catch (IOException ie) {
      // Ignored; caller must have this intention
    }
  }

Schließlich für die Leistung, sollte der Code wahrscheinlich mit Puffern (mehrere Byte pro Lese- / Schreib) arbeiten. Kann nicht durch Zahlen zurück, aber weniger Anrufe sollten effizienter sein als auf gepufferte Ströme hinzugefügt wird.

Für gemeinsame IO-Aufgaben wie das Kopieren einer Datei, Code wie das oben gezeigt wird das Rad neu erfinden. Leider hat das JDK keinen höhere Ebene Dienstprogramme bieten, aber Apache commons-io hat.

Zum Beispiel FileUtils für das arbeiten mit Dateien und Verzeichnissen verschiedene Hilfsmethoden enthält (einschließlich Kopieren). Auf der anderen Seite, wenn Sie wirklich brauchen die IO Unterstützung im JDK IOUtils eine Reihe von closeQuietly enthält () Methoden, die Leser zu schließen, Schriftsteller, Bäche, usw., ohne Ausnahmen zu werfen.

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