使用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对文件逐个扫描的操作,可以减少磁盘读写开销,有助于软件性能提升。当然,没有做过试验,在我这里还不算是一个结论。有这方面性能验证的朋友,可以给我留言解惑,谢谢!

 

posted @ 2018-01-17 16:08  Mr.Simm  阅读(657)  评论(0编辑  收藏  举报