2010-10-11 13 views
5

tiendo a escribir código como el siguiente mucho:cómo simplificar/reutilizar el código de control de excepciones

BufferedWriter w = null; // Or any other object that throws exceptions and needs to be closed 
try { 
    w = new BufferedWriter(new FileWriter(file)); 
    // Do something with w 
} catch (IOException e) { 
    e.printStackTrace(); 
} finally { 
    if (w != null) { 
     try { 
      w.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

lo general, implica un objeto que emite excepciones y necesita ser cerrado, y que cerrar también puede lanza una excepción

Me preguntaba si el código anterior se puede simplificar o reutilizar de cualquier manera.

+0

Estoy aprendiendo mucho Java gracias a esta pregunta. : D – hpique

Respuesta

5

Normalmente pongo el contenido de tu bloque finally en un helper. Al igual que esta interfaz

void close(Closeable c) { 
    if (c != null) { 
     try { 
      c.close(); 
     } catch (IOException e) { 
      // perform logging or just ignore error 
     } 
    } 
} 

Closeable es implementado por muchas clases (flujos de entrada, las conexiones de bases de datos, etc.), así que esto es un poco de ayuda de propósito general.

+0

¡Oh! Algo como Closeable es exactamente lo que estaba buscando. – hpique

0

escribirlo en un método ...

BuffereWriter getMyWriter() 
{ 

// your code.... 

return w; 
} 
4

Sí, ya que Java 1.5 hay una interfaz que se puede cerrar. Puede tener un método estático que cierre cualquier tipo de Cierre.

public static void closeIO(Closeable closeable){ 
     if (closeable != null) { 
     try { 
      closeable.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+1

O reutilizar 'Closeables' de Guava. – whiskeysierra

0

Un patrón método de la plantilla se puede aplicar aquí:

public class FileTemplate { 
    public void write(File file, WriteCallback c) { 
     BufferedWriter w = null; // Or any other object that throws exceptions and needs to be closed 
     try { 
      w = new BufferedWriter(new FileWriter(file)); 
      c.writeFile(w); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      if (w != null) { 
       try { 
        w.close(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

public interface WriteCallback { 
    public void writeFile(BufferedWriter w) throws IOException; 
} 

.

new FileTemplate().write(file, new WriteCallback() { 
    public void writeFile(BufferedWriter w) { ... } 
}); 
1

estoy de acuerdo con otros que ofrecen un método de tomar una Closeable, pero debido a maintining programas de muy larga duración, la solución que uso es un poco diferente. Básicamente se necesita OutputStream para proporcionar flexibilidad.

public class IOHandler { 

    private IOHandler(); 

    public static void close(OutputStream out, Closeable c) { 
    if (c != null) { 
     try { 
     c.close(); 
    } catch (IOException e) { 
     out.print(c.printStackTrace().getBytes()); 
    } 
    } 

} 

Las principales ventajas de esto es que se puede llamar así en una variedad de formas, eliminando la necesidad de utilidades especializadas para manejar excepciones de registro en stderr, stdout, y archivos.

IOHandler.close(System.out, openFile); 
IOHandler.close(System.err, openFile); 
IOHandler.close(logFile, openFile); 

Aparte de esta característica adicional, es básicamente la misma solución que otros han ofrecido.

3

Java 7 está intentándolo con soporte de recursos. Consulte this para obtener más información.

cito el texto relevante y un ejemplo de código aquí:

con la nueva característica del lenguaje try-con-recursos en Java 7, se declara con eficacia sus argumentos corriente como parte del try-construcción, y el el compilador genera código que administra esos recursos de manera automática y limpia para usted.

private static void customBufferStreamCopy(File source, File target) { 
    try (InputStream fis = new FileInputStream(source); 
     OutputStream fos = new FileOutputStream(target)){ 

     byte[] buf = new byte[8192]; 

     int i; 
     while ((i = fis.read(buf)) != -1) { 
      fos.write(buf, 0, i); 
     } 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

+1 más compartiendo los últimos cambios en JDK 7. –

+1

Ok, pero tal vez él no quiere esperar a mediados de 2011 para usar JDK 1.7, ¿no? – romaintaz

+0

Estoy seguro de que cualquier cliente lo entendería. : P – hpique

1

Encuentro que generalmente es mejor no intentar atrapar y finalmente todo en el mismo bloque. A menudo es mejor tener un bloque try-catch y un bloque try-finally separado.

try { 
    BufferedWriter w = new BufferedWriter(new FileWriter(file)); // Or any other object that throws exceptions and needs to be closed 
    try { 
     // Do something with w 
    } finally { 
     w.close(); 
    } 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

Esto también evita la necesidad de anular la comprobación w.

+0

Obtendrá problemas cuando aún se creen flujos subyacentes, pero los flujos externos lanzan una excepción en el constructor. Entonces las transmisiones subyacentes no están cerradas. –

+0

@Fatal 'new BufferedWriter (Writer)' no arroja ninguna excepción marcada. Incluso si lo hizo, el problema existe en la llamada 'new BufferedWriter (new FileWriter (file))' como se describe en la pregunta, no por este método de manejar la excepción. Para mitigar, debe asignar el 'nuevo FileWriter' a una variable separada y cerrarlo también. – ILMTitan

+0

Tiene razón con BufferedWriter, pero este tema aquí es más general y su consejo es muy general también. No tiene que asignar y cerrar FileWriter por separado, debido al contrato 'close()'. hgpc lo está haciendo bien en su primer post. Y así es como se hace en todas las bibliotecas comunes como Apache Commons, lo sé, y no por casualidad. Entonces, la respuesta aceptada es la mejor: simplemente mejora la forma de hacerlo bien y reduce los estándares. Esto aquí no es nada que recomendaría, incluso cuando podría funcionar en este caso especial aquí. –

6

Si no desea escribir código para cerrar finalmente en bloque, usted debe echar un vistazo a Project Lombok

En lugar de escribir la normalidad

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    InputStream in = new FileInputStream(args[0]); 
    try { 
    OutputStream out = new FileOutputStream(args[1]); 
    try { 
     byte[] b = new byte[10000]; 
     while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
     } 
    } finally { 
     out.close(); 
     } 
    } finally { 
    in.close(); 
    } 
    } 
} 

Con Lombok se puede escribir

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    @Cleanup InputStream in = new FileInputStream(args[0]); 
    @Cleanup OutputStream out = new FileOutputStream(args[1]); 
    byte[] b = new byte[10000]; 
    while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
    } 
    } 
} 

Mucho más legible, y genera la forma correcta de cerrar el flujo. Esto funciona con todas las interfaces Closeable

+2

+1 para la introducción de lambok (a mí) – chedine

+0

Lombok is ideal para el código repetitivo –

Cuestiones relacionadas