3

我正在使用“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 行的指针..?

4

2 回答 2

3

任何打印前 5 行的指针..?

  • 将它们保存在Dequeue<String>诸如LinkedList<String>“先进先出 (FIFO)”行为之类的文件中。
  • 要么使用 5 个变量或 5 个字符串的数组,手动将字符串从一个插槽或变量移动到另一个,然后打印它们。
  • 如果您使用 Dequeue/LinkedList,请使用 Dequeue 的addFirst(...)方法在开头添加一个新字符串并removeLast()删除列表的最后一个字符串(如果其大小 > 5)。遍历 LinkedList 以获取它包含的当前字符串。

其他建议:

  • 您的 Scanner 的检查scanner.hasNextXXX()方法应与 get 方法匹配,scanner.nextXXX(). 所以你应该检查hasNextLine()你是否要打电话nextLine()。否则,您将面临问题。
  • 请尝试在您的问题中发布真实代码,而不是某种,永远不会编译代码。即,system.out.printlnSystem.out.println. 我知道这是一件小事,但是当其他人尝试使用您的代码时,这意味着很多。
  • 使用 ArrayList 的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。它通常更快,占用更少的内存,并且需要更少的垃圾收集。

于 2013-07-18T21:55:14.177 回答
1

如果您的文件很小(<一百万行),您最好将这些行复制到一个 ArrayList 中,然后使用随机访问数组来获取下一个和前 5 行。

有时最好的解决方案就是简单的蛮力。

如果您的 +-5 行窗口中有两个关键字命中,您的代码将会变得棘手。假设你有两行分开。你转储两个 10 行窗口吗?一个 12 行窗口?

随机访问将使实现这些东西更容易。

于 2013-07-19T02:24:37.260 回答