2011-01-12 6 views
5

Tôi có mã để sao chép tệp sang vị trí khác.Lỗi với NIO khi cố gắng sao chép tệp lớn

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(); 
     } 
    } 

} 
} 

Trong khi sao chép khối nhỏ, giả sử, 300-400 Mb, mọi thứ hoạt động như ma thuật. Nhưng khi tôi cố gắng sao chép một tệp có kích thước 1,5 Gb thì không thành công. Ngăn xếp là:

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)

Tôi chưa làm việc với NIO chặt chẽ. Ông có thể giúp tôi không? Cảm ơn trước.

+0

Hãy thử với Files.copy http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/io/Files.html nếu nó hoạt động có một cái nhìn xem trong src – oluies

+0

Cảm ơn bạn. Nhưng tôi không muốn sử dụng thư viện của bên thứ ba trong trường hợp cụ thể này. –

Trả lời

5

Tôi nghĩ rằng bạn có thể đã bị ảnh hưởng bởi một số old bug đã gặp phải một số thời gian trước đây. Tôi đã không cố gắng để sao chép một tập tin mà là để tìm kiếm thông qua một tập tin ánh xạ bộ nhớ mà không thành công là tốt. Đối với tôi, giải pháp thay thế là tìm kiếm thông qua tệp trong vòng lặp và yêu cầu GCfinalizers để chạy mọi lúc.

Ánh xạ bộ nhớ ByteBuffers phát hành ánh xạ của chúng trong trình hoàn thiện và nhường chỗ cho ánh xạ mới. Điều này rất xấu, nhưng ít nhất nó hoạt động. Hãy hy vọng họ đã làm điều gì đó về điều này trong lần lặp lại NIO sắp tới.

+1

Tôi tìm thấy một giải pháp. Cảm ơn sự sáng suốt của bạn. http://snippets.dzone.com/posts/show/4946 –

+0

Có, Thực ra họ đã giải quyết lỗi trong JRE 1.7 (Tôi đã kiểm tra trong 1.7.0_51) –

2

Bạn đang ánh xạ bộ nhớ tệp nhưng có không gian địa chỉ bộ nhớ giới hạn trong một JVM 32 bit (mà tôi đoán bạn đang sử dụng) để phương thức ánh xạ không thành công. Tôi không nghĩ rằng bạn có thể lập bản đồ hơn 1,3-1,4 GB dữ liệu đĩa. Bạn đang sử dụng kích thước heap nào?

Bạn có thể thử giảm kích thước heap của mình hoặc sử dụng JRE 64 bit. Ngoài ra, không đọc tệp bằng cách ánh xạ nó vào bộ nhớ bằng NIO. Thay vào đó, hãy sử dụng cách thức truyền thống của trình đọc và người viết được đệm để đọc và ghi dữ liệu từ tệp này sang tệp khác.

+0

Cảm ơn bạn, tôi đã quyết định gắn bó với NIO, chỉ cần sử dụng phương pháp lặp lại với bộ đệm có kích thước 64 Mb. –