如何使用 Java 和正则表达式正确排序文件条目

How to sort files entries correctly using Java and regex

我有一个包含以下条目的文本文件“unsorted.txt”输入:

37060635563
37067264426
37061457700
37067116332
37068672376
37068669157

我希望Java按以下方式在输出文件“sorted.txt”中整理和格式化这些数字。

+370 606 35563
+370 614 57700
+370 686 69157
+370 686 72376
+370 671 16332
+370 672 64426

我已经制作了排序 Java 代码,但它只生成一个条目,我找不到为什么?

import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Scanner;
import java.io.File;
import java.io.FileWriter;
        
public class PhoneSort {

    public static void main(String[] args) {
        
        final String regex = "(\\d{3})(\\d{3})(\\d*)";
        final String subst = "+  ";
        final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        
        File us = new File("unsorted.txt");
        File st = new File("sorted.txt");
        String result = "";
        
        try (Scanner sc = new Scanner(us)){
                 while (sc.hasNextLine()) {
                        try (FileWriter writer = new FileWriter(st)) {
                          writer.write(pattern.matcher(sc.nextLine()).replaceAll(subst)); 
                         } catch(IOException e){}
                    }
                }
        catch (IOException e){}   
    }
}

如果您想知道为什么您的代码只运行一次,那么您需要进行一些调试,并且需要将任何捕获的异常打印到控制台,以便您可以了解您的代码失败的原因 catch (IOException e){e.printStackTrace();}。永远不要只使用错误,除非你确切地知道你在做什么以及如果出现问题会发生什么。

现在我们有两个问题之一,第一个是您的代码失败,如果是这样,则打印的错误将显示您的文件编写器存在问题,这可能意味着您需要关闭每次写入后写入文件,但这会产生不同的问题(见下文)。

但是,更有可能的问题是您每次都创建一个新的 FileWriter 并覆盖您以前的文件。要解决这个问题,您需要在 while 循环之外声明您的文件编写器,而不是每次都尝试创建一个新文件编写器。

以下应该有效,请注意我们现在如何将错误打印到控制台,以及我们如何只创建一次 FileWriter:

    //We can also add the true flag to append data to the file writer
    try (Scanner sc = new Scanner(us);
      FileWriter writer = new FileWriter(st, true);){            
        while (sc.hasNextLine()) {
            writer.write(pattern.matcher(sc.nextLine()).replaceAll(subst)); 
        }
        writer.close();
    }
    catch (IOException e){
        e.printStackTrace();
    }   

这是一个具有所需结果的工作示例

public static void main(String[] args) {
    final String regex = "(\d{3})(\d{3})(\d*)";
    final String subst = "+  ";
    final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);

    File us = new File("unsorted.txt");
    File st = new File("sorted.txt");

    try (BufferedReader reader = new BufferedReader(new FileReader(us));
         BufferedWriter writer = new BufferedWriter(new FileWriter(st))) {
        reader.lines().sorted()
                .map(r -> pattern.matcher(r).replaceAll(subst))
                .forEach(res -> {
                    try {
                        writer.write(res);
                        writer.newLine();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
    } catch (IOException e) {
        e.printStackTrace();
    }
}

我写这个答案是假设你希望输出是,

+370 606 35563
+370 614 57700
+370 671 16332
+370 672 64426
+370 686 69157
+370 686 72376

我的方法不使用正则表达式,而是将文件读入内存。

  1. 将文件中的所有行读入List
  2. 根据要求对以上列表进行排序。 (按前三位排序-如果相同,则按后三位排序。即使相等,也按其余位排序)。
  3. 将排序后的列表写入结果文件。

Path path = Paths.get("<fill_the_path>/unsorted.txt");
List<String> lines = Files.readAllLines(path); 
List<String> sortedList = sort(lines);    

Files.write(Paths.get("<fill_the_path>/sorted.txt"),
            format(sortedList),
            StandardOpenOption.CREATE);



private List<String> sort(List<String> lines) {
    Comparator<String> comparator = Comparator.comparing((String s) -> Integer.valueOf(s.substring(0, 3)))
            .thenComparing(s -> Integer.valueOf(s.substring(3, 6)))
            .thenComparing(s -> Integer.valueOf(s.substring(6)));
    return lines.stream()
            .sorted(comparator)
            .collect(Collectors.toList());
}


private List<String> format(List<String> lines) {
    return lines.stream()
            .map(this::formatLine)
            .collect(Collectors.toList());
}

private String formatLine(String line) {
    return "+" +
            line.substring(0, 3) + " " +
            line.substring(3, 6) + " " +
            line.substring(6);
}

注意:您可以将每行转换为 Long 并使用 Comparator.comparingLong(如果该值适合 long)。

return lines.stream()
        .sorted(Comparator.comparingLong(Long::valueOf))
        .collect(Collectors.toList());