【问题标题】:Delete Files with same Prefix String using Java使用 Java 删除具有相同前缀字符串的文件
【发布时间】:2011-11-06 14:50:55
【问题描述】:

我在一个目录中有大约 500 个文本文件,每个文件的文件名中都有相同的前缀,例如:dailyReport_

文件的后半部分是文件的日期。 (例如dailyReport_08262011.txtdailyReport_08232011.txt

我想使用 Java 过程删除这些文件。 (我可以使用一个 shell 脚本并在 crontab 中添加一个作业,但该应用程序是供外行使用的)。

我可以使用以下方法删除单个文件:

try{
    File f=new File("dailyReport_08232011.txt");
    f.delete();
}
catch(Exception e){ 
    System.out.println(e);
}

但是我可以删除具有特定前缀的文件吗? (例如第 8 个月的 dailyReport08)我可以使用 rm -rf dailyReport08*.txt 在 shell 脚本中轻松做到这一点。

但是File f=new File("dailyReport_08*.txt"); 在 Java 中不起作用(如预期的那样)。

现在在 Java 中是否可以在不运行循环的情况下搜索目录中的文件?

我可以使用一些类似于 shell 脚本中* 的特殊字符来实现这一点吗?

【问题讨论】:

  • 循环有什么问题?
  • 我也有同感……为什么不循环呢?
  • 我知道它可能使用循环......但正如我所说,我可能有大量文件(500 只是一个数字)......所以如果可能的话,不要使用循环其他方式,比如 shell 脚本,我觉得会更好......
  • @S.M.09:所以你想在输入上做一些事情。听起来你需要一个循环。再说一遍:为什么你不想要一个循环?你觉得它有点慢吗?提示:即使是 shell 在某些时候也需要循环,你只是没有看到那个循环。
  • 如果您喜欢 shell,this question 的答案可能会有所帮助。

标签: java filenames java-io


【解决方案1】:

不,你不能。 Java 是相当低级的语言——与 shell-script 相比——所以这样的事情必须更明确地完成。您应该使用 folder.listFiles(FilenameFilter) 搜索具有所需掩码的文件,并遍历返回的数组以删除每个条目。像这样:

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() );
    }
}

【讨论】:

  • 点赞!根本没有 for 循环。
  • @user802421: 有一个 for 循环,但是,我打算避免使用模式搜索文件的循环......正如我所说,这为我尝试循环搜索的逻辑提供了更快的结果用于文件并在找到时删除....
  • 现在你可以用 lambda 替换 FilenameFilter 对象:folder.listFiles((dir, name) -> name.matches("dailyReport_08.*\\.txt"));跨度>
【解决方案2】:

你可以使用循环

for (File f : directory.listFiles()) {
    if (f.getName().startsWith("dailyReport_")) {
        f.delete();
    }
}

【讨论】:

    【解决方案3】:

    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)
    

    【讨论】:

      【解决方案4】:

      使用 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;
      }
      

      简单版:

      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
          }
      }
      

      根据需要修改路径/字符串参数。您甚至可以在文件和路径之间进行转换。 Java >= 8 的首选路径。

      【讨论】:

      • 这在 Java 7 中实际上是可用的。
      【解决方案5】:

      像这样使用FileFilter

      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();
      }
      

      【讨论】:

      • 此代码将删除以 dailyReport_08 开头的任何内容(包括非 txt 文件),可能还会检查扩展名......但给定的代码 BegemoT 给出了完美的结果..谢谢任何方式
      【解决方案6】:

      我知道我迟到了。但是,为了将来参考,我想贡献一个不涉及循环的 java 8 流解决方案。

      它可能不漂亮。我欢迎提出建议,让它看起来更好。但是,它可以完成工作:

      Files.list(deleteDirectory).filter(p -> p.toString().contains("dailyReport_08")).forEach((p) -> {
          try {
              Files.deleteIfExists(p);
          } catch (Exception e) {
              e.printStackTrace();
          }
      });
      

      或者,您可以使用 Files.walk 将深度优先遍历目录。也就是说,如果文件被埋在不同的目录中。

      【讨论】:

      • 我不认为这个解决方案避免了循环,它只是使用了新的语法。
      • @jartaud,是的。不是通常意义上的,而是一个迭代操作。也是对流的终端操作。
      【解决方案7】:

      没有通配符,但您可以实现FilenameFilter 并使用startsWith("dailyReport_") 检查路径。然后调用File.listFiles(filter) 会给你一个文件数组,你可以循环访问并调用 delete()。

      【讨论】:

        【解决方案8】:

        如果没有循环,您将无法做到这一点。但是你可以增强这个循环。首先,问你一个问题:“在循环中搜索和删除有什么问题?”如果由于某种原因太慢,您可以在单独的线程中运行循环,这样它就不会影响您的用户界面。

        其他建议 - 将您的每日报告放在一个单独的文件夹中,然后您就可以删除该文件夹中的所有内容。

        【讨论】:

        • 同意每月文件夹!!!....本来可以每月文件夹,但是合并文件(不同月份的)等某些要求可能会变得乏味......并且已经循环声明大量文件...
        【解决方案9】:

        我同意 BegemoT。

        但是,只有一项优化: 如果您需要一个简单的FilenameFilter,Google 包中有一个类。 因此,在这种情况下,您甚至不必创建自己的匿名类。

        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() );
            }
        }
        

        享受吧!

        【讨论】:

          【解决方案10】:

          或者在scala中

          new java.io.File(<<pathStr>>).listFiles.filter(_.getName.endsWith(".txt")).foreach(_.delete())
          

          【讨论】:

            【解决方案11】:

            看看Apache FileUtils,它提供了许多方便的文件操作。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-04-05
              • 2020-04-16
              • 2015-09-08
              • 2011-05-08
              • 2022-12-16
              • 2012-10-21
              • 1970-01-01
              • 2021-06-08
              相关资源
              最近更新 更多