Bir klasörün ve içeriğin tamamı nasıl silinir?


187

Uygulamamın kullanıcılarının (SD kartta bulunan ve alt klasörler içeren) DCIM klasörünü silebilmesini istiyorum.

Bu mümkün mü, eğer öyleyse nasıl?


1
tekrarlayan aşağıdan yukarıya silme yaklaşımından başka?
Sarwar Erfan

Çok büyük veya karmaşık bir dizininiz varsa rm -rf directorybunun yerine kullanmalısınız FileUtils.deleteDirectory. Kıyaslamadan sonra birden çok kez daha hızlı olduğunu gördük. Burada örnek bir uygulamaya göz atın: stackoverflow.com/a/58421350/293280
Joshua Pinter

Yanıtlar:


301

Öncelikle bir sistem klasörü olduğu için DCIM klasörünü silemeyeceğinizi söyleyeyim. Telefonda manuel olarak sildiğinizde, o klasörün içeriğini siler, ancak DCIM klasörünü silmez. Aşağıdaki yöntemi kullanarak içeriğini silebilirsiniz:

Güncel Yorumlar başı olarak

File dir = new File(Environment.getExternalStorageDirectory()+"Dir_name_here"); 
if (dir.isDirectory()) 
{
    String[] children = dir.list();
    for (int i = 0; i < children.length; i++)
    {
       new File(dir, children[i]).delete();
    }
}

3
erm nasıl dir olduğunu nasıl ilan edebilirim?
Başlangıç

im temelde DCIM olduğu sürece tüm fotoğrafları silmeye çalışıyorum, fotoğraf olduğu sürece silinmez ... bu yüzden 100MEDIA'yı silmek bile bu klasördeki işi yapar
Başlangıç

1
dicm klasörünün yolunu kullanarak dizin bildirmeniz gerekir: use file r = file (path);
chikka.anddev

3
kullanılan Dosya dir = new File (Environment.getExternalStorageDirectory () + "/ DCIM / 100MEDIA");
Acemi

1
@chiragshah Bir klasörü sildikten ve belirtilen klasör adıyla bilinmeyen bir dosyanın oluşturulmasına neden olan klasörü yeniden oluşturduktan sonra ve bu dosyaya erişmeye çalışıyorsam Kaynak veya cihaz meşgul gibi bir istisna atıyor . MD5 imzasını
sha

529

Dosya ve klasörleri özyineli olarak şu şekilde silebilirsiniz:

void deleteRecursive(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory())
        for (File child : fileOrDirectory.listFiles())
            deleteRecursive(child);

    fileOrDirectory.delete();
}

21
Verimlilik için hiçbir test yapmadım, ama benimkinin daha sağlam olduğuna inanıyorum. chirag'lar, DCIM içindeki klasörlerin yalnızca dosya içermesi gereken DCIM klasörünün özel durumu için çalışır (örn. DCIM içindeki klasörler normalde alt klasör içermez). Sürümüm, herhangi bir derinliğe yerleştirilmiş klasörleri silecektir. Kullanıcının SD kartının içeriğini değiştirmesi ihtimali vardır, böylece DCIM daha derin yuvalanmış klasörler içerir (örneğin DCIM\foo\bar\pic.jpg), bu durumda chirag'ın kodu başarısız olur.
teedyay

2
Bir meslektaşımın sorduğu bir soru: Bir klasörde sembolik bir bağlantı varsa ve bu kod yığınını yürütürseniz ne olur?
p4u144

1
@ p4u144 Meslektaşınıza dahi olmak için bir beşlik verin! İyi tespit! Dürüst olmak gerekirse, bu kodun sembolik bağlantılara uyup uymayacağını bilmiyorum, ama eğer yaparsa sonsuz bir döngüye sahip olacaksınız. Test etmeyi seviyor musunuz?
teedyay

8
@ p4u144 Sembolik bağlantılar hakkında endişelenme. "Sembolik bağlarla bağlantının hedefi silinmez, bağ silinir." from docs.oracle.com/javase/tutorial/essential/io/delete.html
corbin

3
Burada olası bir NPE var: dosyaları okurken G / Ç hatası varsa fileOrDirectory.listFiles()dönebilir null. Bu belgelerde açıkça belirtilmiştir: developer.android.com/reference/java/io/File.html#listFiles ()
Brian Yencho

67

Tüm klasörü ve içeriğini silmek için komut satırı bağımsız değişkenlerini kullanabiliriz.

public static void deleteFiles(String path) {

    File file = new File(path);

    if (file.exists()) {
        String deleteCmd = "rm -r " + path;
        Runtime runtime = Runtime.getRuntime();
        try {
            runtime.exec(deleteCmd);
        } catch (IOException e) { }
    }
}

Yukarıdaki kodun örnek kullanımı:

deleteFiles("/sdcard/uploads/");

2
iyi görünüyor, bunun senkron veya asenkron olduğunu biliyor musunuz? Belgeler şunu söylemez: developer.android.com/reference/java/lang/…
Birisi

2
Kötü bir fikir. Neden kabukta?
noamtm


34

Kotlin'de paketin deleteRecursively()uzantısını kullanabilirsinizkotlin.io

val someDir = File("/path/to/dir")
someDir.deleteRecursively()

2
Java ile FilesKt.deleteRecursively(new File("/path/to/dir"));kotlin-stdlib kullanıyorsanız kullanabilirsiniz
Joonsoo

Bu komut, "/ dir" dizinini içerideki içerikle veya yalnızca "/ dir" dizinindeki içerikle silecek ve dizin orada kalacak mı?
Bhimbim

1
@Bhimbim lemme google docs sizin için "Bu dosyayı tüm çocuklarıyla sil." Böylece, dizin yanı sıra içerik silinecek
Dima Rostopira

Teşekkürler @DimaRostopira!.
Bhimbim

kurtarmaya kotlin!
Tobi Oyelekan

15

dosyaları ve alt dizini içeren tüm ana dizini silmek için aşağıdaki yöntemi kullanın. Bu yöntemi çağırdıktan sonra bir kez daha ana dizininizin delete () dizinini çağırın.

// For to Delete the directory inside list of files and inner Directory
public static boolean deleteDir(File dir) {
    if (dir.isDirectory()) {
        String[] children = dir.list();
        for (int i=0; i<children.length; i++) {
            boolean success = deleteDir(new File(dir, children[i]));
            if (!success) {
                return false;
            }
        }
    }

    // The directory is now empty so delete it
    return dir.delete();
}

Tüm cevapların dışında, bu, içindeki dosyaları sildikten sonra dizini de silen SADECE gerçek cevaptır.
zeeshan

Dosya dosyası = yeni Dosya (Environment.getExternalStorageDirectory () + ayırıcı + "klasör_adı" + ayırıcı); deleteDir (dosya); Evet bu işe yarıyor. Teşekkürler :)
ashishdhiman2007

14

Yaklaşımınız yalnızca dosya içeren bir klasör için uygundur, ancak alt klasörler de içeren bir senaryo arıyorsanız özyineleme gerekir

Ayrıca, dosyayı silmenize izin verildiğinden emin olmak için dönüşün dönüş değerini yakalamanız gerekir.

ve dahil et

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

manifestinizde

void DeleteRecursive(File dir)
{
    Log.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
    if (dir.isDirectory())
    {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++)
        {
            File temp = new File(dir, children[i]);
            if (temp.isDirectory())
            {
                Log.d("DeleteRecursive", "Recursive Call" + temp.getPath());
                DeleteRecursive(temp);
            }
            else
            {
                Log.d("DeleteRecursive", "Delete File" + temp.getPath());
                boolean b = temp.delete();
                if (b == false)
                {
                    Log.d("DeleteRecursive", "DELETE FAIL");
                }
            }
        }

    }
    dir.delete();
}

5
(File currentFile: file.listFiles ()) {
Thorben

8

Çok fazla cevap var, ama kendiminkini eklemeye karar verdim, çünkü bu biraz farklı. OOP;) dayanmaktadır

Her dizini temizlemem gerektiğinde bana yardımcı olan DirectoryCleaner sınıfını oluşturdum .

public class DirectoryCleaner {
    private final File mFile;

    public DirectoryCleaner(File file) {
        mFile = file;
    }

    public void clean() {
        if (null == mFile || !mFile.exists() || !mFile.isDirectory()) return;
        for (File file : mFile.listFiles()) {
            delete(file);
        }
    }

    private void delete(File file) {
        if (file.isDirectory()) {
            for (File child : file.listFiles()) {
                delete(child);
            }
        }
        file.delete();

    }
}

Bu sorunu bir sonraki şekilde çözmek için kullanılabilir:

File dir = new File(Environment.getExternalStorageDirectory(), "your_directory_name");
new DirectoryCleaner(dir).clean();
dir.delete();

7

Bir şeyi tekrar tekrar silmeniz gerekmiyorsa, şöyle bir şey deneyebilirsiniz:

File file = new File(context.getExternalFilesDir(null), "");
    if (file != null && file.isDirectory()) {
        File[] files = file.listFiles();
        if(files != null) {
            for(File f : files) {   
                f.delete();
            }
        }
    }

6

Java'da alt dizinleri veya dosyaları varsa dizini silemezsiniz. Bu iki satırlık basit çözümü deneyin. Bu, dizini ve dizinin içindeki yarışmaları silecektir.

File dirName = new File("directory path");
FileUtils.deleteDirectory(dirName);

Bu satırı not dosyasına ekleyin ve projeyi senkronize edin

compile 'org.apache.commons:commons-io:1.3.2'  

2 astar olarak, basit. Ancak yöntemlerinden sadece birini kullanmak için tüm bir kütüphaneyi kurmak verimsiz görünüyor. Kullan bu yerine
Kesir

kepçe ekleme ucu hayatımı kurtardı.
Dracarys

5
public static void deleteDirectory( File dir )
{

    if ( dir.isDirectory() )
    {
        String [] children = dir.list();
        for ( int i = 0 ; i < children.length ; i ++ )
        {
         File child =    new File( dir , children[i] );
         if(child.isDirectory()){
             deleteDirectory( child );
             child.delete();
         }else{
             child.delete();

         }
        }
        dir.delete();
    }
}


4

Belgelere göre :

Bu soyut yol adı bir dizini göstermiyorsa, bu yöntem null değerini döndürür.

Yani eğer kontrol etmelisiniz listFilesolduğunu nullve eğer o değil sadece devam

boolean deleteDirectory(File path) {
    if(path.exists()) {
        File[] files = path.listFiles();
        if (files == null) {
            return false;
        }
        for (File file : files) {
            if (file.isDirectory()) {
                deleteDirectory(file);
            } else {
                boolean wasSuccessful = file.delete();
                if (wasSuccessful) {
                    Log.i("Deleted ", "successfully");
                }
            }
        }
    }
    return(path.delete());
}

1
Bu kabul edilen cevap olmalı. Tıkır tıkır çalışıyor!
MSeiz5

3

Yaptığım şey bu ... (kısa ve test edilmiş)

    ...
    deleteDir(new File(dir_to_be_deleted));
    ...

    // delete directory and contents
    void deleteDir(File file) { 
        if (file.isDirectory())
            for (String child : file.list())
                deleteDir(new File(file, child));
        file.delete();  // delete child file or empty directory
    }

3
private static void deleteRecursive(File dir)
{
    //Log.d("DeleteRecursive", "DELETEPREVIOUS TOP" + dir.getPath());
    if (dir.isDirectory())
    {
        String[] children = dir.list();
        for (int i = 0; i < children.length; i++)
        {
            File temp = new File(dir, children[i]);
            deleteRecursive(temp);
        }

    }

    if (dir.delete() == false)
    {
        Log.d("DeleteRecursive", "DELETE FAIL");
    }
}

2

Tüm dosyaları dizinden silmenin basit yolu:

Sadece çağrı yaparak dizindeki tüm görüntüleri silmek için genel bir işlevdir

deleteAllImageFile (içerik);

public static void deleteAllFile(Context context) {
File directory = context.getExternalFilesDir(null);
        if (directory.isDirectory()) {
            for (String fileName: file.list()) {
                new File(file,fileName).delete();
            }
        }    
    } 

2

Bildiğim en güvenli kod:

private boolean recursiveRemove(File file) {
    if(file == null  || !file.exists()) {
        return false;
    }

    if(file.isDirectory()) {
        File[] list = file.listFiles();

        if(list != null) {

            for(File item : list) {
                recursiveRemove(item);
            }

        }
    }

    if(file.exists()) {
        file.delete();
    }

    return !file.exists();
}

Dosyanın var olup olmadığını kontrol eder, null'ları işler, dizinin gerçekten silindiğini kontrol eder


2

Kısa koltin versiyonu

fun File.deleteDirectory(): Boolean {
    return if (exists()) {
        listFiles()?.forEach {
            if (it.isDirectory) {
                it.deleteDirectory()
            } else {
                it.delete()
            }
        }
        delete()
    } else false
}

1

İşte sadece eğlence için özyinelemeli olmayan bir uygulama:

/**
 * Deletes the given folder and all its files / subfolders.
 * Is not implemented in a recursive way. The "Recursively" in the name stems from the filesystem command
 * @param root The folder to delete recursively
 */
public static void deleteRecursively(final File root) {
    LinkedList<File> deletionQueue = new LinkedList<>();
    deletionQueue.add(root);

    while(!deletionQueue.isEmpty()) {
        final File toDelete = deletionQueue.removeFirst();
        final File[] children = toDelete.listFiles();
        if(children == null || children.length == 0) {
            // This is either a file or an empty directory -> deletion possible
            toDelete.delete();
        } else {
            // Add the children before the folder because they have to be deleted first
            deletionQueue.addAll(Arrays.asList(children));
            // Add the folder again because we can't delete it yet.
            deletionQueue.addLast(toDelete);
        }
    }
}

1

Bu (Verilen dizin dahil tüm alt dosyaları ve alt dizinleri silmeye çalışır) :

  1. Eğer Filesilerseniz
  2. Eğer Empty Directorysilerseniz
  3. eğer Not Empty Directory, çağrı alt dizininde, 1'den 3'e kadar tekrar silin

misal:

File externalDir = Environment.getExternalStorageDirectory()
Utils.deleteAll(externalDir); //BE CAREFUL.. Will try and delete ALL external storage files and directories

Harici Depolama Dizini'ne erişmek için aşağıdaki izinlere ihtiyacınız vardır:

(Kullan ContextCompat.checkSelfPermissionve ActivityCompat.requestPermissions)

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Özyinelemeli yöntem:

public static boolean deleteAll(File file) {
    if (file == null || !file.exists()) return false;

    boolean success = true;
    if (file.isDirectory()) {
        File[] files = file.listFiles();
        if (files != null && files.length > 0) {
            for (File f : files) {
                if (f.isDirectory()) {
                    success &= deleteAll(f);
                }
                if (!f.delete()) {
                    Log.w("deleteAll", "Failed to delete " + f);
                    success = false;
                }
            }
        } else {
            if (!file.delete()) {
                Log.w("deleteAll", "Failed to delete " + file);
                success = false;
            }
        }
    } else {
        if (!file.delete()) {
            Log.w("deleteAll", "Failed to delete " + file);
            success = false;
        }
    }
    return success;
}

0

I 'paces herhangi bir dizin yapısı ile bir klasörü siler rağmen bu bir koydum.

public int removeDirectory(final File folder) {

    if(folder.isDirectory() == true) {
        File[] folderContents = folder.listFiles();
        int deletedFiles = 0;

        if(folderContents.length == 0) {
            if(folder.delete()) {
                deletedFiles++;
                return deletedFiles;
            }
        }
        else if(folderContents.length > 0) {

            do {

                File lastFolder = folder;
                File[] lastFolderContents = lastFolder.listFiles();

                //This while loop finds the deepest path that does not contain any other folders
                do {

                    for(File file : lastFolderContents) {

                        if(file.isDirectory()) {
                            lastFolder = file;
                            lastFolderContents = file.listFiles();
                            break;
                        }
                        else {

                            if(file.delete()) {
                                deletedFiles++;
                            }
                            else {
                                break;
                            }

                        }//End if(file.isDirectory())

                    }//End for(File file : folderContents)

                } while(lastFolder.delete() == false);

                deletedFiles++;
                if(folder.exists() == false) {return deletedFiles;}

            } while(folder.exists());
        }
    }
    else {
        return -1;
    }

    return 0;

}

Bu yardımcı olur umarım.


0
//To delete all the files of a specific folder & subfolder
public static void deleteFiles(File directory, Context c) {
    try {
        for (File file : directory.listFiles()) {
            if (file.isFile()) {
                final ContentResolver contentResolver = c.getContentResolver();
                String canonicalPath;
                try {
                    canonicalPath = file.getCanonicalPath();
                } catch (IOException e) {
                    canonicalPath = file.getAbsolutePath();
                }
                final Uri uri = MediaStore.Files.getContentUri("external");
                final int result = contentResolver.delete(uri,
                        MediaStore.Files.FileColumns.DATA + "=?", new String[]{canonicalPath});
                if (result == 0) {
                    final String absolutePath = file.getAbsolutePath();
                    if (!absolutePath.equals(canonicalPath)) {
                        contentResolver.delete(uri,
                                MediaStore.Files.FileColumns.DATA + "=?", new String[]{absolutePath});
                    }
                }
                if (file.exists()) {
                    file.delete();
                    if (file.exists()) {
                        try {
                            file.getCanonicalFile().delete();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        if (file.exists()) {
                            c.deleteFile(file.getName());
                        }
                    }
                }
            } else
                deleteFiles(file, c);
        }
    } catch (Exception e) {
    }
}

işte çözümünüz de galeriyi de yenileyecek.


0

Bunu çözmenin bir başka (modern) yolu.

public class FileUtils {
    public static void delete(File fileOrDirectory) {
        if(fileOrDirectory != null && fileOrDirectory.exists()) {
            if(fileOrDirectory.isDirectory() && fileOrDirectory.listFiles() != null) {      
                Arrays.stream(fileOrDirectory.listFiles())
                      .forEach(FileUtils::delete);
            }
            fileOrDirectory.delete();
        }
    }
}

Android'de API 26'dan beri

public class FileUtils {

    public static void delete(File fileOrDirectory)  {
        if(fileOrDirectory != null) {
            delete(fileOrDirectory.toPath());
        }
    }

    public static void delete(Path path)  {
        try {
            if(Files.exists(path)) {
                Files.walk(path)
                        .sorted(Comparator.reverseOrder())
                        .map(Path::toFile)
//                      .peek(System.out::println)
                        .forEach(File::delete);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

0

İşi yapmak için bu özyinelemeli işlevi kullanıyorum:

public static void deleteDirAndContents(@NonNull File mFile){
    if (mFile.isDirectory() && mFile.listFiles() != null && mFile.listFiles().length > 0x0) {
        for (File file : mFile.listFiles()) {
            deleteDirAndContents(file);
        }
    } else {
        mFile.delete();
    }
}

İşlev bir dizin mi yoksa dosya mı olduğunu kontrol eder.

Eğer bir dizin ise alt dosyaları olup olmadığını kontrol eder, alt dosyaları varsa kendini tekrar çocuklarını geçip tekrar eder.

Eğer bir dosya ise onu siler.

(Bu işlevi, önbellek dizinini geçerek uygulama önbelleğini temizlemek için kullanmayın, çünkü uygulama kilitlenecek şekilde önbellek dizinini de silecektir ... Önbelleği temizlemek isterseniz, dir ona geçmek:

public static void deleteDirContents(@NonNull File mFile){
        if (mFile.isDirectory() && mFile.listFiles() != null && mFile.listFiles().length > 0x0) {
            for (File file : mFile.listFiles()) {
                deleteDirAndContents(file);
            }
        }
    }

veya aşağıdakileri kullanarak önbellek dizini olup olmadığını kontrol edebilirsiniz:

if (!mFile.getAbsolutePath().equals(context.getCacheDir().getAbsolutePath())) {
    mFile.delete();
}

Uygulama önbelleğini temizlemek için örnek kod:

public static void clearAppCache(Context context){
        try {
            File cache = context.getCacheDir();
            FilesUtils.deleteDirContents(cache);
        } catch (Exception e){
            MyLogger.onException(TAG, e);
        }
    }

Güle güle, iyi günler ve kodlama: D

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.