アプリケーションのユーザーがDCIMフォルダー(SDカードにあり、サブフォルダーを含む)を削除できるようにしたい。
これは可能ですか?
rm -rf directory
代わりに使用する必要がありますFileUtils.deleteDirectory
。ベンチマークの結果、数倍高速であることがわかりました。ここでサンプル実装を確認してください:stackoverflow.com/a/58421350/293280
アプリケーションのユーザーがDCIMフォルダー(SDカードにあり、サブフォルダーを含む)を削除できるようにしたい。
これは可能ですか?
rm -rf directory
代わりに使用する必要がありますFileUtils.deleteDirectory
。ベンチマークの結果、数倍高速であることがわかりました。ここでサンプル実装を確認してください:stackoverflow.com/a/58421350/293280
回答:
DCIMフォルダーはシステムフォルダーであるため削除できないことを最初に説明します。電話で手動で削除すると、そのフォルダーの内容は削除されますが、DCIMフォルダーは削除されません。以下の方法で内容を削除できます。
コメントに従って更新
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();
}
}
次のように、ファイルとフォルダを再帰的に削除できます。
void deleteRecursive(File fileOrDirectory) {
if (fileOrDirectory.isDirectory())
for (File child : fileOrDirectory.listFiles())
deleteRecursive(child);
fileOrDirectory.delete();
}
DCIM\foo\bar\pic.jpg
:)。その場合、chiragのコードは失敗します。
fileOrDirectory.listFiles()
戻るnull
ことがあります。これはドキュメントに明確に記載されています:developer.android.com/reference/java/io/File.html#listFiles()
コマンドライン引数を使用して、フォルダー全体とその内容を削除できます。
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) { }
}
}
上記のコードの使用例:
deleteFiles("/sdcard/uploads/");
KotlinではdeleteRecursively()
、kotlin.io
パッケージの拡張機能を使用できます
val someDir = File("/path/to/dir")
someDir.deleteRecursively()
FilesKt.deleteRecursively(new File("/path/to/dir"));
kotlin-stdlibを使用している場合に使用できます
以下の方法を使用して、ファイルとそのサブディレクトリを含むメインディレクトリ全体を削除します。このメソッドを呼び出した後、メインディレクトリのdelete()ディレクトリをもう一度呼び出します。
// 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();
}
あなたのアプローチはファイルのみを含むフォルダーにはまともですが、サブフォルダーも含むシナリオを探している場合は再帰が必要です
また、ファイルの削除が許可されていることを確認するために、戻りの戻り値をキャプチャする必要があります
そして含む
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
あなたのマニフェストで
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();
}
答えはたくさんありますが、少し違うので自分で追加することにしました。これはOOPに基づいています;)
クラスDirectoryCleanerを作成しました。これは、ディレクトリをクリーンアップする必要があるたびに役立ちます。
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();
}
}
次の方法でこの問題を解決するために使用できます。
File dir = new File(Environment.getExternalStorageDirectory(), "your_directory_name");
new DirectoryCleaner(dir).clean();
dir.delete();
Javaにサブディレクトリまたはファイルがある場合、ディレクトリを削除できません。この2行の簡単なソリューションを試してください。これにより、ディレクトリとディレクトリ内のコンテストが削除されます。
File dirName = new File("directory path");
FileUtils.deleteDirectory(dirName);
この行をgradleファイルに追加し、プロジェクトを同期します
compile 'org.apache.commons:commons-io:1.3.2'
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();
}
}
android.os.FileUtilsを参照してください。API21では非表示です。
public static boolean deleteContents(File dir) {
File[] files = dir.listFiles();
boolean success = true;
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
success &= deleteContents(file);
}
if (!file.delete()) {
Log.w("Failed to delete " + file);
success = false;
}
}
}
return success;
}
ソース:https : //android.googlesource.com/platform/frameworks/base/+/master/core/java/android/os/FileUtils.java#414
ドキュメントによると:
この抽象パス名がディレクトリを示さない場合、このメソッドはnullを返します。
だからあなたはそうであるかどうかをチェックし、そうでない場合にのみ続行する必要listFiles
がnull
あります
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());
}
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");
}
}
ディレクトリからすべてのファイルを削除する簡単な方法:
呼び出すだけでディレクトリからすべての画像を削除するための汎用関数です
deleteAllImageFile(context);
public static void deleteAllFile(Context context) {
File directory = context.getExternalFilesDir(null);
if (directory.isDirectory()) {
for (String fileName: file.list()) {
new File(file,fileName).delete();
}
}
}
私が知っている最も安全なコード:
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();
}
ファイルが存在することを確認し、nullを処理し、ディレクトリが実際に削除されたことを確認します
楽しみのために、これは非再帰的な実装です:
/**
* 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);
}
}
}
これ(提供されたディレクトリを含むすべてのサブファイルとサブディレクトリを削除しようとします):
File
、削除Empty Directory
、削除Not Empty Directory
、サブディレクトリを指定してもう一度deleteを呼び出し、1〜3を繰り返します。例:
File externalDir = Environment.getExternalStorageDirectory()
Utils.deleteAll(externalDir); //BE CAREFUL.. Will try and delete ALL external storage files and directories
外部ストレージディレクトリにアクセスするには、次の権限が必要です。
(使用ContextCompat.checkSelfPermission
とActivityCompat.requestPermissions
)
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
再帰的な方法:
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;
}
私はこれを入れましたが、そのペースはディレクトリ構造を持つフォルダを削除します。
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;
}
お役に立てれば。
//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) {
}
}
これはあなたの解決策ですが、ギャラリーも更新します。
それを解決するさらに別の(現代の)方法。
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();
}
}
}
API 26以降のAndroid
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();
}
}
}
私はこの再帰関数を使用して仕事をしています:
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();
}
}
関数は、それがディレクトリであるかファイルであるかをチェックします。
ディレクトリの場合は、子ファイルがあるかどうかを確認します。子ファイルがある場合は、自分自身を呼び出して、子を渡して繰り返します。
ファイルの場合は削除します。
(この関数を使用してキャッシュディレクトリを渡すことでアプリキャッシュをクリアしないでください。キャッシュディレクトリも削除されるため、アプリがクラッシュします...キャッシュをクリアしたい場合は、この関数を使用して、あなたがそれに渡すdir:
public static void deleteDirContents(@NonNull File mFile){
if (mFile.isDirectory() && mFile.listFiles() != null && mFile.listFiles().length > 0x0) {
for (File file : mFile.listFiles()) {
deleteDirAndContents(file);
}
}
}
または、次のコマンドを使用して、それがキャッシュディレクトリであるかどうかを確認できます。
if (!mFile.getAbsolutePath().equals(context.getCacheDir().getAbsolutePath())) {
mFile.delete();
}
アプリのキャッシュをクリアするコードの例:
public static void clearAppCache(Context context){
try {
File cache = context.getCacheDir();
FilesUtils.deleteDirContents(cache);
} catch (Exception e){
MyLogger.onException(TAG, e);
}
}
さようなら、良い一日を過ごしてコーディング:D