【问题标题】:initialise object variable from file paths从文件路径初始化对象变量
【发布时间】:2018-03-09 09:43:10
【问题描述】:
servername
|-- reports
|    |-- ABC
|    |    |-- COB02May2017
|    |    |    |-- pnlreport.pdf
|    |    |    |-- balancereport.pdf
|    |    |-- COB03May2017
|    |-- CustomerB
|    |    |-- COB02May2017
|    |    |-- COB03May2017
|    |    |    |-- balancereport.pdf 
|    |-- 01CFG
|    |    |-- COB03Sep2017

我有上面的目录树来保存我的客户报告。

我有以下ReportDeliverable 模型:

public class ReportDeliverable {

    private String reportId;
    private String reportName;
    private String customer;
    private String format;
    private Date cobDate;
}

ReportSchedule:

public class ReportSchedule {

    private final String schedule;
    private final String reportId;
    private final String filePattern;
    private final String format;
    private final String filePath;

}

我有以下类负责提供报告可交付对象的列表:

@Service
public class FileServiceImpl implements FileService {


    @Value("${reports.source-path}")
    private String sourcePath;


    @Override
    public List<ReportDeliverable> getReportDeliverables(ReportSchedule reportSchedule) {
        List<ReportDeliverable> reportDeliverables = new ArrayList<>();
        List<Path> filesToProcess = getFilesToProcess(reportSchedule);

        filesToProcess.forEach(path -> {
            //for each path returned, extract and initialise ReportDeliverable object
            ReportDeliverable reportDeliverable = new ReportDeliverable();
            //reportDeliverable.setReportName(); > pnlreport.xls
            //reportDeliverable.setFormat(); >  > PDF
            //reportDeliverable.setCobDate(); > 26-SEP-2017
            //reportDeliverable.setClient(); > CustomerA
            //reportDeliverable.setFilePath(); > \servername\reports\CustomerA\COB26Sep2017\pnlreport.pdf

            reportDeliverables.add(reportDeliverable); 
        });

        return reportDeliverables;
    }

    public List<Path> getFilesToProcess(ReportSchedule reportSchedule) {

        String pattern = reportSchedule.getFilePattern(); //e.g. pnlreport
        String format = reportSchedule.getFormat(); // PDF

        //return full paths from here based on report criteria for COB that is T-1 (day before today). ignore the rest
        // e.g. if today is 27/09/2017
        //return -> \servername\reports\CustomerA\COB26Sep2017\pnlreport.pdf, \servername\reports\CustomerB\COB26Sep2017\pnlreport.PDF

        return path;
    }
}

每天都会创建一个目录,名称为COB-{prior-day-date},如上述目录结构。在 Java 8 中,

  1. 我需要一些帮助来返回与ReportSchedules 中保存的标准有关的所有文件paths。我试图在 getFilesToProcess(ReportSchedule reportSchedule) 的 cmets 中解释
  2. 从路径中,我需要初始化 ReportDeliverable 字段,在 cmets getReportDeliverables(ReportSchedule reportSchedule) 中再次说明

【问题讨论】:

    标签: java nio java-io file-processing


    【解决方案1】:

    我对您的问题的理解是如何遍历目录结构以在目录中查找适合特定模式的文件,这些文件的命名方式包括遵循特定格式规则的格式化日期。这是我想出的。有可能的优化,但它应该是一个起点。

    如果我理解错了你的问题,你可能会改写一下,这样我就可以更正我的答案了。

    import java.io.File;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Calendar;
    import java.util.List;
    import java.util.Locale;
    
    public class RetrievePathsOfYesterday {
    
        public final static void main(String[] args) {
            String pattern = "pnlreport";
            String format = "PDF";
            String baseDir = "F:/Test";
            switch(args.length) {
            case 3:
                format = args[2];
            case 2:
                pattern = args[1];
            case 1:
                baseDir = args[0];
            }
            File root = new File(baseDir);
            File[] customerDirs = root.listFiles(file -> file.getName().toLowerCase(Locale.ENGLISH).startsWith("customer"));
            ArrayList<Path> result = new ArrayList<>();
            for (int i = 0; i < customerDirs.length; i++) {
                result.addAll(getFilesToProcess(customerDirs[i], pattern, format));
            }
            System.out.println(result);
        }
    
        public static List<Path> getFilesToProcess(File baseDir, String pattern, String format) {
            pattern = pattern.toLowerCase(Locale.ENGLISH);
            format = "." + format.toLowerCase(Locale.ENGLISH);
            Calendar now = Calendar.getInstance();
            now.add(Calendar.DAY_OF_YEAR, -1);
            SimpleDateFormat sdf = new SimpleDateFormat("ddMMMyyyy", Locale.ENGLISH);
            File startDir = new File(baseDir, "COB" + sdf.format(now.getTime()));
            ArrayList<Path> result = new ArrayList<>();
            getFilesToProcess(result, startDir, pattern, format);
            return result;
        }
    
        private static void getFilesToProcess(List<Path> resList, File baseDir, String pattern, String format) {
            System.out.println("processing " + baseDir.getAbsolutePath());
            if (!baseDir.exists()) {
                return;
            }
            File[] files = baseDir.listFiles(pathName -> {
                System.out.println("filter " + pathName.getName());
                if (pathName.isDirectory()) {
                    return true;
                }
                if (!pathName.isFile()) {
                    return false;
                }
                String name = pathName.getName().toLowerCase(Locale.ENGLISH);
                if (!name.startsWith(pattern)) {
                    return false;
                }
                if (!name.endsWith(format)) {
                    return false;
                }
                return true;
            });
    
            for (int i = 0; i < files.length; i++) {
                File current = files[i];
                System.out.println("Checking " + current.getAbsolutePath());
                if (current.isDirectory()) {
                    getFilesToProcess(resList, current, pattern, format);
                    continue;
                }
                resList.add(Paths.get(current.toURI()));
            }
        }
    }
    

    我用以下目录结构测试了这段代码:

    kimmerin@harry /cygdrive/f
    $ ls -R Test
    Test:
    CustomerA  CustomerB
    
    Test/CustomerA:
    COB26Sep2017
    
    Test/CustomerA/COB26Sep2017:
    pnlreport.pdf
    
    Test/CustomerB:
    COB26Sep2017
    
    Test/CustomerB/COB26Sep2017:
    otherreport.PDF
    

    如果您将Test 替换为servername/report,这应该与您在问题中描述的结构完全相同。这是使用默认值启动类时的输出:

    过滤 pnlreport.pdf

    检查 F:\Test\CustomerA\COB26Sep2017\pnlreport.pdf

    处理 F:\Test\CustomerB\COB26Sep2017

    过滤其他报告.PDF

    [F:\Test\CustomerA\COB26Sep2017\pnlreport.pdf]

    【讨论】:

    • 快速浏览一下答案,客户是独一无二的,不遵循相应目录的模式。
    • @user2781389 我将用于测试的目录结构添加到答案中。
    • 谢谢。由于客户目录级别的名称中没有“客户”等模式,您能否更新您的答案以读取所有客户目录。我们可以将 Streams 与 Files.find() 一起使用并提供 maxdepth 来读取所有 customerdir 吗?也许在这个答案中提供一些优化范围或重构?如何将 COB 日期读取为 Date 对象?
    猜你喜欢
    • 1970-01-01
    • 2016-11-15
    • 2011-08-21
    • 2013-04-05
    • 2013-05-15
    • 2013-07-04
    • 1970-01-01
    • 2015-04-16
    • 2014-11-29
    相关资源
    最近更新 更多