【问题标题】:Sort a file based on substring using Java使用Java根据子字符串对文件进行排序
【发布时间】:2020-05-12 22:24:54
【问题描述】:

我有一个名为 logfile.log 的文件。我想通过子字符串(两个管道字符之间的测试名称)对 logfile.log 进行排序,并将输出定向到名为 sorted_logfile.log 的文件

当前日志文件.log:

2020-05-09 05:51:13,985 INFO  | CreateCardTest|  :  -> some message
2020-05-09 05:51:13,985 INFO  | WorkspaceTest|  :  -> some message
2020-05-09 05:51:14,779 INFO  | WorkspaceTest| :  -> some message
2020-05-09 05:51:14,779 INFO  | CreateCardTest|  :  -> some message 
2020-05-09 05:51:14,779 INFO  | WorkspaceTest|  :  -> some message
2020-05-09 05:51:14,779 INFO  | SavedTest| Leads :  -> some message
2020-05-09 05:51:14,779 INFO  | WorkspaceTest|  :  some message
2020-05-09 05:51:14,780 INFO  | WorkspaceTest| Workspace : some message
2020-05-09 05:51:15,732 INFO  | CreateCardTest| Leads :  -> some message
2020-05-09 05:51:15,732 INFO  | WorkspaceTest| Workspace : some message 
2020-05-09 05:51:21,638 INFO  | SavedTest| Leads :  -> some message
2020-05-09 05:51:21,638 INFO  | CreateCardTest| Leads :  -> some message 
2020-05-09 05:51:21,653 INFO  | WorkspaceTest| Workspace : Accounts,All Accounts :  -> some message
2020-05-09 05:51:21,653 INFO  | WorkspaceTest| Workspace : Accounts,All Accounts :  -> some message 
2020-05-09 05:51:21,803 INFO  | WorkspaceTest| Workspace : Accounts,All Accounts :  -> some message
2020-05-09 05:51:21,803 INFO  | CreateCardTest| Leads :  -> some message

“CreateCardTest”、“WorkspaceTest”和“SavedTest”是测试名称。它是两个管道字符之间的子字符串,需要根据它进行排序。在测试中,消息的顺序应该相同(按当前日志文件中的时间戳排序)。

期望的 sorted_logfile.log:

2020-05-09 05:51:13,985 INFO  | CreateCardTest|  :  -> some message
2020-05-09 05:51:14,779 INFO  | CreateCardTest|  :  -> some message
2020-05-09 05:51:15,732 INFO  | CreateCardTest| Leads :  -> some message
2020-05-09 05:51:21,638 INFO  | CreateCardTest| Leads :  -> some message 
2020-05-09 05:51:21,803 INFO  | CreateCardTest| Leads :  -> some message
2020-05-09 05:51:14,779 INFO  | SavedTest| Leads :  -> some message
2020-05-09 05:51:21,638 INFO  | SavedTest| Leads :  -> some message
2020-05-09 05:51:13,985 INFO  | WorkspaceTest|  :  -> some message
2020-05-09 05:51:14,779 INFO  | WorkspaceTest| :  -> some message
2020-05-09 05:51:14,779 INFO  | WorkspaceTest|  :  -> some message
2020-05-09 05:51:14,779 INFO  | WorkspaceTest|  :  some message
2020-05-09 05:51:14,780 INFO  | WorkspaceTest| Workspace : some message
2020-05-09 05:51:15,732 INFO  | WorkspaceTest| Workspace : some message 
2020-05-09 05:51:21,653 INFO  | WorkspaceTest| Workspace : Accounts,All Accounts :  -> some message
2020-05-09 05:51:21,653 INFO  | WorkspaceTest| Workspace : Accounts,All Accounts :  -> some message 
2020-05-09 05:51:21,803 INFO  | WorkspaceTest| Workspace : Accounts,All Accounts :  -> some message

这是我当前的代码:

public static void main(String[] args) {
        BufferedReader reader;
        try {
            reader = new BufferedReader(new FileReader("log/logfile.log"));
            String line = reader.readLine();
            while (line != null) {
                System.out.println(line);
                // read next line
                line = reader.readLine();
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

我如何实现这一目标?我看过 Collections.sort() 但这对子字符串不起作用。

【问题讨论】:

    标签: java sorting


    【解决方案1】:

    您可以根据比较器进行排序;比较器需要能够以一致的方式判定:给定任意 2 个对象,哪一个“更高”?

    另外,请注意 main 可以抛出,以便清理您的代码,除非您真的,真的,真的知道您想要平台默认值,否则不应在未指定字符集的情况下使用 FileReader (提示:你没有)。在 java8 上这个构造函数不存在,所以你根本不能使用 filereader。

    public static void main(String[] args) throws Exception {
        var lines = new ArrayList<String>();
        try (BufferedReader br = new FileReader("log/logfile.log", StandardCharsets.UTF_8)) {
            String line = br.readLine();
            while (line != null) {
                lines.add(line);
                line = br.readLine();
            }
        }
    
        lines.sort(Comparator.comparing(a -> textBetweenBars(a)));
    }
    
    public String textBetweenBars(String a) {
        int idx1 = a.indexOf('|' + 1);
        int idx2 = a.indexOf('|', idx1);
        return a.substring(idx1, idx2);
        // you may want to write some code on what to do if those bars aren't there...
    }
    

    或者使用更简洁的新 API:

    public static void main(String[] args) throws Exception {
        var lines = Files
            .readAllLines(Paths.get("log/logfile.log"))
            .sort(Comparator.comparing(a -> textBetweenBars(a)));
    }
    
    public String textBetweenBars(String a) {
        int idx1 = a.indexOf('|') + 1;
        int idx2 = a.indexOf('|', idx1);
        return a.substring(idx1, idx2);
        // you may want to write some code on what to do if those bars aren't there...
    }
    

    注意:Files 类中的各种字符串读取/写入方法默认为 UTF-8,而大多数其他内容(包括 FileReader)默认为“平台默认值”;这就是为什么使用 Files API 时,您无需指定字符集。

    NB2:“新”是指“10 岁”。现在真的。没关系,当然,即使这是一个课程,在这一点上。

    【讨论】:

      【解决方案2】:

      编写下面的方法从每个字符串中获取密钥。然后使用以下比较器作为 sort 方法的参数。为此,需要将文件读入List&lt;String&gt;

          Comparator<String> comp = (a,b)->getKey(a).compareTo(getKey(b));
      
          public static String getKey(String a) {
              int start = a.indexOf("|") + 1;
              int end = a.indexOf("|", start);
              return a.substring(start, end);
          }
      

      【讨论】:

        猜你喜欢
        • 2015-08-13
        • 1970-01-01
        • 1970-01-01
        • 2021-10-13
        • 2021-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多