Java Scanner打印上一行和下一行

时间:2013-07-18 21:53:49

标签: java java.util.scanner

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

2 个答案:

答案 0 :(得分:2)

  

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

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

其他建议:

  • 您的扫描仪检查scanner.hasNextXXX()方法应与get方法scanner.nextXXX()匹配。因此,如果您打算致电hasNextLine(),请检查nextLine()。否则你会冒问题。
  • 请尝试在您的问题中发布真实代码,而不是排序,永远不会编译代码。即,system.out.println vs System.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。它通常更快,占用更少的内存,并且需要更少的垃圾回收。

答案 1 :(得分:1)

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

有时最好的解决办法就是蛮力。

如果在+ -5行窗口中有两个关键字匹配,那么您的代码会变得棘手。比方说你分开了两行。你翻了两个10行窗户吗?一个12行窗口?

随机访问将使这种方式更容易实现。