There is a text file that stores session data:

1542384078773 668873060 236.215.100.166 1542384079774 161963738 194.42.176.2 1542384080774 378627692 37.138.100.42 1542384081774 335983167 254.241.160.5 1542384082774 798168250 68.167.208.123 

And so on, here in each line the first number is the time of the session start in a millisecond format (since the beginning of 1970), the second number is a randomly generated 9-bit session ID, the third is an IP address.

The task is to rewrite this file, removing data about sessions older than three days from it, for example.

How can we allocate the first number in each row in order to determine whether we delete the row with this session (it is older than three days) or not?

 public void createNewListOfSessions(int ageInDays) { while (scanner.hasNext()) { Date date = new Date(System.currentTimeMillis()); if (Long.parseLong(scanner.nextLine().split(" ").get(0)) > (date.getTime() - 3 * 24 * 60 * 60 * 1000)) { SessionData session = new SessionData(); session.setSessionStartTime(Long.parseLong(scanner.next())); session.setSessionID(scanner.next()); session.setSessionIP(scanner.next()); sessionsCounter++; scannedSessions.add(session); } } } 

Here I tried to allocate the first number of each line through scanner.nextLine().split(" ").get(0) , but this is incorrect. How to highlight this number?

As a result, the following 100% working method was obtained:

 public void createNewListOfSessions(int ageInDays) { while (scanner.hasNext()) { Date date = new Date(System.currentTimeMillis()); String[] current = scanner.nextLine().split("\\s+"); for (String subCurrent : current) { if ("".equals(subCurrent)) { continue; } } Long sessionStartTime = Long.parseLong(current[0].trim()); if (sessionStartTime > (date.getTime() - ageInDays * 24 * 60 * 60 * 1000)) { SessionData session = new SessionData(); session.setSessionStartTime(sessionStartTime); session.setSessionID(current[1]); session.setSessionIP(current[2]); sessionsCounter++; scannedSessions.add(session); } } } 
  • Why wrong? - Enikeyschik
  • Cannot invoke get (int) on the array type String [] - says Eclipse and underlines in red. - Vitaliy Tretyakov
  • can still with the help of regular expressions ... - Muzaffar Rasulov

2 answers 2

Here I tried to allocate the first number of each line through scanner.nextLine (). Split ("") .get (0), but this is incorrect. How to highlight this number?

Why wrong? That's right, only you get so that you read the entire line, for the sake of a single number, and your cursor / pointer in the file has already read this line, respectively, the subsequent call to scanner.next() already refers to the next line. Well, yes, and the arrays do not have a get method, the elements are accessed using the [] operator.

 if (Long.parseLong(scanner.nextLine().split(" ").get(0)) > (date.getTime() - 3 * 24 * 60 * 60 * 1000)) { 

Here inside if you read the following line to the end ( scanner.nextLine() ):

 1542384078773 668873060 236.215.100.166 

And further along the code, you probably expect that you are counted on the new value of the first line , but this is not the case ; you will have to read the second line already.

 session.setSessionStartTime(Long.parseLong(scanner.next())); //читается 1542384079774 session.setSessionID(scanner.next()); //читается 161963738 session.setSessionIP(scanner.next()); //читается 194.42.176.2 

To prevent this from happening, it is more convenient to read the line once and save it, split it into split parts, and work with them already, for example:

 while (scanner.hasNext()) { Date date = new Date(System.currentTimeMillis()); String[] current = scanner.nextLine().split(" "); if (Long.parseLong(current[0]) > (date.getTime() - 3 * 24 * 60 * 60 * 1000)) { SessionData session = new SessionData(); session.setSessionStartTime(Long.parseLong(current[0])); session.setSessionID(current[1]); session.setSessionIP(current[2]); sessionsCounter++; scannedSessions.add(session); } } 

Also, try to get rid of the same repeated actions in your code.

 Long.parseLong(current[0]) 

You parse a number from the same line twice in a row, in the if and right there in the set method. What for? It is enough to do it once:

 String[] current = scanner.nextLine().split(" "); String sessionStartTime = Long.parseLong(current[0]); if (sessiongStartTime > ...) { ... session.setSessionStartTime(sessionStartTime); ... } 
  • Thank. But when executing somewhere, an empty string is produced or there is a space after the 'split' action and an error is received: Exception in thread "java.lang.NumberFormatException" For input string: "" at java.lang.NumberFormatException.forInputString (NumberFormatException. java: 65) at java.lang.Long.parseLong (Long.java:601) at java.lang.Long.parseLong (Long.java:631) Looked here: stackoverflow.com/questions/27597841/… - Vitaliy Tretyakov
  • It is necessary to watch your data format. If he is like the example in question, without extra spaces and whitespace, then everything should be fine. Apparently you have deviations from this format. Since you get an empty string somewhere, after split, it’s likely that there are extra spaces somewhere. You can try to call split with regular split("\\s+") or filter the resulting array after split into blank lines. - iksuy
  • Using .split ("\\ s +") did not help. Even adding .trim () didn't help - Long sessionStartTime = Long.parseLong (current [0] .trim ()). Apparently, we really need to filter the resulting array into empty lines ... - Vitaliy Tretyakov
  • Well, you can still do as you did before, read the tokens by the next method, but save the first value - iksuy
  • one
    Everything won the problem! - Vitaliy Tretyakov

To properly read a string, it is better to use some BufferedReader

 BufferedReader reader = new BufferedReader(new FileReader(new File(".../foo.txt"))); String session = ""; if (reader.ready()) session = reader.readLine(); reader.close(); 

The easiest way to parse this option is to use substring :

 String timeStr = session.substring(0, session.indexOf(" ")); 

The Date class is now considered obsolete, at a minimum, and it does not implement many useful functions for working with time and dates. It is better to work with new classes like LocalDateTime . For example, we can easily round up the time of interest to us to the day.

  // получаем объект времени сессии LocalDateTime sessionDate = Instant.ofEpochMilli(Long.parseLong(timeStr)) .atZone(ZoneId.systemDefault()) .toLocalDateTime(); // округляем до целого дня (если нужно) sessionDate = sessionDate.truncatedTo(ChronoUnit.DAYS); System.out.println(sessionDate); // проверяем // получаем объект референсного времени, до которого надо все отфильтровать LocalDateTime requestDate = LocalDateTime.now().minusDays(3); // дней назад requestDate = requestDate.truncatedTo(ChronoUnit.DAYS); System.out.println(requestDate); // проверяем // сравниваем эти два объекта и что то делаем, например перезаписываем строку в другой файл if (sessionDate.isAfter(requestDate)) { // do something System.out.println("+++++++ date is valid"); } 

Do not forget to specify Locale , and you will be able to handle date / time objects more easily and more flexibly.