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