2011-01-12 11 views
5

Tengo el código para copiar un archivo a otra ubicación.Error con NIO al intentar copiar un archivo grande

public static void copyFile(String sourceDest, String newDest) throws IOException { 

    File sourceFile = new File(sourceDest); 
    File destFile = new File(newDest); 
    if (!destFile.exists()) { 
     destFile.createNewFile(); 
    } 

    FileChannel source = null; 
    FileChannel destination = null; 
    try { 
     source = new FileInputStream(sourceFile).getChannel(); 
     destination = new FileOutputStream(destFile).getChannel(); 
     destination.transferFrom(source, 0, source.size()); 
    } finally { 
     if (source != null) { 
      source.close(); 
     } 
     if (destination != null) { 
      destination.close(); 
     } 
    } 

} 
} 

Durante la copia de pequeños trozos, por ejemplo, 300-400 Mb, todo funciona como magia. Pero cuando intenté copiar un archivo de un tamaño de 1.5 Gb, falló. La pila es:

run: 12.01.2011 11:16:36 FileCopier main SEVERE: Exception occured while copying file. Try again. java.io.IOException: Map failed at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:748) at sun.nio.ch.FileChannelImpl.transferFromFileChannel(FileChannelImpl.java:527) at sun.nio.ch.FileChannelImpl.transferFrom(FileChannelImpl.java:590) at FileCopier.copyFile(FileCopier.java:64) at FileCopier.main(FileCopier.java:27) Caused by: java.lang.OutOfMemoryError: Map failed at sun.nio.ch.FileChannelImpl.map0(Native Method) at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:745) ... 4 more BUILD SUCCESSFUL (total time: 0 seconds)

No he trabajado estrechamente con NIO. ¿Podrías por favor ayudarme? Muchas gracias de antemano.

+0

Pruebe con Files.copy http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/io/Files.html si funciona tiene un aspecto en el src – oluies

+0

Gracias. Pero prefiero no utilizar bibliotecas de terceros en este caso específico. –

Respuesta

5

Creo que puede haber sido golpeado por un old bug que ya se encontró hace algún tiempo. No intenté copiar un archivo, sino buscar un archivo mapeado en memoria que también falló. Para mí, la solución consiste en buscar a través del archivo en un bucle y solicitar que GC y finalizers se ejecuten de vez en cuando.

La memoria asignada ByteBuffers libera su asignación en el finalizador y deja espacio para nuevas asignaciones. Esto es muy feo, pero al menos funciona. Esperemos que hayan hecho algo al respecto en la próxima iteración de NIO.

+1

Encontré una solución. Gracias por la visión de usted. http://snippets.dzone.com/posts/show/4946 –

+0

Sí, en realidad han resuelto el error en JRE 1.7 (lo registré en 1.7.0_51) –

2

Está mapeando la memoria de un archivo, pero hay espacio de direcciones de memoria limitado en una JVM de 32 bits (que supongo que está utilizando) por lo que el método de mapa está fallando. No creo que pueda mapear más de 1.3-1.4 GB de datos de disco. ¿Qué tamaño de pila estás usando?

Puede intentar reducir su tamaño de pila o utilizar un JRE de 64 bits. Alternativamente, no lea el archivo asignándolo a la memoria usando NIO. En su lugar, utilice la forma tradicional de un lector y escritor de almacenamiento intermedio para leer y escribir datos de un archivo a otro.

+0

Gracias, decidí seguir con NIO, solo con un enfoque iterativo con un buffer de un tamaño de 64 Mb. –

Cuestiones relacionadas