Sao Chép Tệp tin
(Copying Files)

Bạn có thể sao chép một tệp hoặc thư mục bằng cách sử dụng phương thức copy(Path, Path, CopyOption...). Việc sao chép sẽ thất bại nếu tệp đích đã tồn tại, trừ khi bạn chỉ định tùy chọn REPLACE_EXISTING.

Lưu ý quan trọng:

↳ Liên kết biểu tượng (Symbolic Links): Khi sao chép một liên kết biểu tượng, mục tiêu của liên kết sẽ được sao chép. Nếu bạn muốn sao chép chính liên kết thay vì nội dung mà liên kết trỏ tới, hãy chỉ định NOFOLLOW_LINKS hoặc REPLACE_EXISTING.

Phương thức này hỗ trợ các tùy chọn varargs. Các enum sau đây từ StandardCopyOption và LinkOption được hỗ trợ:

↳ REPLACE_EXISTING: Thực hiện sao chép ngay cả khi tệp đích đã tồn tại. Nếu đích là một liên kết biểu tượng, chính liên kết sẽ được sao chép thay vì nội dung mà liên kết trỏ tới. Nếu đích là một thư mục không trống, việc sao chép sẽ thất bại với ngoại lệ DirectoryNotEmptyException.

↳ COPY_ATTRIBUTES: Sao chép các thuộc tính tệp liên quan đến tệp sang tệp đích. Các thuộc tính tệp cụ thể được sao chép phụ thuộc vào hệ thống tệp và nền tảng, nhưng thời gian sửa đổi cuối cùng (last-modified-time) được hỗ trợ trên các nền tảng và sẽ được sao chép sang tệp đích.

↳ NOFOLLOW_LINKS: Chỉ định rằng các liên kết biểu tượng không nên được theo dõi. Nếu tệp được sao chép là một liên kết biểu tượng, chính liên kết sẽ được sao chép thay vì mục tiêu của liên kết.

(1) Sao chép tệp tin

Dưới đây là một ví dụ về cách sử dụng phương thức Files.copy() với các tùy chọn StandardCopyOption và LinkOption để sao chép tệp:

Ví dụ: Example.java

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class Example {
    public static void main(String[] args) {
        // Đường dẫn tới tệp nguồn
        Path sourcePath = Paths.get("path/to/source/file.txt");
        
        // Đường dẫn tới tệp đích
        Path targetPath = Paths.get("path/to/target/file.txt");

        try {
            // Sao chép tệp từ tệp nguồn đến tệp đích với các tùy chọn sau:
            // REPLACE_EXISTING: Nếu tệp đích đã tồn tại, nó sẽ bị ghi đè.
            // COPY_ATTRIBUTES: Sao chép các thuộc tính của tệp nguồn sang tệp đích.
            // NOFOLLOW_LINKS: Không theo các liên kết biểu tượng (symbolic links).
            Files.copy(sourcePath, targetPath, 
                       StandardCopyOption.REPLACE_EXISTING, 
                       StandardCopyOption.COPY_ATTRIBUTES, 
                       java.nio.file.LinkOption.NOFOLLOW_LINKS);
            
            // In ra thông báo khi sao chép thành công
            System.out.println("Đã sao chép tập tin thành công.");
        } catch (IOException e) {
            // In ra thông báo lỗi nếu có sự cố trong quá trình sao chép
            System.err.println("Sao chép tập tin thất bại: " + e.getMessage());
        }
    }
}

Kết quả của chương trình là:

Nếu tệp đích đã tồn tại, nó sẽ bị thay thế bởi tệp nguồn.
Các thuộc tính tệp từ tệp nguồn sẽ được sao chép sang tệp đích, bao gồm cả thời gian sửa đổi cuối cùng.
Nếu tệp nguồn là một liên kết biểu tượng, chỉ liên kết sẽ được sao chép chứ không phải tệp mà liên kết trỏ tới.

(2) Sao chép giữa tệp tin và luồng

↳ Sao chép từ InputStream sang tệp: Sử dụng phương thức copy(InputStream, Path, CopyOption...) để sao chép tất cả các byte từ một luồng đầu vào sang một tệp.

↳ Sao chép từ tệp sang OutputStream: Sử dụng phương thức copy(Path, OutputStream) để sao chép tất cả các byte từ một tệp sang luồng đầu ra.

Dưới đây là Ví dụ này minh họa cách sao chép tất cả các byte từ một InputStream sang một tệp đích:

Ví dụ: Example.java

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

public class Example {
    public static void main(String[] args) {
        // Đường dẫn đến tệp đích
        Path targetPath = Paths.get("path/to/target/file.txt");

        try (InputStream inputStream = new FileInputStream("path/to/source/inputfile.txt")) {
            // Sao chép tất cả các byte từ InputStream sang tệp đích
            Files.copy(inputStream, targetPath, StandardCopyOption.REPLACE_EXISTING);

            // In ra thông báo khi sao chép thành công
            System.out.println("Đã sao chép từ InputStream sang tệp thành công.");
        } catch (IOException e) {
            // In ra thông báo lỗi nếu có sự cố trong quá trình sao chép
            System.err.println("Sao chép thất bại: " + e.getMessage());
        }
    }
}

Dưới đây là ví dụ này minh họa cách sao chép tất cả các byte từ một tệp nguồn sang OutputStream:

Ví dụ: Example.java

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class Example {
    public static void main(String[] args) {
        // Đường dẫn đến tệp nguồn
        Path sourcePath = Paths.get("path/to/source/file.txt");

        try (OutputStream outputStream = new FileOutputStream("path/to/target/outputfile.txt")) {
            // Sao chép tất cả các byte từ tệp nguồn sang OutputStream
            Files.copy(sourcePath, outputStream);

            // In ra thông báo khi sao chép thành công
            System.out.println("Đã sao chép từ tệp sang OutputStream thành công.");
        } catch (IOException e) {
            // In ra thông báo lỗi nếu có sự cố trong quá trình sao chép
            System.err.println("Sao chép thất bại: " + e.getMessage());
        }
    }
}

Cả hai ví dụ đều đảm bảo rằng tài nguyên InputStream và OutputStream được đóng tự động sau khi sử dụng nhờ vào cấu trúc try-with-resources, giúp tránh các lỗi về tài nguyên bị rò rỉ.

Hy vọng rằng qua các ví dụ trên, bạn sẽ hiểu rõ hơn về cách sao chép tệp tin trong Java.

Câu Nói Truyền Cảm Hứng

“Bắt đầu ở đâu không quan trọng, quan trọng là bạn sẵn sàng bắt đầu.” – W. Clement Stone

Không Gian Tích Cực

“Chúc bạn luôn giữ vững niềm tin và sức mạnh để vượt qua mọi thử thách trong cuộc sống.”