J'ai environ 500 fichiers texte dans un répertoire avec le même préfixe dans leur nom de fichier, par exemple dailyReport_
.
La dernière partie du fichier est la date du fichier. (Par exemple, dailyReport_08262011.txt
, dailyReport_08232011.txt
)
Je veux supprimer ces fichiers en utilisant une procédure Java (je pourrais aller chercher un script Shell et l'ajouter à un travail dans la crontab mais l'application est destinée à être utilisée par des profanes).
Je peux supprimer un seul fichier en utilisant quelque chose comme ça
try{
File f=new File("dailyReport_08232011.txt");
f.delete();
}
catch(Exception e){
System.out.println(e);
}
mais puis-je supprimer les fichiers ayant un certain préfixe (par exemple: dailyReport08
pour le 8ème mois), je pourrais facilement le faire dans un script shell en utilisant rm -rf dailyReport08*.txt
.
Mais File f=new File("dailyReport_08*.txt");
ne fonctionne pas en Java (comme prévu).
Maintenant, est-il possible en Java sans exécuter une boucle de rechercher des fichiers dans le répertoire?
Puis-je y parvenir en utilisant des caractères spéciaux similaires à *
utilisés dans un script Shell?
Non, tu ne peux pas. Java est plutôt un langage de bas niveau - comparé à Shell-script - donc des choses comme celle-ci doivent être faites de manière plus explicite. Vous devez rechercher les fichiers avec le masque requis avec folder.listFiles (FilenameFilter) et effectuer une itération dans un tableau renvoyé en supprimant chaque entrée. Comme ça:
final File folder = ...
final File[] files = folder.listFiles( new FilenameFilter() {
@Override
public boolean accept( final File dir,
final String name ) {
return name.matches( "dailyReport_08.*\\.txt" );
}
} );
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
Vous pouvez utiliser une boucle
for (File f : directory.listFiles()) {
if (f.getName().startsWith("dailyReport_")) {
f.delete();
}
}
Avec Java 8:
public static boolean deleteFilesForPathByPrefix(final String path, final String prefix) {
boolean success = true;
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(Paths.get(path), prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) {
success = false;
e.printStackTrace();
}
return success;
}
Version simple:
public static void deleteFilesForPathByPrefix(final Path path, final String prefix) {
try (DirectoryStream<Path> newDirectoryStream = Files.newDirectoryStream(path, prefix + "*")) {
for (final Path newDirectoryStreamItem : newDirectoryStream) {
Files.delete(newDirectoryStreamItem);
}
} catch (final Exception e) { // empty
}
}
Modifiez l'argument Path/String si nécessaire. Vous pouvez même convertir entre File et Path. Path est préféré pour Java> = 8.
Je sais que je suis en retard à la fête. Cependant, pour référence future, je souhaitais apporter une solution Java 8 stram ne comportant pas de boucle.
Ce n'est peut-être pas joli. J'apprécie les suggestions pour améliorer l'apparence. Cependant, il fait le travail:
Files.list(deleteDirectory).filter(p -> p.toString().contains("dailyReport_08")).forEach((p) -> {
try {
Files.deleteIfExists(p);
} catch (Exception e) {
e.printStackTrace();
}
});
Alternativement, vous pouvez utiliser Files.walk qui parcourra le répertoire en premier. C'est-à-dire si les fichiers sont enterrés dans des répertoires différents.
Il n'y a pas de caractère générique mais vous pouvez implémenter un FilenameFilter et vérifier le chemin avec une startsWith("dailyReport_")
. Ensuite, appeler File.listFiles(filter)
vous donne un tableau de fichiers que vous pouvez parcourir et appelez delete ().
Utilisez FileFilter
comme suit:
File dir = new File(<path to dir>);
File[] toBeDeleted = dir.listFiles(new FileFilter() {
boolean accept(File pathname) {
return (pathname.getName().startsWith("dailyReport_08") && pathname.getName().endsWith(".txt"));
}
for (File f : toBeDeleted) {
f.delete();
}
Java 8:
final File downloadDirectory = new File("directoryPath");
final File[] files = downloadDirectory.listFiles( (dir,name) -> name.matches("dailyReport_.*?" ));
Arrays.asList(files).stream().forEach(File::delete)
Je suis d'accord avec BegemoT.
Cependant, une seule optimisation: Si vous avez besoin d'une simple FilenameFilter
, il existe une classe dans les packages Google . Donc, dans ce cas, vous n'avez même pas à créer votre propre classe anonyme.
import com.google.common.io.PatternFilenameFilter;
final File folder = ...
final File[] files = folder.listFiles(new PatternFilenameFilter("dailyReport_08.*\\.txt"));
// loop through the files
for ( final File file : files ) {
if ( !file.delete() ) {
System.err.println( "Can't remove " + file.getAbsolutePath() );
}
}
Prendre plaisir !
Vous ne pouvez pas le faire sans une boucle. Mais vous pouvez améliorer cette boucle. Tout d’abord, posez-vous une question: "quel est le problème avec la recherche et la suppression dans la boucle?" Si cela est trop lent pour une raison quelconque, vous pouvez simplement exécuter votre boucle dans un thread séparé, afin que cela n’affecte pas votre interface utilisateur.
Autre conseil - mettez vos rapports quotidiens dans un dossier séparé pour pouvoir supprimer ce dossier avec tout le contenu.
Regardez Apache FileUtils qui offre de nombreuses manipulations de fichiers pratiques.
new Java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())