43 votes

Java io moche essayer-finalement bloquer

Existe-t-il un moyen moins laid de traiter l'exception close () pour fermer les deux flux alors:

     InputStream in = new FileInputStream(inputFileName);
    OutputStream out = new FileOutputStream(outputFileName);

    try {
    copy(in, out);
    } finally {
    try {
        in.close();
    } catch (Exception e) {
        try {
        // event if in.close fails, need to close the out
        out.close();
        } catch (Exception e2) {}
        throw e; // and throw the 'in' exception
    }
    out.close();
    }
 

mise à jour: tout le code ci-dessus est dans un plus try-catch, merci pour les avertissements.

- FINALEMENT (après les réponses)

Et une bonne méthode d'utilité peut être utilisée avec l' idiome Execute Around (merci à Tom Hawtin).

54voto

Yishai Points 42417

Ceci est l'idom correct (et cela fonctionne bien):

    InputStream in = null;
   OutputStream out = null;
   try {
       in = new FileInputStream(inputFileName);
       out = new FileOutputStream(outputFileName);
       copy(in, out);
   finally {
       close(in);
       close(out);
   }

  public static void close(Closeable c) {
     if (c == null) return; 
     try {
         c.close();
     } catch (IOException e) {
         //log the exception
     }
  }
 

La raison pour laquelle cela fonctionne bien est que l'exception levée avant votre arrivée sera finalement levée après la fin de votre code, à condition que votre code final ne lance pas lui-même une exception ou ne se termine pas d'une autre manière anormale.

32voto

Adamski Points 29884

Vous pouvez implémenter une méthode utilitaire:

 public final class IOUtil {
  private IOUtil() {}

  public static void closeQuietly(Closeable... closeables) {
    for (Closeable c : closeables) {
        if (c != null) try {
          c.close();
        } catch(Exception ex) {}
    }
  }
}
 

Ensuite, votre code serait réduit à:

 try {
  copy(in, out);
} finally {
  IOUtil.closeQuietly(in, out);
}
 

Additionnel

J'imagine qu'il y aura une telle méthode dans une bibliothèque open source tierce. Toutefois, ma préférence est d'éviter les dépendances inutiles de la bibliothèque, sauf si j'utilise une grande partie de ses fonctionnalités. Par conséquent, j'ai tendance à mettre en œuvre des méthodes d'utilité simples comme celle-ci.

18voto

try {
    final InputStream in = new FileInputStream(inputFileName);
    try {
        final OutputStream out = new FileOutputStream(outputFileName);    
        try {
            copy(in, out);
            out.flush(); // Doesn't actually do anything in this specific case.
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
} catch (IOException exc) {
    throw new SomeRelevantException(exc);
}

Rappelez-vous que l'ouverture d'un flux peut lancer une exception, si vous avez besoin d'un try entre le flux des ouvertures (merci de ne pas faire certains hack impliquant nulls. Tout peut jeter un Error (qui ne sont pas d'un cas d' Exception).

Il s'avère qu' catch et finally rarement partagent le même try.

Depuis Java SE 7, vous pouvez écrire essai d'utilisation-avec-ressource afin d'éviter beaucoup de l'indentation. Il est plus ou moins fait la même chose même si il sont supprimés, à l'exception caché.

try (
    final InputStream in = new FileInputStream(inputFileName);
    final OutputStream out = new FileOutputStream(outputFileName);    
) {
    copy(in, out);
    out.flush(); // Doesn't actually do anything in this specific case.
} catch (IOException exc) {
    throw new SomeRelevantException(exc);
}

Vous souhaiterez peut-être utiliser l' Exécuter Autour de l'idiome.

Je crois que la bonne façon de copie à l'aide de NIO est transferTo/transferFrom.

8voto

ColinD Points 48573

La goyave est très agréable IO Api qui permettent d'éliminer le besoin pour cela. Par exemple, votre exemple serait:

Files.copy(new File(inputFileName), new File(outputFileName));

Plus généralement, il utilise le concept d' InputSuppliers et OutputSuppliers pour permettre à l' InputStreams et OutputStreams être créé au sein de son utilité des méthodes, permettant un contrôle total sur eux, de sorte qu'il peut gérer la fermer correctement.

En outre, il a Closeables.closeQuietly(Closeable) qui est essentiellement le type de méthode de la plupart des réponses ont suggéré.

Les IO des choses est encore en version bêta et est sujette à changement, mais il vaut la peine de vérifier et même d'utiliser, en fonction de ce que vous travaillez sur.

5voto

Istao Points 2764

Vous avez, dans les biens communs, dans IOUtils , des méthodes très proches .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X