我如何按月份过滤目录中的文件,根据月份对它们进行压缩,重命名,然后将它们放在包含zipfile的文件夹中?

问题描述 投票:0回答:1

我的目录中包含1000多个文件,我需要根据月份对它们进行压缩,重命名并将压缩后的文件放在文件夹中。我通常会手动执行此操作,但是我厌倦了这种方式。我编写了一个程序来重命名文件并将其放置在新文件夹中,但是我不知道如何在Windows 10上按月过滤或使用Java压缩文件。

        String path = "C:\\\\Users\\\\srs\\\\Desktop\\\\Test\\notProcessed";

        File[] filelist = new File(path).listFiles();

        for (File file : filelist) {
            Date d = new Date(file.lastModified());
            Calendar c = Calendar.getInstance();
            c.setTime(d);
            int iyear = c.get(Calendar.YEAR);
            int imonth = c.get(Calendar.MONTH);
            String syear = Integer.toString(iyear);
            String smonth = Integer.toString(imonth);
            System.out.println(syear + "_" + smonth);
            String destpath = "C:\\\\Users\\\\srs\\\\Desktop\\\\Test\\notProcessed\\\\TestZip\\\\";
            byte[] buffer = new byte[1024];
            try {
                FileOutputStream fos = new FileOutputStream(destpath + syear + "_" + smonth + ".zip");
                ZipOutputStream zos = new ZipOutputStream(fos);
                System.out.println("Output to Zip : " + file);
                System.out.println("File Added : " + file.getAbsolutePath().toString());
                ZipEntry ze = new ZipEntry(file.getName());
                zos.putNextEntry(ze);
                FileInputStream in = new FileInputStream(file);
                int len;
                while ((len = in.read(buffer)) > 0) {
                    zos.write(buffer, 0, len);
                }
                in.close();
                zos.closeEntry();
                zos.close();
                System.out.println("Done");
            } catch (IOException ex) {
                ex.printStackTrace();
            }

        }

    }

所以这是我到目前为止所拥有的。该程序运行,但是没有给我所需的结果。它应该给我3个标有(基于lastModified())的zip文件夹2019_07、2019_08、2019_09,但我得到的是2019_06、2019_07、2019_08、2019_10,每个文件夹中只有一个文件。

java directory zip filtering file-rename
1个回答
0
投票

分组

您当前正在使用File API和旧的日期时间API(例如Date)。我会建议你:

  1. 使用java.nio.file API代替File API。
  2. 使用Java 8中添加的java.time API,而不是旧的日期时间API。
    • 这一点特别重要。创建新代码时,应不惜一切代价避免使用旧的日期时间API。

根据您对问题的了解,您希望按文件的最后修改时间的年和月对文件进行分组,然后将其放入自己的ZIP文件中。对于分组,我们可以使用YearMonth类和YearMonth方法。这是一个例子:

Files#walkFileTree(Path,Set,int,FileVisitor)

以上使用的是系统默认时区。我还添加了选项以指定搜索文件树(植根于Files#walkFileTree(Path,Set,int,FileVisitor))时的最大深度。如果只想查找Map<YearMonth, List<Path>> groupFiles(Path dir, int depth) throws IOException { Map<YearMonth, List<Path>> result = new HashMap<>(); Files.walkFileTree(dir, Set.of(), depth, new SimpleFileVisitor<>() { private final ZoneId systemZone = ZoneId.systemDefault(); private final YearMonth currentYearMonth = YearMonth.now(); @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { YearMonth yearMonth = getYearMonthOfLastModifiedTime(attrs); if (yearMonth.isBefore(currentYearMonth)) { result.computeIfAbsent(yearMonth, k -> new ArrayList<>()).add(file); } return FileVisitResult.CONTINUE; } private YearMonth getYearMonthOfLastModifiedTime(BasicFileAttributes attrs) { Instant lastModInstant = attrs.lastModifiedTime().toInstant(); return YearMonth.from(LocalDate.ofInstant(lastModInstant, systemZone)); } }); return result; } 的直接子文件,请使用dir。另外,在最大深度总是dir的情况下,可以使用1代替1


创建ZIP

一旦您将文件的最后修改时间按DirectoryStream分组,则需要将它们放入ZIP文件中。在JDK中,至少有两个选项可用于创建ZIP文件:

  1. FileVisitor API。
  2. YearMonth(通过java.util.zip API使用。

我相信,第一种选择可让您更好地控制压缩过程。但是,第二个选项可让您以透明方式将ZIP文件与任何其他文件系统相同。对于这个答案,我将显示第二个选项的示例:

ZIP File System Provider

我使用java.nio.file,因为您的问题表明ZIP文件的文件名应为List<Path> compressFiles(Path zipDir, Map<YearMonth, List<Path>> groupedFiles) throws IOException { List<Path> zipFiles = new ArrayList<>(groupedFiles.size()); DateTimeFormatter zipFilenameFormatter = DateTimeFormatter.ofPattern("uuuu_MM'.zip'"); for (Map.Entry<YearMonth, List<Path>> entry : groupedFiles.entrySet()) { Path zipFile = zipDir.resolve(zipFilenameFormatter.format(entry.getKey())); zipFiles.add(zipFile); URI uri = URI.create("jar:" + zipFile.toUri()); Map<String, ?> env = Map.of("create", Boolean.toString(Files.notExists(zipFile))); try (FileSystem zipFileSystem = FileSystems.newFileSystem(uri, env)) { Path zipRoot = zipFileSystem.getRootDirectories().iterator().next(); for (Path source : entry.getValue()) { Files.move(source, zipRoot.resolve(source.getFileName().toString())); } } } return zipFiles; } (带下划线)。 DateTimeFormatter方法将返回DateTimeFormatter(带短划线),因此year_month.zip用于通过下划线分隔年和月。如果您不介意破折号,则只需使用YearMonth#toString()即可创建文件名。

以上使用year-month将文件实际添加到ZIP文件中。该文件将被压缩。请注意,如果ZIP文件中已经存在具有该名称的条目,则此操作将失败,但是您可以使用DateTimeFormatter进行更改。调用yearMonth.toString() + ".zip"将删除源文件;如果不希望这样做,请考虑改用Files#move(Path,Path,CopyOption...)

请注意,我使用Files#move(Path,Path,CopyOption...)而不是REPLACE_EXISTING,因为根据我的经验,后者要求两个#move实例属于同一提供者。

© www.soinside.com 2019 - 2024. All rights reserved.