java - 读取/过滤文本文件的最快方法是什么

标签 java

我正在尝试遍历包含 SSH 登录和其他日志的日志文本文件。

程序正在返回 SSH 登录的总数。

我的解决方案确实有效,但似乎有点慢(在 200mo 文件上大约需要 3.5 秒)。我想知道是否有任何方法可以让它更快。我不太熟悉 Java 的良好做法。

我正在使用 BufferedReader 类。也许有更好的类/方法,但我在网上找到的其他所有东西都比较慢。

{
            BufferedReader br;
            if(fileLocation != null) {
                br = new BufferedReader(new FileReader(fileLocation));
            }
            else {
                br = new BufferedReader((new InputStreamReader(System.in, "UTF-8")));
            }
            String line;
            Stack<String> users = new Stack<>();
            int succeeded = 0;
            int failed;
            int total = 0;

            if(!br.ready()) {
                help("Cannot read the file", true);
            }
            while((line=br.readLine())!=null)
            {
                if(!line.contains("sshd")) continue;
                String[] arr = line.split("\\s+");
                if(arr.length < 11) continue;


                String log = arr[4];
                String log2 = arr[5];
                String log3 = arr[8];
                String user = arr[10];
                if(!log.contains("sshd")) continue;
                if(!log2.contains("Accepted")) {
                    if(log3.contains("failure")) {
                        total++;
                    }
                    continue;
                }
                total++;
                succeeded++;

                if(!repeat) {
                    if (users.contains(user)) continue;
                    users.add(user);
                }

                System.out.println((total + 1) + " " + user);
            }

完整代码:https://pastebin.com/xp2P9wja

此外,这是日志文件的一些行:

Dec  3 12:20:12 k332 sshd[25206]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=10.147.222.137 
Dec  3 12:20:14 k332 sshd[25204]: error: PAM: Authentication failure for illegal user admin from 10.147.222.137
Dec  3 12:20:14 k332 sshd[25204]: Failed keyboard-interactive/pam for invalid user admin from 10.147.222.137 port 36417 ssh2
Dec  3 12:20:14 k332 sshd[25204]: Connection closed by invalid user admin 10.147.222.137 port 36417 [preauth]
Dec  3 12:20:40 k332 sshd[25209]: pam_tally2(sshd:auth): Tally overflowed for user root

最终输出为:

Total :
103 unique IP SSH logins succeeded
30387 SSH logins succeeded
17186 SSH logins failed
47573 total SSH logins

感谢您的宝贵时间!

编辑:Mo (Mega Octet) = MB (Mega Byte)(我们通常用法语说 Mo)

这是完整的更新代码,任何人都需要它:https://pastebin.com/Kn5EqLNX

最佳答案

如果您对代码进行分析,就会清楚问题出在 String.split() 方法中:

enter image description here

这是标准 Java 库中的一个已知问题:Java split String performances .

所以为了加速你的代码,你需要通过某种方式来加速这部分代码。我可以建议的第一件事是将第 75-79 行的代码替换为:

Pattern pattern = Pattern.compile("\\s+");
while ((line = br.readLine()) != null) {
    if (!line.contains("sshd")) continue;
    String[] arr = pattern.split(line);
    if (arr.length < 11) continue;
...
}

这可能会稍微加快代码速度,但是从配置文件中可以看出,很多时间仍然花费在 Pattern 和 Matcher 方法上。我们需要摆脱 Pattern 和 Matcher 以获得显着的加速。

对于单字符模式,split 无需使用 Regex 即可工作并且效率很高,让我们尝试将代码替换为:

while ((line = br.readLine()) != null) {
    if (!line.contains("sshd")) continue;
    String[] arr = Arrays.stream(line.split(" "))
                    .filter(s -> !s.isEmpty())
                    .toArray(String[]::new);
    if (arr.length < 11) continue;
...
}

此代码在相同数据上的运行速度几乎是原来的两倍。

关于java - 读取/过滤文本文件的最快方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72258518/

相关文章:

java - 将数字四舍五入到特定的倍数

java - 如何在 Windows 中使用带代理的 weka 包管理器?

java - 学习 Java 编程最重要的东西是什么?

java - 类似 "qualified this"但用于访问嵌套类而不是封闭类的成员

java - 如何将十六进制颜色字符串解析为整数

java - 我需要帮助来显示 java 13 中 20 个整数的输入集中的所有偶数

java - Spring Data MongoDB - 保存 LocalDate/LocalDateTime 时,值被设置为昨天

java - 将对象引用或基本类型作为参数传递时,void 方法的行为如何

java - 将单独的组件锚定在 JFrame 中

java - 使用 XStream 和 JsonHierarchicalStreamDriver 输出值,如何舍入 double ?