使Java扫描程序更加健壮?

使Java扫描程序更加健壮?,java,java.util.scanner,Java,Java.util.scanner,我通常不会在日常工作中使用Java,尽管我希望这样做,因为每件事都有一个类(有时太多了)。昨天我花了一天的大部分时间写下面的程序。Tiny rant:java.util.scanner不太直观,我想用它扫描日志文件中的两种特定模式,对其进行一些日期运算并打印结果。如果我获取日志文件并删除不匹配的行,然后运行该程序,则该程序可以工作。我可以用vi、sed或其他工具来实现这一点,但我更感兴趣的是使用这个工具,使它对那些不太习惯使用shell脚本或vi的人更有用。今天我将对此进行更多的讨论,但我想知道

我通常不会在日常工作中使用Java,尽管我希望这样做,因为每件事都有一个类(有时太多了)。昨天我花了一天的大部分时间写下面的程序。Tiny rant:java.util.scanner不太直观,我想用它扫描日志文件中的两种特定模式,对其进行一些日期运算并打印结果。如果我获取日志文件并删除不匹配的行,然后运行该程序,则该程序可以工作。我可以用vi、sed或其他工具来实现这一点,但我更感兴趣的是使用这个工具,使它对那些不太习惯使用shell脚本或vi的人更有用。今天我将对此进行更多的讨论,但我想知道这里是否有一些专业知识可以让我更快地前进

import java.util.*;
import java.util.concurrent.*;
import java.text.SimpleDateFormat;
import java.util.regex.Pattern;
import java.util.regex.MatchResult;
import java.io.*;
import java.time.*;
import java.time.format.*;

public class TimeDiff {
    private static SimpleDateFormat m_formatter = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
    private static Pattern m_startRunPattern = Pattern.compile("start of run=([^,]+)");
    private static Pattern m_currentTimePattern = Pattern.compile("current time=(.+)");
    
    private String m_fileArg;
    private File m_file;
    private Scanner m_scanner;

    public TimeDiff(String[] args)
    {
        if (args.length == 0) {
            System.err.println("nope.");
            System.exit(1);
        }

        m_fileArg = args[0];
        m_file = new File(m_fileArg);
    }

    public String findPattern(Scanner fileScan, Pattern pattern)
    {
        String ret_val = null;
        try {
            ret_val = fileScan.findInLine(pattern);
            MatchResult result = fileScan.match();
            if (result.groupCount() > 0) {
                ret_val = result.group(1);
            }
        }
        catch (java.util.InputMismatchException e) {
            System.out.println("failed at second");
        }
        catch (java.lang.IllegalStateException e) {
            System.out.println("failed at second match " + e);
        }
        
        return ret_val;
    }

    public void run(String[] args) throws Exception
    {
        try (Scanner fileScan = new Scanner(m_file)) {
            while (fileScan.hasNext()) {
                String beginTimeStr = findPattern(fileScan, m_startRunPattern);
                String endTimeStr = findPattern(fileScan, m_currentTimePattern);

                if (beginTimeStr == null && endTimeStr == null) {
                    if (fileScan.hasNext()) {
                        fileScan.next();
                    }
                }
                else {
                    Date startDate = m_formatter.parse(beginTimeStr);
                    Date endDate   = m_formatter.parse(endTimeStr);

                    long duration  = endDate.getTime() - startDate.getTime();
                    long diffInSeconds = TimeUnit.MILLISECONDS.toSeconds(duration);
                    long diffInMinutes = TimeUnit.MILLISECONDS.toMinutes(duration);

                    long remainderSeconds = 0;
                    if (diffInMinutes > 0) {
                        remainderSeconds = diffInSeconds % diffInMinutes;
                    }
                    else {
                        remainderSeconds = diffInSeconds;
                    }

                    System.out.println("elapsed seconds: " + diffInSeconds + ", (" + diffInMinutes + " minutes, " + remainderSeconds + " seconds).");
                    if (fileScan.hasNext()) {
                        fileScan.next();
                    }
                }
            }
        }
        catch (IOException exception) {
            System.out.println(exception);
        }
    }

    public static void main(java.lang.String args[])
    {
        try {
            TimeDiff app = new TimeDiff(args);
            app.run(args);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
经过处理的日志文件条目如下所示:

DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 17:54:13  start of run=2020-07-29-17.53.31.216800, current time=2020-07-29-17.54.13.530384
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 17:54:13  start of run=2020-07-29-17.53.29.903984, current time=2020-07-29-17.54.13.805200
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 17:54:13  start of run=2020-07-29-17.53.14.356440, current time=2020-07-29-17.54.13.907528
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 23:16:01  start of run=2020-07-29-23.15.27.722784, current time=2020-07-29-23.16.01.016640
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 23:16:04  start of run=2020-07-29-23.15.39.955272, current time=2020-07-29-23.16.04.418160
DealWithResponse.cpp, DealWithResponse(XMLSocketApp &, DOMDocument *), 247 2020-07-29 23:16:05  start of run=2020-07-29-23.15.52.154920, current time=2020-07-29-23.16.05.480384

当然,日志文件的其余部分包含业务逻辑内容(SQL等)。

来自
Scanner
findInLine
文档:

尝试查找指定模式的下一个匹配项,忽略分隔符。如果在下一行分隔符之前找到该模式,则扫描仪将通过匹配的输入并返回与该模式匹配的字符串。如果在下一行分隔符之前的输入中未检测到此类图案,则返回null,并且扫描仪的位置不变。此方法可能会阻止等待与模式匹配的输入

您所观察到的是findInLine在换行之前没有找到任何与指定模式匹配的内容,因此返回
null
,并且不改变任何位置

也许
findWithinHorizon(模式,0)
更符合您的喜好?如果需要的话,它将一直查找(直到输入结束),直到在您的regexp中找到匹配项为止

然后它返回匹配。如果需要整行代码,只需在regexp上展开:
“^.*当前时间=(.*)$”
将始终匹配整行代码


第二个提示:异常处理非常糟糕。如果发现异常,请处理它。”打印一些文字,然后继续,就好像什么都没有错一样。简单的解决方案:将
抛出异常
添加到主方法中(在任何情况下,这几乎总是一个好主意)。那就。。摆脱所有
尝试{
捕获{}
在代码中阻塞。使其更简短、更易于阅读,并且更好地引导!

关于异常处理的观点,但这绝不是一个完整的程序,我主要是在正确调用以正确扫描文件。在我得到我想要的工作后,我将进行清理和优化。异常非常有用o现在让我告诉我调用了错误的代码,或者我没有正确使用返回值。如果您像我提到的那样编写异常处理,您将[1]得到更好的错误报告[2]编写更少的代码。我不认为“但我只是在测试东西”是一个很好的解释,解释了为什么你编写了让事情变得更糟的冗余代码。事实上,自从我学会了如何更好地使用这个类以来,我已经删除了很多代码,所以我首先需要做更少的异常处理。这绝不是最终的代码,而是一个work正在进行中,这是我自己的一个教育练习。第二个版本即将推出。