gpt4 book ai didi

java - 按数字顺序排列文件

转载 作者:行者123 更新时间:2023-12-05 00:50:53 24 4
gpt4 key购买 nike

我制作了一个程序来将文件夹中的所有文件组合在一起。

这是我的部分代码:

File folder = new File("c:/some directory");
File[] listOfFiles = folder.listFiles();
for (File file : listOfFiles){

if (file.isFile()){
System.out.println(file.getName());
File f = new File("c:/some directory"+file.getName());

但是,我希望我的文件可以按如下顺序排列:job1.script, job2.script, .....

但我得到:job1.script, job10.script, job11.script, 那个10,11,12...在2的前面。

我希望我能得到高效的代码来避免这个问题。

最佳答案

是时候摆脱所有笨拙的代码,并使用 Java 8 了!此答案还包含 Path类,它已经是 Java 7 的一部分,但在 Java 8 中似乎有了很大改进。

代码:

private void init() throws IOException {
Path directory = Paths.get("C:\\Users\\Frank\\Downloads\\testjob");
Files.list(directory)
.filter(path -> Files.isRegularFile(path))
.filter(path -> path.getFileName().toString().startsWith("job"))
.filter(path -> path.getFileName().toString().endsWith(".script"))
.sorted(Comparator.comparingInt(this::pathToInt))
.map(path -> path.getFileName())
.forEach(System.out::println);
}

private int pathToInt(final Path path) {
return Integer.parseInt(path.getFileName()
.toString()
.replace("job", "")
.replace(".script", "")
);
}

pathToInt的解释:

  1. 来自给定的 Path , 获取文件的字符串表示形式。
  2. 删除 "job"".script" .
  3. 尝试将字符串解析为整数。

init的解释, 主要方法:

  1. 获得 Path到文件所在的目录。
  2. 获得 Path 的延迟填充列表s 在目录中,请注意:这些 Path s 仍然完全合格!
  3. 保留常规文件。
  4. 保留 Path 最后一部分的文件,因此文件名(例如 job1.script )以 "job" 开头. 请注意您需要先获取 Path 的字符串表示形式在你检查它之前,否则你将检查整个Path从名为 "job" 的目录开始.
  5. 对以 ".script" 结尾的文件执行相同操作.
  6. 现在有趣的一点来了。这里我们根据 Comparator 对文件列表进行排序比较我们通过调用 pathToInt 获得的整数在 Path 上.这里我使用了一个方法引用,方法comparingInt(ToIntFunction<? super T> keyExtractor需要一个映射 T 的函数,在本例中为 Path , 到一个整数。这正是pathToInt确实如此,因此它可以用作方法引用。
  7. 然后我映射每个PathPath仅由文件名组成。
  8. 最后,对于 Stream<Path> 的每个元素,我调用System.out.println(Path.toString()) .

看起来这段代码可以写得更简单,但我故意把它写得更冗长。我这里的设计是保留完整的 Path始终完好无损,forEach 中代码的最后一部分实际上在它仅映射到文件名之前不久就违反了该原则,因此您无法处理完整的 Path。稍后再说。

这段代码也被设计为快速失败,因此它期望文件以 job(\D+).script 的形式存在。 , 并会抛出 NumberFormatException如果不是这样的话。

示例输出:

job1.script
job2.script
job10.script
job11.script

一个可以说是更好的替代方案具有正则表达式的强大功能:

private void init() throws IOException {
Path directory = Paths.get("C:\\Users\\Frank\\Downloads\\testjob");
Files.list(directory)
.filter(path -> Files.isRegularFile(path))
.filter(path -> path.getFileName().toString().matches("job\\d+.script"))
.sorted(Comparator.comparingInt(this::pathToInt))
.map(path -> path.getFileName())
.forEach(System.out::println);
}

private int pathToInt(final Path path) {
return Integer.parseInt(path.getFileName()
.toString()
.replaceAll("job(\\d+).script", "$1")
);
}

这里我使用正则表达式"job\\d+.script" , 匹配以 "job" 开头的字符串, 后跟一位或多位数字,然后是“.script”。
我对 pathToInt 使用几乎相同的表达式方法,但是我使用捕获组、括号和 $1使用该捕获组。

我还将提供一种简洁的方法来读取一个大文件中的文件内容,正如您在问题中所问的那样:

private void init() throws IOException {
Path directory = Paths.get("C:\\Users\\Frank\\Downloads\\testjob");
try (BufferedWriter writer = Files.newBufferedWriter(directory.resolve("masterjob.script"))) {
Files.list(directory)
.filter(path -> Files.isRegularFile(path))
.filter(path -> path.getFileName().toString().matches("job\\d+.script"))
.sorted(Comparator.comparingInt(this::pathToInt))
.flatMap(this::wrappedLines)
.forEach(string -> wrappedWrite(writer, string));
}
}

private int pathToInt(final Path path) {
return Integer.parseInt(path.getFileName()
.toString()
.replaceAll("job(\\d+).script", "$1")
);
}

private Stream<String> wrappedLines(final Path path) {
try {
return Files.lines(path);
} catch (IOException ex) {
//swallow
return null;
}
}

private void wrappedWrite(final BufferedWriter writer, final String string) {
try {
writer.write(string);
writer.newLine();
} catch (IOException ex) {
//swallow
}
}

请注意,lambdas 不能 throw/catch checked Exception s,因此有必要在代码周围编写包装器,以决定如何处理错误。吞下异常很少是一个好主意,我只是在这里简单地将它用于代码。

这里真正的大变化是我不再打印名称,而是将每个文件映射到它的内容并将这些内容写入文件。

关于java - 按数字顺序排列文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22411299/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com