web-dev-qa-db-fra.com

java essayez enfin de bloquer pour fermer le flux

Je veux fermer mon flux dans le bloc finally, mais il lance un IOException il semble donc que je doive imbriquer un autre bloc try dans mon bloc finally pour fermer le flux. Est-ce la bonne façon de procéder? Cela semble un peu maladroit.

Voici le code:

 public void read() {
    try {
        r = new BufferedReader(new InputStreamReader(address.openStream()));
        String inLine;
        while ((inLine = r.readLine()) != null) {
            System.out.println(inLine);
        }
    } catch (IOException readException) {
        readException.printStackTrace();
    } finally {
        try {
            if (r!=null) r.close();
        } catch (Exception e){
            e.printStackTrace();
        }
    }


}
32
jhlu87

Cela semble un peu maladroit.

C'est. Au moins l'essai de Java7 avec des ressources corrige cela.

Avant Java7, vous pouvez créer une fonction closeStream qui l'avale:

public void closeStream(Closeable s){
    try{
        if(s!=null)s.close();
    }catch(IOException e){
        //Log or rethrow as unchecked (like RuntimException) ;)
    }
}

Ou mettez l'essai ... enfin à l'intérieur de la prise d'essai:

try{
    BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()));
    try{

        String inLine;
        while ((inLine = r.readLine()) != null) {
            System.out.println(inLine);
        }
    }finally{
        r.close();
    }
}catch(IOException e){
    e.printStackTrace();
}

Il est plus détaillé et une exception dans le dernier en masquera un lors de l'essai, mais il est sémantiquement plus proche du try-with-resources introduit dans Java 7.

24
ratchet freak

De plus, si vous utilisez Java 7, vous pouvez utiliser une instruction try-with-resources :

try(BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()))) {
    String inLine;
    while ((inLine = r.readLine()) != null) {
        System.out.println(inLine);
    }
} catch(IOException readException) {
    readException.printStackTrace();
}           
35
Steven Goldade

Dans Java 7 vous pouvez le faire ...

try (BufferedReader r = new BufferedReader(...)){
     String inLine;
     while ((inLine = r.readLine()) != null) {
          System.out.println(inLine);
     }
} catch(IOException e) {
   //handle exception
}
  • La déclaration d'une variable dans le bloc try nécessite qu'elle implémente AutoCloseable .
  • La déclaration d'une variable dans le bloc try limite également sa portée au bloc try.
  • Toute variable déclarée dans le bloc try aura automatiquement close() appelée à la fin du bloc try.

Cela s'appelle un Try with resources statement .

23
Jeffrey

Oui, c'est maladroit, laid et déroutant. Une solution possible consiste à utiliser Commons IO qui propose une méthode closeQuietly .

Il y a un certain nombre de questions dans la colonne "Connexes" sur la droite de cette page qui sont en fait des doublons, je vous conseille de les parcourir pour trouver d'autres moyens de résoudre ce problème.

8
fvu

Comme la réponse mentionnant la bibliothèque Commons IO, la Google Guava Libraries a une méthode d'assistance similaire pour les choses qui sont Java.io.Closeable. La classe est com.google.common.io.Closeables . La fonction que vous recherchez porte le même nom que Commons IO: closeQuietly ().

Ou vous pouvez rouler le vôtre pour fermer un groupe comme celui-ci: Closeables.close (closeable1, closeable2, closeable3, ...):

import Java.io.Closeable;
import Java.util.HashMap;
import Java.util.Map;

public class Closeables {
  public Map<Closeable, Exception> close(Closeable... closeables) {

  HashMap<Closeable, Exception> exceptions = null;

  for (Closeable closeable : closeables) {
    try {
      if(closeable != null) closeable.close();
    } catch (Exception e) {
        if (exceptions == null) {
          exceptions = new HashMap<Closeable, Exception>();
        }
        exceptions.put(closeable, e);
      }
    }

    return exceptions;
  }
}

Et cela retourne même une carte de toutes les exceptions qui ont été levées ou nulles si aucune ne l'a été.

5
Jord Sonneveld

Votre approche intérieure est enfin correcte. Si le code que vous appelez dans un bloc finally peut éventuellement lever une exception, assurez-vous de le gérer ou de le journaliser. Ne le laissez jamais sortir du bloc enfin.

Dans le bloc catch, vous avalez l'exception - ce qui n'est pas correct.

Merci...

2
Prabath Siriwardena

La première chose que j'ai remarquée dans votre code est le crochet {} manquant dans votre code si vous le regardez. vous devez également initialiser la valeur de r à null de sorte que vous devez d'abord passer la valeur nulle à l'objet afin que si la condition que vous avez écrite puisse faire not null contrôle la condition et vous permet de fermer le flux.

0
surendrapanday
public void enumerateBar() throws SQLException {
    Statement statement = null;
    ResultSet resultSet = null;
    Connection connection = getConnection();
    try {
        statement = connection.createStatement();
        resultSet = statement.executeQuery("SELECT * FROM Bar");
        // Use resultSet
    }
    finally {
        try {
            if (resultSet != null)
                resultSet.close();
        }
        finally {
            try {
                if (statement != null)
                    statement.close();
            }
            finally {
                connection.close();
            }
        }
    }
}

private Connection getConnection() {
    return null;
}

source . Cet échantillon m'a été utile.

0
dea.diana