使用nio对磁盘下的文件进行过滤
上篇博文讲到为了解决tomcat日志自动清理的问题,翻看了tomcat-juli这个jar包。在FileHandler类下有一个利用nio完成对磁盘下过期文件进行过滤的功能实现,正好这段时间正在学习nio框架,所以特意抽离源码做了一下测试。以下将提供测试代码(主要代码摘抄自tomcat-juli.jar源码),与君共勉。
package nio; import java.io.File; import java.io.IOException; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.regex.Pattern; public class FilesFilter { private static int maxDays = 0; private static String directory = "E:\\Program Files\\Apache Software Foundation\\Tomcat 8.5.24\\logs"; private static String prefix = "localhost."; private static String suffix = ".log"; private static Pattern pattern = null; public static void main(String[] args) { // TODO Auto-generated method stub pattern = Pattern .compile("^(" + Pattern.quote(prefix) + ")\\d{4}-\\d{1,2}-\\d{1,2}(" + Pattern.quote(suffix) + ")$"); try { DirectoryStream<Path> files = streamFilesForDelete(); System.out.println("准备输出:"); for (Path file : files) { // Files.delete(file); System.out.println(file.toRealPath()); } } catch (IOException e) { System.out.println("Unable to delete log files older than [" + maxDays + "] days"); } } /** * 查询过期文件 * @return * @throws IOException */ private static DirectoryStream<Path> streamFilesForDelete() throws IOException { final Date maxDaysOffset = getMaxDaysOffset(); final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); return Files.newDirectoryStream(new File(directory).toPath(), new DirectoryStream.Filter<Path>() { public boolean accept(Path path) throws IOException { boolean result = false; String date = obtainDateFromPath(path); if (date != null) { try { Date dateFromFile = formatter.parse(date); result = dateFromFile.before(maxDaysOffset); } catch (ParseException e) { // no-op } } return result; } }); } private static String obtainDateFromPath(Path path) { Path fileName = path.getFileName(); if (fileName == null) { return null; } String date = fileName.toString(); if (pattern.matcher(date).matches()) { date = date.substring(prefix.length()); return date.substring(0, date.length() - suffix.length()); } else { return null; } } private static Date getMaxDaysOffset() { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); cal.add(Calendar.DATE, -maxDays); return cal.getTime(); } }
代码重点只有一个: java.nio.file.Files.newDirectoryStream(Path dir,DirectoryStream.Filter<? super Path> filter),nio的Files类下newDirectoryStream方法用于获取指定磁盘下的物理文件列表Stream,该方法第二个参数可接收一个用于过滤的功能函数。实现accept方法,针对自己的场景自定义过滤条件。个人理解这种方式,可以在一次磁盘扫描中,完成无效文件过滤与符合条件文件的获取操作。比起传统的io对文件逐个扫描的操作,可以减少磁盘读写开销,有助于软件性能提升。当然,没有做过试验,在我这里还不算是一个结论。有这方面性能验证的朋友,可以给我留言解惑,谢谢!
每天都是崭新的开始 ——Mr.司满(214382122)[]~( ̄▽ ̄)~*