2008-11-18 34 views

Trả lời

71

Dưới đây là làm thế nào để làm điều này với java.nio hoạt động:

public static void copyFile(File sourceFile, File destFile) throws IOException { 
    if(!destFile.exists()) { 
     destFile.createNewFile(); 
    } 

    FileChannel source = null; 
    FileChannel destination = null; 
    try { 
     source = new FileInputStream(sourceFile).getChannel(); 
     destination = new FileOutputStream(destFile).getChannel(); 

     // previous code: destination.transferFrom(source, 0, source.size()); 
     // to avoid infinite loops, should be: 
     long count = 0; 
     long size = source.size();    
     while((count += destination.transferFrom(source, count, size-count))<size); 
    } 
    finally { 
     if(source != null) { 
      source.close(); 
     } 
     if(destination != null) { 
      destination.close(); 
     } 
    } 
} 
+5

nếu tệp tồn tại, nội dung sẽ được thêm hoặc ghi đè? – Janusz

+0

@Rigo Điều này chỉ di chuyển các tệp, tôi không thể di chuyển các thư mục – Arasu

+11

Cần lưu ý rằng Java 7 có các phương pháp [copy/move] đơn giản hơn (http://docs.oracle.com/javase/tutorial/essential/io/ copy.html). – Tharwen

40

Chưa, nhưng New NIO (JSR 203) sẽ có hỗ trợ cho các hoạt động phổ biến này.

Trong thời gian chờ đợi, có một vài điều cần lưu ý.

File.renameTo thường chỉ hoạt động trên cùng một khối lượng hệ thống tệp. Tôi nghĩ về điều này tương đương với lệnh "mv". Sử dụng nó nếu bạn có thể, nhưng đối với bản sao chung và hỗ trợ di chuyển, bạn sẽ cần phải có một dự phòng.

Khi đổi tên không hoạt động, bạn sẽ cần sao chép tệp (xóa bản gốc bằng File.delete nếu đó là thao tác "di chuyển"). Để làm điều này với hiệu quả cao nhất, hãy sử dụng các phương pháp FileChannel.transferTo hoặc FileChannel.transferFrom. Việc thực hiện là nền tảng cụ thể, nhưng nói chung, khi sao chép từ một tập tin sang một tệp khác, việc triển khai tránh chuyển dữ liệu qua lại giữa nhân và không gian người dùng, mang lại hiệu quả lớn.

17

Check-out: http://commons.apache.org/io/

Nó có sao chép, và như đã nêu JDK đã có di chuyển.

Không triển khai phương thức sao chép của riêng bạn. Có rất nhiều nổi ngoài kia ...

+0

Commons IO có các giới hạn đối với kích thước tệp mà tệp có thể sao chép. Đối với một giải pháp đa năng, một triển khai mạnh mẽ hơn sẽ được mong đợi. – erickson

+3

Thực hiện phương pháp sao chép của riêng mình là tầm thường và có nghĩa là bạn sẽ không phụ thuộc vào toàn bộ thư viện. * Do * thực hiện phương thức sao chép –

+17

của riêng bạn là không đáng kể. Bạn có thể dễ dàng tạo một cái đúng không thực hiện bằng cách sử dụng Luồng và nhanh chóng nhưng không chính xác bằng cách sử dụng NIO. Không bao giờ thực hiện các tiện ích của riêng bạn khi có thư viện chất lượng ở đó. – Pyrolistical

10

câu trả lời trước dường như đã lỗi thời.

Java File.renameTo() có lẽ là giải pháp dễ nhất cho API 7 và có vẻ hoạt động tốt. Hãy cẩn thận với CNTT KHÔNG NÊN NGOẠI TRỪ, nhưng trả về true/false !!!

Lưu ý rằng có vẻ như có vấn đề với nó trong các phiên bản trước (giống như NIO).

Nếu bạn cần sử dụng phiên bản trước, hãy kiểm tra here.

Here's an example for API7: 
     File f1= new File("C:\\Users\\.....\\foo"); 
     File f2= new File("C:\\Users\\......\\foo.old"); 
     System.err.println("Result of move:"+f1.renameTo(f2)); 

Hoặc:

System.err.println("Move:" +f1.toURI() +"--->>>>"+f2.toURI()); 
    Path b1=Files.move(f1.toPath(), f2.toPath(), StandardCopyOption.ATOMIC_MOVE ,StandardCopyOption.REPLACE_EXISTING);); 
    System.err.println("Move: RETURNS:"+b1); 
+3

Nếu bạn đang nhận được "Quá trình không thể truy cập tệp vì nó đang được sử dụng bởi một quy trình khác." Quá trình không thể truy cập tệp vì nó đang được sử dụng bởi một quy trình khác. "Ngoại lệ trên đoạn mã thứ hai, hãy nhớ đóng tập tin trước khi di chuyển nó ..... – ntg

+2

Có những tình huống bất ngờ khác mà nó không thành công, ví dụ trên linux nếu bạn có hai hệ thống tập tin khác nhau được gắn dưới/mnt/a/mnt/b, bạn không thể đổi tên tập tin/mnt/a/file1 đến/mnt/b/file2, vì nó thực sự là một thao tác di chuyển, File.renameTo sẽ thất bại trong trường hợp này – xask

+1

Đây là giải pháp tốt nhất. Chỉ cần sử dụng Files.move() nếu bạn lo lắng về việc hoạt động đổi tên thất bại. – xtian

7

Cố gắng sử dụng org.apache.commons.io.FileUtils (tiện ích chung tập tin thao tác). Các phương tiện được cung cấp theo các phương pháp sau:

(1) FileUtils.moveDirectory(File srcDir, File destDir) => Di chuyển thư mục .

(2) FileUtils.moveDirectoryToDirectory(File src, File destDir, boolean createDestDir) => Di chuyển thư mục sang thư mục khác.

(3) FileUtils.moveFile(File srcFile, File destFile) => Di chuyển tệp.

(4) FileUtils.moveFileToDirectory(File srcFile, File destDir, boolean createDestDir) => Chuyển tệp vào thư mục.

(5) FileUtils.moveToDirectory(File src, File destDir, boolean createDestDir) => Di chuyển tệp hoặc thư mục đến thư mục đích .

Thật đơn giản, dễ dàng và nhanh chóng.

+0

Các hàm này có nguyên tử không? – Sumit

0

Quan sát thú vị: Cố gắng sao chép cùng một tệp thông qua các lớp java khác nhau và thời gian in bằng nano giây.

Thời gian dòng sử dụng FileOutputStream byte: 4 965 078

Thời gian sử dụng BufferedOutputStream: 1 237 206

Thời gian sử dụng (nhân vật văn bản Reader: 2 858 875

Thời gian sử dụng BufferedReader (dòng văn bản nhân vật đệm : 1 998 005

Thời lượng sử dụng (Tệp NIO sao chép): 18 351 115

w hen sử dụng tập tin Nio sao chép tùy chọn nó mất gần 18 lần lâu hơn !!! Nio là tùy chọn chậm nhất để sao chép tệp và BufferedOutputStream trông giống như nhanh nhất. Tôi đã sử dụng cùng một tệp văn bản đơn giản cho mỗi lớp.