0

So I've got a log file that i need to search for certain strings and print out the lines that fall in between certain date ranges.

Ive got the first part done but im stuck on the second. How would i print out a string within a certain date. so say i want to print all strings between 2012-09-01 and 2012-09-15

Log Example:

 2012-09-13 16:04:22 DEBUG SID:34523 BID:1329 RID:65d33 'Starting new session'
 2012-09-13 16:04:30 DEBUG SID:34523 BID:1329 RID:54f22 'Authenticating User'
 2012-09-13 16:05:30 DEBUG SID:42111 BID:319 RID:65a23 'Starting new session'
 2012-09-13 16:04:50 ERROR SID:34523 BID:1329 RID:54ff3 'Missing Authentication token'
 2012-09-13 16:05:31 DEBUG SID:42111 BID:319 RID:86472 'Authenticating User'
 2012-09-13 16:05:31 DEBUG SID:42111 BID:319 RID:7a323 'Deleting asset with ID 543234'
 2012-09-13 16:05:32 WARN SID:42111 BID:319 RID:7a323 'Invalid asset ID'

This is my code so far:

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Scanner;


public class ReadLogs {

   public static void main(String args[]) throws FileNotFoundException{
       String line, logString ="";
       Date startDate, endDate;

       ArrayList<String> logList = new ArrayList<>();

       Scanner logScanner = new Scanner(new        File("C:\\Users\\cmccarth\\Desktop\\logs.txt"));
       while (logScanner.hasNextLine()) {
            line = logScanner.nextLine();
            logList.add(line);                  
        }

       for (String z : logList) {
//          System.out.println(z);
        }


      // This function prints out all lines containing a specific string

       for( int i = 0; i <= logList.size() - 1; i++)
       {
           logString = logList.get(i);
           if(logString.contains("16:04:22")){
               System.out.println("String Contains" +logString);
           }

       }
   }     
}
Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
CoffeeTime
  • 305
  • 1
  • 6
  • 17
  • split the string to keep the date (look for DEBUG / WARNING / ERROR), parse it, compare with bounds and if of, print the whole line –  Apr 14 '14 at 16:32
  • i'd substring the date (splitting wouldn't be guaranteed), parse it, compare it, print if matches. – patterned Apr 14 '14 at 16:36

3 Answers3

1

Perform the following steps :

1) Create 2 Date objects with the date range you want to search in ( get these dates using Simple date format) :

 Date lowerRange; 
 Date upperRange;

2) Now loop through your filtered log list and okenize the string that you get from the log file and then get the date as tokens[0].

String[] tokens = logString.split(" ");
String dateStr = tokens[0];

// Convert this date to String using Simple Date Format
Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse(dateStr);

3) Now you can compare this date with the 2 dates that you have to see if it falls in the range.

if(date > lowerRange && date < upperRange)
{
  // this is the date you wanted...process the log file entry
}

Refer the following SO post for String to Date conversion : String-to-date

Community
  • 1
  • 1
Kakarot
  • 4,252
  • 2
  • 16
  • 18
  • Why add all that overhead of `split` when you can just `substring`? – patterned Apr 14 '14 at 16:48
  • @patterned You are correct we can substring to extract the date from the String. We can also use regex to make it more robust. – Kakarot Apr 14 '14 at 16:50
  • By using substring/splot we are hardcoding the position where the date is present in the log file. Say if the pattern changes you would have to modify the start-end position of the date extraction algo. Regex would ensure that correct date is extracted irrespective of the changes in the position of the Date string. – Kakarot Apr 14 '14 at 16:57
  • I wouldn't expect the logger to start spitting out a different format, though. If that could happen without you knowing there wouldn't be much you could do to account for all scenarios. It could switch date format, stop inserting new line characters, etc. Either way you have to revist your code. I'd just leave regex out. – patterned Apr 14 '14 at 17:01
  • Regex can take care of all date formats :) But Regex would just complicate this task, lets leave it to substring/split – Kakarot Apr 14 '14 at 17:03
0

Try this sample code.

It is using Calendar, SimpleDateFormat and Pattern.

  • Calendar : to form a start date and end date along with time parameter
  • SimpleDateFormat : to parse a string into date object
  • Pattern : to get a specific pattern of date from the log

Here is the code:

   String[] logs = new String[] {

            "2012-09-13 16:04:22 DEBUG SID:34523 BID:1329 RID:65d33 'Starting new session'",
            "2012-09-13 16:04:30 DEBUG SID:34523 BID:1329 RID:54f22 'Authenticating User'",
            "2012-09-13 16:05:30 DEBUG SID:42111 BID:319 RID:65a23 'Starting new session'",
            "2012-09-13 16:04:50 ERROR SID:34523 BID:1329 RID:54ff3 'Missing Authentication token'",
            "2012-09-13 16:05:31 DEBUG SID:42111 BID:319 RID:86472 'Authenticating User'",
            "2012-09-13 16:05:31 DEBUG SID:42111 BID:319 RID:7a323 'Deleting asset with ID 543234'",
            "2012-09-13 16:05:32 WARN SID:42111 BID:319 RID:7a323 'Invalid asset ID'" };

    List<String> logList = new ArrayList<String>();
    for (String log : logs) {
        logList.add(log);
    }

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, 2012);
    cal.set(Calendar.MONTH, 8);
    cal.set(Calendar.DATE, 13);
    cal.set(Calendar.HOUR_OF_DAY, 16);
    cal.set(Calendar.MINUTE, 4);
    cal.set(Calendar.SECOND, 30);
    cal.set(Calendar.MILLISECOND, 0);

    Date startDate = cal.getTime();

    cal.set(Calendar.MINUTE, 5);
    cal.set(Calendar.SECOND, 31);

    Date endDate = cal.getTime();

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    Pattern pattern = Pattern.compile("^(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})");

    Matcher matcher = null;
    String logString = null;
    Date date = null;
    for (int i = 0; i < logList.size(); i++) {
        logString = logList.get(i);
        matcher = pattern.matcher(logString);

        if (matcher.find()) {
            try {
                date = format.parse(matcher.group());
                if (date.getTime() >= startDate.getTime()
                        && date.getTime() <= endDate.getTime()) {
                    System.out.println(logString);
                }
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }

    }

output: (logs between 2012-09-13 16:04:30 and 2012-09-13 16:05:31 inclusive)

2012-09-13 16:04:30 DEBUG SID:34523 BID:1329 RID:54f22 'Authenticating User'
2012-09-13 16:05:30 DEBUG SID:42111 BID:319 RID:65a23 'Starting new session'
2012-09-13 16:04:50 ERROR SID:34523 BID:1329 RID:54ff3 'Missing Authentication token'
2012-09-13 16:05:31 DEBUG SID:42111 BID:319 RID:86472 'Authenticating User'
2012-09-13 16:05:31 DEBUG SID:42111 BID:319 RID:7a323 'Deleting asset with ID 543234'
Braj
  • 46,415
  • 5
  • 60
  • 76
0

Try this(it works for me):

static void readdata(String startDate, String endDate) throws IOException, ParseException {
        String file = "your file location";
        List<String> logList = new ArrayList<String>();
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line = reader.readLine();
        while (line != null) {
            logList.add(line);
            // read next line
            line = reader.readLine();
        }
        reader.close();

        Pattern pattern = Pattern.compile("([12]\\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01]))");

        Matcher matcher = null;
        String logString = null;
        Date date = null;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        for (int i = 0; i < logList.size(); i++) {
            logString = logList.get(i);
            matcher = pattern.matcher(logString);
            if (matcher.find()) {
                date = format.parse(matcher.group());

                Date st = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse(startDate);
                Date ed = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse(endDate);

                int res = st.compareTo(date);

                if (res <= 0) {

                    if (logString.contains(startDate)) {
                        {
                            System.out.println(logString);
                        }
                        continue;
                    }
                    if (date.after(ed)) {
                        break;
                    }

                    System.out.println(logString);
                }

            }
        }
    }
Jayant
  • 1
  • 1
  • 1
    Thanks for wanting to contribute. Please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat` class. At least not as the first option. And not without any reservation. Today we have so much better in [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) and its `DateTimeFormatter`. – Ole V.V. Jun 04 '19 at 07:29