Schließen eines Java Fileinputstream

stimmen
31

In Ordnung, ich habe getan, um die folgende (Variablennamen wurden geändert):


FileInputStream fis = null;
try
{
    fis = new FileInputStream(file);

    ... process ...

}
catch (IOException e)
{
    ... handle error ...
}
finally
{
    if (fis != null)
        fis.close();
}

Vor kurzem begann ich FindBugs mit, was darauf schließen lässt, dass ich richtig bin nicht Ströme schließen. Ich beschließe, um zu sehen, ob es etwas gibt, das mit einem finally {} -Block durchgeführt werden kann, und dann sehe ich, oh yeah, close () kann IOException werfen. Was sollen die Menschen hier tun? Die Java-Bibliotheken werfen zu viele Ausnahmen geprüft.

Veröffentlicht am 01/10/2008 um 08:00
quelle vom benutzer
In anderen Sprachen...                            


9 antworten

stimmen
40

Für Java 7 und höher Try-with-Ressourcen verwendet werden sollen:

try (InputStream in = new FileInputStream(file)) {
  // TODO: work
} catch (IOException e) {
  // TODO: handle error
}

Wenn Sie auf Java 6 oder unten stecken ...

Dieses Muster vermeidet herumschlagen mit null :

    try {
        InputStream in = new FileInputStream(file);
        try {
            // TODO: work
        } finally {
            in.close();
        }
    } catch (IOException e) {
        // TODO: error handling
    }

Für ein Detail auf , wie zu effektiv behandeln Nähe , lesen Sie diese Blog - Post: Java: wie nicht ein Chaos von Strom Handhabung zu machen . Es hat mehr Beispielcode, mehr Tiefe und deckt die Gefahren der Umwickeln Schließen in einem Rastblock.

Beantwortet am 01/10/2008 um 10:44
quelle vom benutzer

stimmen
25

So etwas wie die folgenden sollte es an Ihnen tun, ob Sie die IOException werfen oder schlucken auf dem Versuch, den Strom zu schließen.

FileInputStream fis = null;
try
{
    fis = new FileInputStream(file);

    ... process ...


}
catch (IOException e)
{
    ... blah blah blah ...
}
finally
{
    try
    {
        if (fis != null)
            fis.close();
    }
    catch (IOException e)
    {
    }
}
Beantwortet am 01/10/2008 um 08:05
quelle vom benutzer

stimmen
10

Sie könnten der Verwendung Try-with-Ressourcen Feature JDK7 hinzugefügt. Es wurde gerade erstellt mit dieser Art von Dingen zu beschäftigen

static String readFirstLineFromFile(String path) throws IOException {
  try (BufferedReader br = new BufferedReader(new FileReader(path))) {
    return br.readLine();
  }
}

Die Dokumenation sagt:

Die Try-mit-Ressourcen-Anweisung stellt sicher, dass jede Ressource am Ende der Anweisung geschlossen wird.

Beantwortet am 17/05/2012 um 23:35
quelle vom benutzer

stimmen
4

Sie könnten auch eine einfache statische Helper-Methode verwenden:

public static void closeQuietly(InputStream s) {
   if (null == s) {
      return;
   }
   try {
      s.close();
   } catch (IOException ioe) {
      //ignore exception
   }
}

und verwenden Sie diese von Ihrem finally-Block.

Beantwortet am 01/10/2008 um 08:12
quelle vom benutzer

stimmen
3

Es gibt nicht viel hinzuzufügen, außer einen sehr geringen stilistischen Vorschlag. Das kanonische Beispiel für Code selbst dokumentierten gilt in diesem Fall - gibt einen beschreibenden Variablennamen die ignoriert , IOExceptiondass Sie fangen müssen close().

So Squiddle Antwort wird:

public static void closeQuietly(InputStream s) {
   try {
      s.close();
   } catch (IOException ignored) {
   }
}
Beantwortet am 01/10/2008 um 09:12
quelle vom benutzer

stimmen
2

In den meisten Fällen finde ich es nur besser nicht die IO Ausnahmen zu fangen, und verwenden Sie einfach versuchen- zu guter Letzt:

final InputStream is = ... // (assuming some construction that can't return null)
try {
    // process is
    ...
} finally {
    is.close();
}

Mit Ausnahme FileNotFoundException, können Sie in der Regel nicht „Umgehen“ ein IOException. Das einzige , was noch zu tun ist , einen Fehler zu melden, und Sie werden in der Regel handhaben, dass weiter oben in dem Call - Stack, so finde ich es besser , die Ausnahme zu propagieren.

Da IOExceptioneine geprüfte Ausnahme ist, werden Sie , dass dieser Code erklären (und jeder seiner Kunden) throws IOException. Das könnte zu laut sein, oder Sie möglicherweise nicht über die Implementierung Detail mit IO zeigen wollen. In diesem Fall können Sie den gesamten Block mit einem Exception - Handler wickeln , dass die Packungen IOExceptionin einem RuntimeExceptionoder einem abstrakten Ausnahmetyp.

Detail: Ich bin mir bewusst , dass der obige Code jede Ausnahme vom schluckt tryBlock , wenn der closeBetrieb in dem finallyBlock eine erzeugt IOException. Ich glaube nicht , dass ein großes Problem: In der Regel, die Ausnahme von dem tryBlock wird das gleiche sein , IOExceptiondass die Ursachen closezu versagen (dh es ist sehr selten für IO gut funktionieren und dann an dem Punkt des Schließens gescheitert). Wenn dies ein Problem ist, könnte es die Mühe auf „Schweigen“ die Nähe wert sein.

Beantwortet am 01/10/2008 um 11:52
quelle vom benutzer

stimmen
1

Die folgende Lösung wirft korrekt eine Ausnahme, wenn schließt nicht ohne eine mögliche Ausnahme vor dem Ende versteckt.

try {
    InputStream in = new FileInputStream(file);
    try {
        // work
        in.close();
    } finally {
        Closeables.closeQuietly(in);
    }
} catch(IOException exc) {
    // kernel panic
}

Das funktioniert , weil Aufruf der Nähe ein zweites Mal keine Wirkung hat .

Dies beruht auf Guave Closeables , aber man kann seine eigene closeQuietly Methode schreiben , wenn bevorzugt, wie gezeigt Squiddle (siehe auch serg10 ).

Melden eines Fehlers der Nähe, im allgemeinen Fall, ist wichtig, weil in der Nähe ein paar letzte Byte in den Stream schreiben könnte, zB durch Pufferung. Daher möchte Ihre Benutzer wissen, ob es ausgefallen ist, oder Sie wahrscheinlich irgendwie handeln wollen. Zugegeben, dies im konkreten Fall eines Fileinputstream nicht wahr sein könnte, weiß ich nicht (aber aus Gründen bereits erwähnen Ich denke, es ist besser, einen wachsamen Fehler zu melden, wenn sie auftritt sowieso).

Der obige Code ist ein bisschen schwierig, aufgrund der Struktur der eingebetteten try-Blöcke zu erreichen. Es könnte klarer mit zwei Methoden in Betracht gezogen werden, eine, die eine IOException und wirft man, dass es fängt. Zumindest ist das, was ich für opt.

private void work() throws IOException {
    InputStream in = new FileInputStream(file);
    try {
        // work
        in.close();
    } finally {
        Closeables.closeQuietly(in);
    }
}

public void workAndDealWithException() {
    try {
        work();
    } catch(IOException exc) {
        // kernel panic
    }
}

Basierend auf http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html (bezogen von McDowell).

Beantwortet am 23/07/2011 um 20:28
quelle vom benutzer

stimmen
0

Hoffentlich werden wir bekommen Schließungen in Java eines Tages, und dann werden wir viele der Ausführlichkeit verlieren.

Anstatt also wird es eine Hilfsmethode somwhere in javaIO sein, dass Sie importieren können, wird es dauert wahrscheinlich einen „Verschließbare“ Schnittstelle und auch einen Block. Innerhalb dieses Hilfsmethode wird der try {closable.close ()} catch (IOException ex) {// blah} definiert ein für alle Mal, und dann werden Sie in der Lage zu schreiben

 Inputstream s = ....;
 withClosable(s) {
    //your code here
 }
Beantwortet am 01/10/2008 um 08:18
quelle vom benutzer

stimmen
-4

Betroffen sind Sie in erster Linie mit einem sauberen Bericht von FindBugs bekommen oder mit Code , das funktioniert? Diese sind nicht unbedingt das Gleiche. Ihr Original - Code ist in Ordnung (obwohl ich werde die redundanten befreien würde if (fis != null)überprüfen , da eine OutOfMemoryExceptionwürde geworfen wurde aus anderen Gründen ). Fileinputstream hat eine Finalizer - Methode , die den Strom für Sie in dem unwahrscheinlichen Fall , schließen die Sie tatsächlich eine IOException in Ihrer Verarbeitung erhalten. Es ist einfach nicht wert , die Mühe Code anspruchsvollere machen die extrem unwahrscheinliches Szenario von vermeiden

  1. Sie erhalten eine IOException und
  2. dies geschieht so oft, dass Sie in Finalizerthread Rückstand Probleme laufen.

Edit: Wenn Sie so viele IOExceptions bekommen , dass Sie Probleme laufen mit der Finalizerthread Warteschlange dann haben Sie weit weit größere Fische zu braten! Hier geht es um eine Perspektive zu bekommen.

Beantwortet am 01/10/2008 um 09:37
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more