【问题标题】:Delete files older than x days删除超过 x 天的文件
【发布时间】:2013-02-23 16:39:04
【问题描述】:

我如何知道文件是何时使用 java 创建的,因为我希望删除超过某个时间段的文件,目前我正在删除目录中的所有文件,但这并不理想:

public void DeleteFiles() {
    File file = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/");
    System.out.println("Called deleteFiles");
    DeleteFiles(file);
    File file2 = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/Uploaded/");
    DeleteFilesNonPdf(file2);
}

public void DeleteFiles(File file) {
    System.out.println("Now will search folders and delete files,");
    if (file.isDirectory()) {
        for (File f : file.listFiles()) {
            DeleteFiles(f);
        }
    } else {
        file.delete();
    }
}

以上是我当前的代码,我现在正在尝试添加一个 if 语句,它只会删除一周之前的文件。

编辑:

@ViewScoped
@ManagedBean
public class Delete {

    public void DeleteFiles() {
        File file = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/web/resources/pdf/");
        System.out.println("Called deleteFiles");
        DeleteFiles(file);
        File file2 = new File("D:/Documents/NetBeansProjects/printing~subversion/fileupload/Uploaded/");
        DeleteFilesNonPdf(file2);
    }

    public void DeleteFiles(File file) {
        System.out.println("Now will search folders and delete files,");
        if (file.isDirectory()) {
            System.out.println("Date Modified : " + file.lastModified());
            for (File f : file.listFiles()) {
                DeleteFiles(f);
            }
        } else {
            file.delete();
        }
    }

现在添加一个循环。

编辑

我注意到在测试上面的代码时我得到了最后一次修改:

INFO: Date Modified : 1361635382096

如果是上述格式,我应该如何对 if 循环进行编码以说明是否超过 7 天将其删除?

【问题讨论】:

    标签: java time delete-file


    【解决方案1】:

    您可以使用File.lastModified() 获取文件/目录的最后修改时间。

    可以这样使用:

    long diff = new Date().getTime() - file.lastModified();
    
    if (diff > x * 24 * 60 * 60 * 1000) {
        file.delete();
    }
    

    删除早于xint)天的文件。

    【讨论】:

    • 谢谢 :) 会调查的
    • 它会给出最后修改时间而不是文件创建时间。
    • 没关系,文件一旦创建就不能修改了:)
    • :D 这真的很简单。我正在编写文件创建时间的ans。 ;)
    • 谢谢! :) 正在 atm 测试它,但到目前为止看起来很完美!
    【解决方案2】:

    使用 lambdas (Java 8+)

    删除当前文件夹中所有超过 N 天的文件的非递归选项(忽略子文件夹):

    public static void deleteFilesOlderThanNDays(int days, String dirPath) throws IOException {
        long cutOff = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000);
        Files.list(Paths.get(dirPath))
        .filter(path -> {
            try {
                return Files.isRegularFile(path) && Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS) < cutOff;
            } catch (IOException ex) {
                // log here and move on
                return false;
            }
        })
        .forEach(path -> {
            try {
                Files.delete(path);
            } catch (IOException ex) {
                // log here and move on
            }
        });
    }
    

    递归选项,遍历子文件夹并删除所有超过 N 天的文件:

    public static void recursiveDeleteFilesOlderThanNDays(int days, String dirPath) throws IOException {
        long cutOff = System.currentTimeMillis() - (days * 24 * 60 * 60 * 1000);
        Files.list(Paths.get(dirPath))
        .forEach(path -> {
            if (Files.isDirectory(path)) {
                try {
                    recursiveDeleteFilesOlderThanNDays(days, path.toString());
                } catch (IOException e) {
                    // log here and move on
                }
            } else {
                try {
                    if (Files.getLastModifiedTime(path).to(TimeUnit.MILLISECONDS) < cutOff) {
                        Files.delete(path);
                    }
                } catch (IOException ex) {
                    // log here and move on
                }
            }
        });
    }
    

    【讨论】:

      【解决方案3】:

      这是使用 Time API 的 Java 8 版本。它已经在我们的项目中经过测试和使用:

          public static int deleteFiles(final Path destination,
              final Integer daysToKeep) throws IOException {
      
          final Instant retentionFilePeriod = ZonedDateTime.now()
                  .minusDays(daysToKeep).toInstant();
      
          final AtomicInteger countDeletedFiles = new AtomicInteger();
          Files.find(destination, 1,
                  (path, basicFileAttrs) -> basicFileAttrs.lastModifiedTime()
                          .toInstant().isBefore(retentionFilePeriod))
                  .forEach(fileToDelete -> {
                      try {
                          if (!Files.isDirectory(fileToDelete)) {
                              Files.delete(fileToDelete);
                              countDeletedFiles.incrementAndGet();
                          }
                      } catch (IOException e) {
                          throw new UncheckedIOException(e);
                      }
                  });
      
          return countDeletedFiles.get();
      }
      

      【讨论】:

      • 我正在根据我的需要调整它,并且收到了来自 SonarQube 的警告,指出应该关闭 Files.find 流,或者最好将其放入资源块的尝试中。
      【解决方案4】:

      你可以使用NIO获取文件的创建日期,方法如下:

      BasicFileAttributes attrs = Files.readAttributes(file, BasicFileAttributes.class);
      System.out.println("creationTime: " + attrs.creationTime());
      

      更多信息可以在这里找到:http://docs.oracle.com/javase/tutorial/essential/io/fileAttr.html

      【讨论】:

      • BasicFileAttributes 仅适用于 java 7。您不能将其用于 java 6 或更早版本。
      【解决方案5】:

      JavaSE 规范解决方案。 删除早于expirationPeriod 天的文件。

      private void cleanUpOldFiles(String folderPath, int expirationPeriod) {
          File targetDir = new File(folderPath);
          if (!targetDir.exists()) {
              throw new RuntimeException(String.format("Log files directory '%s' " +
                      "does not exist in the environment", folderPath));
          }
      
          File[] files = targetDir.listFiles();
          for (File file : files) {
              long diff = new Date().getTime() - file.lastModified();
      
              // Granularity = DAYS;
              long desiredLifespan = TimeUnit.DAYS.toMillis(expirationPeriod); 
      
              if (diff > desiredLifespan) {
                  file.delete();
              }
          }
      }
      

      例如- 删除文件夹“/sftp/logs”调用中所有超过 30 天的文件:

      cleanUpOldFiles("/sftp/logs", 30);

      【讨论】:

        【解决方案6】:

        使用 Apache utils 可能是最简单的。这是我能想到的最简单的解决方案。

        public void deleteOldFiles() {
            Date oldestAllowedFileDate = DateUtils.addDays(new Date(), -3); //minus days from current date
            File targetDir = new File("C:\\TEMP\\archive\\");
            Iterator<File> filesToDelete = FileUtils.iterateFiles(targetDir, new AgeFileFilter(oldestAllowedFileDate), null);
            //if deleting subdirs, replace null above with TrueFileFilter.INSTANCE
            while (filesToDelete.hasNext()) {
                FileUtils.deleteQuietly(filesToDelete.next());
            }  //I don't want an exception if a file is not deleted. Otherwise use filesToDelete.next().delete() in a try/catch
        }
        

        【讨论】:

        • 另外值得注意的是,您可以使用毫秒来创建像 new AgeFileFilter(System.currentTimeMillis() - AGE_LIMIT_MILLIS) 这样的 AgeFileFilter,其中 AGE_LIMIT_MILLIS 可以说是 24*60*60*1000L 24 小时。
        • @MattC 如果我将它用于具有 2 或 300 万条记录的目录,这是否会产生内存不足异常之类的影响?
        • @Diwa 是的,我猜如果您有数百万个文件,您可能会遇到内存问题。 FileUtils 创建一个 java.util.LinkedList,然后返回该列表的迭代器。
        【解决方案7】:

        使用带有 lambda 和 Commons IO 的 Java NIO 文件

        final long time = System.currentTimeMillis();
        // Only show files & directories older than 2 days
        final long maxdiff = TimeUnit.DAYS.toMillis(2);
        

        列出所有找到的文件和目录:

        Files.newDirectoryStream(Paths.get("."), p -> (time - p.toFile().lastModified()) < maxdiff)
        .forEach(System.out::println);
        

        或者用FileUtils删除找到的文件:

        Files.newDirectoryStream(Paths.get("."), p -> (time - p.toFile().lastModified()) < maxdiff)
        .forEach(p -> FileUtils.deleteQuietly(p.toFile()));
        

        【讨论】:

        • 建议使用System.currentTimeMillis(),我也觉得应该是&gt;
        【解决方案8】:

        Commons IO 内置支持按年龄过滤文件的AgeFileFilter。您的 DeleteFiles 可能看起来像这样:

        import java.io.File;
        import org.apache.commons.io.FileUtils;
        import org.apache.commons.io.filefilter.AgeFileFilter;
        import static org.apache.commons.io.filefilter.TrueFileFilter.TRUE;
        
        // a Date defined somewhere for the cutoff date
        Date thresholdDate = <the oldest age you want to keep>;
        
        public void DeleteFiles(File file) {
            Iterator<File> filesToDelete =
                FileUtils.iterateFiles(file, new AgeFileFilter(thresholdDate), TRUE);
            for (File aFile : filesToDelete) {
                aFile.delete();
            }
        }
        

        更新:要使用编辑中给出的值,请将thresholdDate 定义为:

        Date tresholdDate = new Date(1361635382096L);
        

        【讨论】:

        • 有什么方法可以将 AgeFileFilter 与另一个过滤器(例如 NameFileFilter)结合起来?
        • @NathanChristie 请参阅 AndFileFilterOrFileFilter
        • 参数:iterateFiles(File directory, IOFileFilter fileFilter, IOFileFilter dirFilter), dirfilter 可选(可以为null)
        • 示例无法编译,无法迭代 Iterator 可能想使用 listFiles?
        【解决方案9】:

        使用 Java 8 的 Time API 的示例

        LocalDate today = LocalDate.now();
        LocalDate eailer = today.minusDays(30);
            
        Date threshold = Date.from(eailer.atStartOfDay(ZoneId.systemDefault()).toInstant());
        AgeFileFilter filter = new AgeFileFilter(threshold);
            
        File path = new File("...");
        File[] oldFolders = FileFilterUtils.filter(filter, path);
            
        for (File folder : oldFolders) {
            System.out.println(folder);
        }
        

        【讨论】:

        • 需要明确的是,AgeFileFilter 来自 Apache Commons IO,而不是来自 Java 8 Time API。
        【解决方案10】:

        对于同时使用 NIO 文件流和 JSR-310 的 JDK 8 解决方案

        long cut = LocalDateTime.now().minusWeeks(1).toEpochSecond(ZoneOffset.UTC);
        Path path = Paths.get("/path/to/delete");
        Files.list(path)
                .filter(n -> {
                    try {
                        return Files.getLastModifiedTime(n)
                                .to(TimeUnit.SECONDS) < cut;
                    } catch (IOException ex) {
                        //handle exception
                        return false;
                    }
                })
                .forEach(n -> {
                    try {
                        Files.delete(n);
                    } catch (IOException ex) {
                        //handle exception
                    }
                });
        

        这里最糟糕的是需要在每个 lambda 中处理异常。如果 API 为每个 IO 方法提供 UncheckedIOException 重载,那就太好了。有帮助者可以这样写:

        public static void main(String[] args) throws IOException {
            long cut = LocalDateTime.now().minusWeeks(1).toEpochSecond(ZoneOffset.UTC);
            Path path = Paths.get("/path/to/delete");
            Files.list(path)
                    .filter(n -> Files2.getLastModifiedTimeUnchecked(n)
                            .to(TimeUnit.SECONDS) < cut)
                    .forEach(n -> {
                        System.out.println(n);
                        Files2.delete(n, (t, u)
                                      -> System.err.format("Couldn't delete %s%n",
                                                           t, u.getMessage())
                        );
                    });
        }
        
        
        private static final class Files2 {
        
            public static FileTime getLastModifiedTimeUnchecked(Path path,
                    LinkOption... options)
                    throws UncheckedIOException {
                try {
                    return Files.getLastModifiedTime(path, options);
                } catch (IOException ex) {
                    throw new UncheckedIOException(ex);
                }
            }
        
            public static void delete(Path path, BiConsumer<Path, Exception> e) {
                try {
                    Files.delete(path);
                } catch (IOException ex) {
                    e.accept(path, ex);
                }
            }
        
        }
        

        【讨论】:

          【解决方案11】:

          这是删除六个月以来未修改的文件并创建日志文件的代码。

          package deleteFiles;
          
          import java.io.File;
          import java.io.IOException;
          import java.util.ArrayList;
          import java.util.Calendar;
          import java.util.Date;
          import java.util.logging.FileHandler;
          import java.util.logging.Logger;
          import java.util.logging.SimpleFormatter;
          
          public class Delete {
              public static void deleteFiles()
              {
                  int numOfMonths = -6;
                  String path="G:\\Files";
                  File file = new File(path);
                  FileHandler fh;
                  Calendar sixMonthAgo = Calendar.getInstance();
                  Calendar currentDate = Calendar.getInstance();
                  Logger logger = Logger.getLogger("MyLog");
                  sixMonthAgo.add(Calendar.MONTH, numOfMonths);
                  File[] files = file.listFiles();
                  ArrayList<String> arrlist = new ArrayList<String>();
          
                  try {
                      fh = new FileHandler("G:\\Files\\logFile\\MyLogForDeletedFile.log");
                      logger.addHandler(fh);
                      SimpleFormatter formatter = new SimpleFormatter();
                      fh.setFormatter(formatter);
          
                      for (File f:files)
                      {
                          if (f.isFile() && f.exists())
                          {
                              Date lastModDate = new Date(f.lastModified());
                              if(lastModDate.before(sixMonthAgo.getTime()))
                              {
                                  arrlist.add(f.getName());
                                  f.delete();
                              }
                          }
                      }
                      for(int i=0;i<arrlist.size();i++)
                          logger.info("deleted files are ===>"+arrlist.get(i));
                  }
                  catch ( Exception e ){
                      e.printStackTrace();
                      logger.info("error is-->"+e);
                  }
              }
              public static void main(String[] args)
              {
                  deleteFiles();
              }
          }
          

          【讨论】:

          • 解释 OP 不理解的部分比向他们提供大量代码来做他们想要的事情更有帮助。看看这里接受的答案,它的代码比你的少得多,但解释更多,简洁地解决了问题。
          【解决方案12】:

          Apache commons-io 和 joda 的另一种方法:

          private void deleteOldFiles(String dir, int daysToRemainFiles) {
              Collection<File> filesToDelete = FileUtils.listFiles(new File(dir),
                      new AgeFileFilter(DateTime.now().withTimeAtStartOfDay().minusDays(daysToRemainFiles).toDate()),
                      TrueFileFilter.TRUE);    // include sub dirs
              for (File file : filesToDelete) {
                  boolean success = FileUtils.deleteQuietly(file);
                  if (!success) {
                      // log...
                  }
              }
          }
          

          【讨论】:

            【解决方案13】:

            使用 Apache commons-io 和 joda:

                    if ( FileUtils.isFileOlder(f, DateTime.now().minusDays(30).toDate()) ) {
                        f.delete();
                    }
            

            【讨论】:

              【解决方案14】:

              需要指出列出的第一个解决方案的一个错误,如果 x 很大,x * 24 * 60 * 60 * 1000 将最大化 int 值。所以需要将其转换为长值

              long diff = new Date().getTime() - file.lastModified();
              
              if (diff > (long) x * 24 * 60 * 60 * 1000) {
                  file.delete();
              }
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-03-26
                • 2018-01-02
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多