我正在使用'java.util.Scanner'来读取和扫描关键字,并希望打印前5行和接下来的5行遇到的关键字,下面是我的代码
ArrayList<String> keywords = new ArrayList<String>();
keywords.add("ERROR");
keywords.add("EXCEPTION");
java.io.File file = new java.io.File(LOG_FILE);
Scanner input = null;
try {
input = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
int count = 0;
String previousLine = null;
while(input.hasNext()){
String line = input.nextLine();
for(String keyword : keywords){
if(line.contains(keyword)){
//print prev 5 lines
system.out.println(previousLine); // this will print only last previous line ( i need last 5 previous lines)
???
//print next 5 lines
system.out.println(input.nextLine());
system.out.println(input.nextLine());
system.out.println(input.nextLine());
system.out.println(input.nextLine());
system.out.println(input.nextLine());
}
previousLine = line;
}
打印前5行的任何指针..?
答案 0 :(得分:2)
打印前5行的任何指针..?
Dequeue<String>
中,例如LinkedList<String>
,因为它的“先入先出(FIFO)”行为。 addFirst(...)
方法将新String添加到开头,并removeLast()
删除列表的最后一个String(如果其大小为> 5)。迭代LinkedList以获取它包含的当前字符串。其他建议:
scanner.hasNextXXX()
方法应与get方法scanner.nextXXX()
匹配。因此,如果您打算致电hasNextLine()
,请检查nextLine()
。否则你会冒问题。system.out.println
vs System.out.println
。我知道这是一件小事,但当其他人尝试使用您的代码时,这意味着很多。contains(...)
方法摆脱for循环。如,
LinkedList<String> fivePrevLines = new LinkedList<>();
java.io.File file = new java.io.File(LOG_FILE);
Scanner input = null;
try {
input = new Scanner(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (input.hasNextLine()) {
String line = input.nextLine();
if (keywords.contains(line)) {
System.out.println("keyword found!");
for (String prevLine : fivePrevLines) {
System.out.println(prevLine);
}
} else {
fivePrevLines.addFirst(line);
if (fivePrevLines.size() > 5) {
fivePrevLines.removeLast();
}
}
}
if (input != null) {
input.close();
}
修改强>
您在评论中说明:
好吧我运行了一个小测试程序来查看contains(...)方法是否有效......
<unreadable unformatted code>
...并且找不到这个返回的关键字......!
这就是你如何使用它。 contains(...)
方法用于检查Collection是否包含另一个对象。如果你输入一个巨大的字符串,它可能会或可能不会使用集合中的一个字符串,但它将适用于构成较大字符串的单个字符串,它将无法工作。例如:
ArrayList<String> temp = new ArrayList<String>();
temp.add("error");
temp.add("exception");
String s = "Internal Exception: org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object";
String[] tokens = s.split("[\\s\\.:,]+");
for (String token : tokens) {
if (temp.contains(token.toLowerCase())) {
System.out.println("keyword found: " + token);
} else {
System.out.println("keyword not found: " + token);
}
}
此外,您还希望避免在评论中发布代码,因为它们不会保留其格式并且不可读且不可测试。而是编辑您的原始问题并发表评论以提醒我们进行编辑。
编辑2
根据dspyz:
对于堆栈和队列,当没有任何重要的功能/性能原因使用一个而不是另一个时,您应该默认使用ArrayDeque而不是LinkedList。它通常更快,占用更少的内存,并且需要更少的垃圾回收。
答案 1 :(得分:1)
如果你的文件很小(超过一百万行),你最好只是将这些行复制到一个ArrayList中,然后使用对数组的随机访问来获取下一行和前五行。
有时最好的解决办法就是蛮力。
如果在+ -5行窗口中有两个关键字匹配,那么您的代码会变得棘手。比方说你分开了两行。你翻了两个10行窗户吗?一个12行窗口?
随机访问将使这种方式更容易实现。