2013-01-06 47 views
0

我有一個日誌文件列表,我需要找到哪一個具有最新版本的特定行,並且全部或全部都沒有此行。查找具有最新更新信息的文件

在文件中的行是這樣的:

2013/01/06 16:01:00:283 INFO ag.doLog: xxxx xxxx xxxx xxxx 

我需要一條線可以說

xx/xx/xx xx:xx:xx:xxx INFO ag.doLog: the line i need 

我知道如何獲得文件的數組,如果我掃描向後我可以在每個文件中找到最新的最新行(如果存在)。

最大的問題是該文件可能很大(2k行?),我想以相對較快的方式(幾秒鐘)找到該行,因此我樂於提供建議。

個人建議: 如果一個文件在X時間有一行,那麼在X時間之前沒有找到該行的任何文件都不應再被掃描。這將需要同時搜索所有文件,我不知道如何。

Atm代碼中斷,我想如果內存不足。

代碼:

if(files.length>0) { //in case no log files exist 
    System.out.println("files.length: " + files.length); 
    for(int i = 0; i < files.length; i++) { ///for each log file look for string 
     System.out.println("Reading file: " + i + " " + files[i].getName()); 
     RandomAccessFile raf = new RandomAccessFile(files[i].getAbsoluteFile(), "r"); //open log file 
     long lastSegment = raf.length(); //Finds how long is the files 
     lastSegment = raf.length()-5; //Sets a point to start looking 
     String leido = ""; 
     byte array[] = new byte[1024];  
     /* 
     * Going back until we find line or file is empty. 
     */ 
     while(!leido.contains(lineToSearch)||lastSegment>0) { 
      System.out.println("leido: " + leido); 
      raf.seek(lastSegment);   //move the to that point 
      raf.read(array);     //Reads 1024 bytes and saves in array 
      leido = new String(array);  //Saves what is read as a string 
      lastSegment = lastSegment-15; //move the point a little further back 
     } 
     if(lastSegment<0) { 
      raf.seek(leido.indexOf(lineToSearch) - 23); //to make sure we get the date (23 characters long) NOTE: it wont be negative. 
      raf.read(array);     //Reads 1024 bytes and saves in array 
      leido = new String(array);  //make the array into a string 
      Date date = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(leido.substring(0, leido.indexOf(" INFO "))); //get only the date part 
      System.out.println(date); 
      //if date is bigger than the other save file name 
     } 
    } 
} 
+0

這難道不是一種計算科學問題? – Val

回答

1

我發現代碼難以覈實。人們可以將任務分解成向後讀取器,該讀取器從文件結尾開始讀取行。並用它來解析日期線明智。

介意,我不打算對漂亮的代碼,但是這樣的事情:

public class BackwardsReader implements Closeable { 

    private static final int BUFFER_SIZE = 4096; 

    private String charset; 
    private RandomAccessFile raf; 
    private long position; 
    private int readIndex; 
    private byte[] buffer = new byte[BUFFER_SIZE]; 

    /** 
    * @param file a text file. 
    * @param charset with bytes '\r' and '\n' (no wide chars). 
    */ 
    public BackwardsReader(File file, String charset) throws IOException { 
     this.charset = charset; 
     raf = new RandomAccessFile(file, "r"); 
     position = raf.length(); 
    } 

    public String readLine() throws IOException { 
     if (position + readIndex == 0) { 
      raf.close(); 
      raf = null; 
      return null; 
     } 

     String line = ""; 
     for (;;) { // Loop adding blocks without newline '\n'. 

      // Search line start: 

      boolean lineStartFound = false; 
      int lineStartIndex = readIndex; 
      while (lineStartIndex > 0) { 
       if (buffer[lineStartIndex - 1] == (byte)'\n') { 
        lineStartFound = true; 
        break; 
       } 
       --lineStartIndex; 
      } 
      String line2; 
      try { 
       line2 = new String(buffer, lineStartIndex, readIndex - lineStartIndex, 
         charset).replaceFirst("\r?\n?", ""); 
       readIndex = lineStartIndex; 
      } catch (UnsupportedEncodingException ex) { 
       Logger.getLogger(BackwardsReader.class.getName()) 
         .log(Level.SEVERE, null, ex); 
       return null; 
      } 
      line = line2 + line; 
      if (lineStartFound) { 
       --readIndex; 
       break; 
      } 

      // Read a prior block: 

      int toRead = BUFFER_SIZE; 
      if (position - toRead < 0) { 
       toRead = (int) position; 
      } 
      if (toRead == 0) { 
       break; 
      } 
      position -= toRead; 
      raf.seek(position); 
      raf.readFully(buffer, 0, toRead); 
      readIndex = toRead; 
      if (buffer[readIndex - 1] == (byte)'\r') { 
       --readIndex; 
      } 
     } 
     return line; 
    } 

    @Override 
    public void close() throws IOException { 
     if (raf != null) { 
      raf.close(); 
     } 
    } 
} 

以及使用例如:

public static void main(String[] args) { 
    try { 
     File file = new File(args[0]); 
     BackwardsReader reader = new BackwardsReader(file, "UTF-8"); 
     int lineCount = 0; 
     for (;;) { 
      String line = reader.readLine(); 
      if (line == null) { 
       break; 
      } 
      ++lineCount; 
      System.out.println(line); 
     } 
     reader.close(); 
     System.out.println("Lines: " + lineCount); 
    } catch (IOException ex) { 
     Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 
+0

這似乎是答案,抱歉延遲檢查。目前唯一的問題是結束的行「):0。」以某種方式將它們視爲空。檢查atm。 – Juan

+0

該模式必須錯誤;最後應該不重要。也許嘗試'ParsePosition pos = new ParsePosition(0);解析(...,pos)'左右。 –