Cách xóa thư mục chứa tệp bằng Java


104

Tôi muốn tạo và xóa một thư mục bằng Java, nhưng nó không hoạt động.

File index = new File("/home/Work/Indexer1");
if (!index.exists()) {
    index.mkdir();
} else {
    index.delete();
    if (!index.exists()) {
        index.mkdir();
    }
}

3
Điều gì đã xảy ra khi bạn cố gắng?
Abimaran Kugathasan

Câu hỏi là gì?
Aniket Thakur

1
tập tin chỉ mục không bị xóa.
Mr.G


1
Thật không may, @AniketThakur, cách tiếp cận đó sẽ đi theo các liên kết tượng trưng và xóa các tệp và thư mục có thể không được dự kiến.
Hank Schultz

Câu trả lời:


99

Java không thể xóa các thư mục có dữ liệu trong đó. Bạn phải xóa tất cả các tệp trước khi xóa thư mục.

Sử dụng một cái gì đó như:

String[]entries = index.list();
for(String s: entries){
    File currentFile = new File(index.getPath(),s);
    currentFile.delete();
}

Sau đó, bạn sẽ có thể xóa thư mục bằng cách sử dụng index.delete() Untested!


37
Thao tác này sẽ không xóa các thư mục con không trống.
Francesco Menzani

13
bạn phải viết một phương thức đệ quy hoặc sử dụng FileUtils.deleteDirectorynhư @Franceco Menzani đã nói.
EN20

4
Hãy RẤT cẩn thận. Nếu chỉ mục là một liên kết tượng trưng đến một thư mục khác, bạn sẽ kết thúc việc xóa nội dung của thư mục khác. Thật không may, tôi vẫn chưa tìm ra cách tốt để phát hiện các liên kết tượng trưng trên Windows trong Java 6, mặc dù Java 7 cung cấp Files.isSymbolicLink ().
Hank Schultz

1
Giải pháp: bọc đoạn mã này vào if (!index.delete()) {...}. Sau đó, nếu chỉ mục là một liên kết tượng trưng, ​​nó sẽ bị xóa bất kể nó xuất hiện có nội dung hay không.
Hank Schultz

Điều này sẽ ném ra một NullPointerException nếu có một ngoại lệ I / O trong khi đọc thư mục. Mã sẽ kiểm tra xem có phải entrieslà null hay không.
mernst

178

Chỉ là một lớp lót.

import org.apache.commons.io.FileUtils;

FileUtils.deleteDirectory(new File(destination));

Tài liệu tại đây



13
À, không. Đây là một lớp lót với sự phụ thuộc bên ngoài, đó là một điều quan trọng cần ghi nhớ. Lần duy nhất sử dụng phụ thuộc bên ngoài như thế này đơn giản là khi bạn đang thực hiện một dự án nhà cá nhân, hoặc công ty của bạn thực sự không quan tâm đến khả năng bị kiện.
searchhengine27

11
@ searchhengine27 nhưng có vẻ như thư viện thuộc Apache Commons nên nguy cơ bị kiện là không đáng kể whitesourcesoftware.com/whitesource-blog/… .
simtim

1
@simtim, bạn hoàn toàn thiếu điểm. Một công ty sẽ không bao giờ chấp thuận cho thư viện sử dụng mà không có đội ngũ luật sư thông qua các điều khoản sử dụng và thỏa thuận người dùng cuối, và bất kỳ tài liệu pháp lý nào khác liên quan đến thư viện trước. Ai đó phải trả tiền cho những luật sư đó ... đôi khi không ai muốn, có nghĩa là nhà phát triển không được sử dụng nó. Bạn làm việc cho công ty càng lớn, bạn càng phải trải qua nhiều băng đỏ hơn.
searchhengine27

19
@ searchhengine27 không, bạn hoàn toàn thiếu điểm. Một công ty cần một đội quân luật sư để cho phép sử dụng apache commons là một bệnh lý tuyệt đối và không có gì gần với tiêu chuẩn trong thế giới CNTT. Tôi chưa bao giờ nghe nói về bất kỳ ai gặp vấn đề như vậy và nếu bạn gặp vấn đề như vậy, rất có thể bạn đã bị chặn quyền truy cập vào SO nên dù sao bạn cũng không thể truy cập được câu trả lời.
9ilsdx 9rvj 0lo

94

Điều này hoạt động và mặc dù có vẻ không hiệu quả nếu bỏ qua kiểm tra thư mục, nhưng không phải vậy: kiểm tra diễn ra ngay lập tức trong listFiles().

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            deleteDir(f);
        }
    }
    file.delete();
}

Cập nhật, để tránh các liên kết tượng trưng sau:

void deleteDir(File file) {
    File[] contents = file.listFiles();
    if (contents != null) {
        for (File f : contents) {
            if (! Files.isSymbolicLink(f.toPath())) {
                deleteDir(f);
            }
        }
    }
    file.delete();
}

2
Hóa ra, có một lỗi trong việc này. Nếu một quá trình khác xóa các tệp trong vòng lặp, nó có thể gây ra một ngoại lệ cần được bắt và bỏ qua.
Jeff Learman

2
@ 9ilsdx9rvj0lo Thay vì khó xử, có lẽ bạn có thể cung cấp một chỉnh sửa để xử lý các liên kết tượng trưng. OP không nói về các liên kết tượng trưng trong bài đăng của mình. Chỉ cần tạo và xóa một thư mục. Hãy cũng liệt kê ra "nhiều thứ còn thiếu". Giúp chúng tôi ra.
Perry Tew

@PerryTew Tôi không cáu kỉnh đâu. Tôi chỉ chỉ ra rằng tôi hoàn toàn không đồng ý với nhận xét của bạn về việc câu trả lời sẽ tốt hơn vì không có thư viện bên ngoài nào được sử dụng. Không phải vậy. Có một lý do chính đáng mà mọi người đang sử dụng apache commons: bạn không phải tự mình lập trình bất kỳ thứ nào. Các liên kết tượng trưng chỉ là một ví dụ về những thứ bạn sẽ bỏ lỡ khi viết mọi thứ từ đầu.
9ilsdx 9rvj 0lo

2
Đó không phải là vấn đề tốt hơn / xấu hơn, mà là ưu và nhược điểm. Không phụ thuộc vào các thư viện bên ngoài đôi khi là một lợi ích đáng kể. Tất nhiên, có một lợi ích đáng kể khi sử dụng phần mềm đã thử và đúng. Nhà phát triển phải cân bằng các vấn đề. Nếu có lỗi khác ngoài hai lỗi đã được đề cập, chúng tôi chắc chắn muốn biết về chúng.
Jeff Learman

31

Tôi thích giải pháp này trên java 8:

  Files.walk(pathToBeDeleted)
    .sorted(Comparator.reverseOrder())
    .map(Path::toFile)
    .forEach(File::delete);

Từ trang web này: http://www.baeldung.com/java-delete-directory


2
Lưu ý rằng điều này có thể có các vấn đề về khả năng mở rộng vì nó xây dựng danh sách đầy đủ, tạo một bản sao được sắp xếp và sau đó lặp lại bản sao được sắp xếp. Quay lại những ngày xưa tồi tệ khi trí nhớ không cạn kiệt, đây sẽ là một ý tưởng rất tồi. Nó ngắn gọn nhưng có chi phí trong không gian (O (N) so với O (1)) và hiệu quả (O (N log N) so với O (N)). Điều này sẽ không thành vấn đề trong hầu hết các trường hợp sử dụng.
Jeff Learman

Lẽ ra tôi nên nói "không gian O (N) vs O (chiều sâu)" ở trên, nơi sâu là chiều sâu của cây thư mục (so sánh giải pháp này cho những người đệ quy.)
Jeff Learman

1
cái này thanh lịch, hoạt động và không dựa vào các thư viện bên ngoài. yêu nó
Leo

Điều này không có vấn đề rò rỉ xử lý tệp? Ví dụ này không đóng luồng được trả về Files.walk(), được chỉ ra rõ ràng trong tài liệu API. Tôi biết rằng nếu bạn không đóng luồng được trả lại bởi Files.list()ví dụ, bạn có thể hết khả năng xử lý và chương trình sẽ sập. Xem ví dụ: stackoverflow.com/q/36990053/421049stackoverflow.com/q/26997240/421049 .
Garret Wilson


23

Sử dụng Apache Commons-IO, nó đang theo sau một lớp lót:

import org.apache.commons.io.FileUtils;

FileUtils.forceDelete(new File(destination));

Đây là (một chút) hiệu suất hơn FileUtils.deleteDirectory.


nhóm: 'commons-io', và tên: 'commons-io', phiên bản: '2. +' - hữu ích
mike động vật gặm nhấm

10

Như đã đề cập, Java không thể xóa một thư mục chứa tệp, vì vậy trước tiên hãy xóa các tệp và sau đó là thư mục.

Đây là một ví dụ đơn giản để làm điều này:

import org.apache.commons.io.FileUtils;



// First, remove files from into the folder 
FileUtils.cleanDirectory(folder/path);

// Then, remove the folder
FileUtils.deleteDirectory(folder/path);

Hoặc là:

FileUtils.forceDelete(new File(destination));

9

Phiên bản đệ quy cơ bản của tôi, hoạt động với các phiên bản cũ hơn của JDK:

public static void deleteFile(File element) {
    if (element.isDirectory()) {
        for (File sub : element.listFiles()) {
            deleteFile(sub);
        }
    }
    element.delete();
}

2
Điều này sẽ ném ra một NullPointerException nếu có một ngoại lệ I / O trong khi đọc thư mục. Mã nên kiểm tra xem có listFiles()trả về null hay không, thay vì gọi isDirectory().
mernst

9

Đây là giải pháp tốt nhất cho Java 7+:

public static void deleteDirectory(String directoryFilePath) throws IOException
{
    Path directory = Paths.get(directoryFilePath);

    if (Files.exists(directory))
    {
        Files.walkFileTree(directory, new SimpleFileVisitor<Path>()
        {
            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException
            {
                Files.delete(path);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path directory, IOException ioException) throws IOException
            {
                Files.delete(directory);
                return FileVisitResult.CONTINUE;
            }
        });
    }
}

6

Ổi 21+ để giải cứu. Chỉ sử dụng nếu không có liên kết tượng trưng nào trỏ ra khỏi thư mục để xóa.

com.google.common.io.MoreFiles.deleteRecursively(
      file.toPath(),
      RecursiveDeleteOption.ALLOW_INSECURE
) ;

(Câu hỏi này đã được Google lập chỉ mục tốt, vì vậy những người khác sử dụng Guava có thể rất vui khi tìm thấy câu trả lời này, ngay cả khi nó là thừa với các câu trả lời khác ở nơi khác.)


4

Tôi thích giải pháp này nhất. Nó không sử dụng thư viện của bên thứ 3, thay vào đó nó sử dụng NIO2 của Java 7.

/**
 * Deletes Folder with all of its content
 *
 * @param folder path to folder which should be deleted
 */
public static void deleteFolderAndItsContent(final Path folder) throws IOException {
    Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            Files.delete(file);
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            if (exc != null) {
                throw exc;
            }
            Files.delete(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}

3

Một lựa chọn nữa là sử dụng org.springframework.util.FileSystemUtilsphương pháp có liên quan của Spring sẽ xóa một cách đệ quy tất cả nội dung của thư mục.

File directoryToDelete = new File(<your_directory_path_to_delete>);
FileSystemUtils.deleteRecursively(directoryToDelete);

Điều đó sẽ thực hiện công việc!


2

Trong này

index.delete();

            if (!index.exists())
               {
                   index.mkdir();
               }

bạn đang gọi

 if (!index.exists())
                   {
                       index.mkdir();
                   }

sau

index.delete();

Đây có nghĩa là bạn đang tạo ra các tập tin một lần nữa sau khi xóa File.Delete () trả về một value.So boolean nếu bạn muốn kiểm tra sau đó làm System.out.println(index.delete());nếu bạn nhận được truesau đó phương tiện này mà tập tin bị xóa

File index = new File("/home/Work/Indexer1");
    if (!index.exists())
       {
             index.mkdir();
       }
    else{
            System.out.println(index.delete());//If you get true then file is deleted




            if (!index.exists())
               {
                   index.mkdir();// here you are creating again after deleting the file
               }




        }

từ các bình luận đưa ra bên dưới, câu trả lời được cập nhật như thế này

File f=new File("full_path");//full path like c:/home/ri
    if(f.exists())
    {
        f.delete();
    }
    else
    {
        try {
            //f.createNewFile();//this will create a file
            f.mkdir();//this create a folder
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

2

Nếu bạn có các thư mục con, bạn sẽ thấy rắc rối với các câu trả lời Cemron. vì vậy bạn nên tạo một phương thức hoạt động như sau:

private void deleteTempFile(File tempFile) {
        try
        {
            if(tempFile.isDirectory()){
               File[] entries = tempFile.listFiles();
               for(File currentFile: entries){
                   deleteTempFile(currentFile);
               }
               tempFile.delete();
            }else{
               tempFile.delete();
            }
        getLogger().info("DELETED Temporal File: " + tempFile.getPath());
        }
        catch(Throwable t)
        {
            getLogger().error("Could not DELETE file: " + tempFile.getPath(), t);
        }
    }

2

Bạn có thể sử dụng FileUtils.deleteDirectory . JAVA không thể xóa các màn hình đầu tiên không trống bằng File.delete () .


1

directry không thể xóa đơn giản nếu nó có các tệp, vì vậy bạn có thể cần phải xóa các tệp bên trong trước và sau đó là thư mục

public class DeleteFileFolder {

public DeleteFileFolder(String path) {

    File file = new File(path);
    if(file.exists())
    {
        do{
            delete(file);
        }while(file.exists());
    }else
    {
        System.out.println("File or Folder not found : "+path);
    }

}
private void delete(File file)
{
    if(file.isDirectory())
    {
        String fileList[] = file.list();
        if(fileList.length == 0)
        {
            System.out.println("Deleting Directory : "+file.getPath());
            file.delete();
        }else
        {
            int size = fileList.length;
            for(int i = 0 ; i < size ; i++)
            {
                String fileName = fileList[i];
                System.out.println("File path : "+file.getPath()+" and name :"+fileName);
                String fullPath = file.getPath()+"/"+fileName;
                File fileOrFolder = new File(fullPath);
                System.out.println("Full Path :"+fileOrFolder.getPath());
                delete(fileOrFolder);
            }
        }
    }else
    {
        System.out.println("Deleting file : "+file.getPath());
        file.delete();
    }
}

1

Bạn có thể thực hiện cuộc gọi đệ quy nếu tồn tại các thư mục con

import java.io.File;

class DeleteDir {
public static void main(String args[]) {
deleteDirectory(new File(args[0]));
}

static public boolean deleteDirectory(File path) {
if( path.exists() ) {
  File[] files = path.listFiles();
  for(int i=0; i<files.length; i++) {
     if(files[i].isDirectory()) {
       deleteDirectory(files[i]);
     }
     else {
       files[i].delete();
     }
  }
}
return( path.delete() );
}
}

1

chúng ta có thể sử dụng spring-corephụ thuộc;

boolean result = FileSystemUtils.deleteRecursively(file);

1

Hầu hết các câu trả lời (thậm chí gần đây) tham chiếu đến các lớp JDK đều dựa vào File.delete()nhưng đó là một API thiếu sót vì hoạt động có thể không thành công.
Các java.io.File.delete()tiểu bang tài liệu hướng dẫn phương pháp:

Lưu ý rằng java.nio.file.Fileslớp định nghĩa deletephương thức ném IOExceptionmột tệp khi không thể xóa tệp. Điều này rất hữu ích cho việc báo cáo lỗi và chẩn đoán lý do tại sao không thể xóa tệp.

Để thay thế, bạn nên ưu tiên Files.delete(Path p) ném một IOExceptionthông báo lỗi.

Mã thực tế có thể được viết như:

Path index = Paths.get("/home/Work/Indexer1");

if (!Files.exists(index)) {
    index = Files.createDirectories(index);
} else {

    Files.walk(index)
         .sorted(Comparator.reverseOrder())  // as the file tree is traversed depth-first and that deleted dirs have to be empty  
         .forEach(t -> {
             try {
                 Files.delete(t);
             } catch (IOException e) {
                 // LOG the exception and potentially stop the processing

             }
         });
    if (!Files.exists(index)) {
        index = Files.createDirectories(index);
    }
}

0

bạn có thể thử như sau

  File dir = new File("path");
   if (dir.isDirectory())
   {
         dir.delete();
   }

Nếu có các thư mục con bên trong thư mục của bạn, bạn có thể cần phải xóa chúng một cách đệ quy.


0
private void deleteFileOrFolder(File file){
    try {
        for (File f : file.listFiles()) {
            f.delete();
            deleteFileOrFolder(f);
        }
    } catch (Exception e) {
        e.printStackTrace(System.err);
    }
}

0
        import org.apache.commons.io.FileUtils;

        List<String> directory =  new ArrayList(); 
        directory.add("test-output"); 
        directory.add("Reports/executions"); 
        directory.add("Reports/index.html"); 
        directory.add("Reports/report.properties"); 
        for(int count = 0 ; count < directory.size() ; count ++)
        {
        String destination = directory.get(count);
        deleteDirectory(destination);
        }





      public void deleteDirectory(String path) {

        File file  = new File(path);
        if(file.isDirectory()){
             System.out.println("Deleting Directory :" + path);
            try {
                FileUtils.deleteDirectory(new File(path)); //deletes the whole folder
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        else {
        System.out.println("Deleting File :" + path);
            //it is a simple file. Proceed for deletion
            file.delete();
        }

    }

Hoạt động như một sự quyến rũ. Đối với cả thư mục và tệp. Salam :)


-1

Xóa nó khỏi phần khác

File index = new File("/home/Work/Indexer1");
if (!index.exists())
{
     index.mkdir();
     System.out.println("Dir Not present. Creating new one!");
}
index.delete();
System.out.println("File deleted successfully");

-1

Một số câu trả lời trong số này có vẻ dài không cần thiết:

if (directory.exists()) {
    for (File file : directory.listFiles()) {
        file.delete();
    }
    directory.delete();
}

Hoạt động cho các thư mục con quá.


-3

Bạn có thể sử dụng chức năng này

public void delete()    
{   
    File f = new File("E://implementation1/");
    File[] files = f.listFiles();
    for (File file : files) {
        file.delete();
    }
}

Nó hoạt động tốt với một thư mục có tất cả các tệp đã đóng. Nhưng khi thử trên thư mục với các tệp đang mở, nó không hoạt động. Bạn có thể giúp tôi tìm một cách để xóa thư mục Mặc dù có các tập tin mở
Piyush Rumao

2
Thao tác này sẽ không xóa các thư mục con không trống.
Pang
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.