Zadanie na wyrażenia regularne

0

Witam, kolejne zadanie kolejny problem.

Potrzebuje zaczytać dane z pliku tekstowego, a następnie znaleźć wśród nich wyrażenia regularne (do tego momentu nie mam problemów). A następnie na podstawie odczytanej linii zainicjować konstruktor innej klasy... (i tu odpadam)

Ale po kolei:
Pierwszy krok - utwórz klasę wiadomość (jej pola i konstruktor). Klasę Wiadomość utworzyłem trochę okrojoną, wychodzę z założenia że jak rozwiąże problem inicjowania konstruktora linia odczytaną z pliku, to ją rozbuduje do pełnego wymiaru, tak jak jest wymagane w zadaniu).

Klasa Wiadomosc ma pola
int dzien;
int miesiac;
int rok;
String godzina;
//String user; - o to na razie sobie uprościłem
//String ip; - o to na razie sobie uprościłem
//String tekst; - o to na razie sobie uprościłem


public class Wiadomosc {
	int dzien;
	int miesiac;
	int rok;
	String godzina;
	//String user;
	//String ip;
	//String tekst;
	
	Wiadomosc(int dzien, int miesiac, int rok, String godzina){
		this.dzien = dzien;
		this.miesiac = miesiac;
		this.rok = rok;
		this.godzina = godzina;
	}
	
}

Wczytaj zawartosc pliku serverLog.txt podziel dane tak, żeby kazda linia inicjowała wspomiany obiekt klasy Wiadomość...
W kolejnym kroku umieść obiekt w kolekcji ArrayList.
Na koniec mam utworzyć trzy metody do wświetlania wszystkich wiadomosci z danego dnia, miesiąca bądx adresu IP.

Przykładowe wiersze z pliku ServerLog.txt:

10 6/23/2006 809 AM - (not logged in) (10.0.2.143)> Connected, sending welcome message...
11 6/23/2006 809 AM - (not logged in) (10.0.2.143)> 220-FileZilla Server version 0.9.18 beta

public class WiadomoscTest {

	public static void main(String[] args) {
		
		ArrayList<String> lista = new ArrayList();
	
		StringBuilder sb = new StringBuilder();
		File file = new File("ServerLog.txt");
		try{
			FileInputStream fis = new FileInputStream(file);
			int tmp;
			while((tmp = fis.read()) != -1){
				sb.append((char) tmp);
			}
			fis.close();
			
		} catch (FileNotFoundException e){
			e.printStackTrace();
		} catch (IOException e){
			e.printStackTrace();
		}
		//poniżej okrojony pattern na dzien miesiac rok i godzine.			 
		Pattern p = Pattern.compile("([0-9]{1,2})/([0-9]{2})/([0-9]{4}) (([0-9]{1,2}:){2}[0-9]{2} [A-Z]{2})");
		Matcher m = p.matcher(sb.toString());
		
		for(int i = 0;i <= lista.size();i++){
			while(m.find()){
                         //poniżej mam błąd... czy jest możliwość uruchomienia w ten sposób niejako dynamicznie tworzonego konstruktora klasy Wiadomosc?
				lista.add(new Wiadomosc("Int " +  m.group(1) + "," + "Int " +  m.group(2) + "," + "Int " +  m.group(3) + "," + "String " +  m.group(4)));// = m.group("wiadomosc");
				System.out.println(lista.get(i));
			
			}
		}
	}
}

Problem mam jak napisałem wyżej w komentarzu, z uruchomieniem konstruktora podając mu jako argumenty odczytane dane.
Pytanie do bardziej doświadczonych, czy dobrze kombinuje, czy to jest w ogóle ślepa uliczka i powinienem pójść w innym kierunku?
Jeżeli tak, to jak się powinno zgodnie ze sztuką rozwiązać taki problem?

1

Jak Masz nie mieć błędu, skoro tutaj new Wiadomosc("Int " + m.group(1) + "," + "Int " + m.group(2) + "," + "Int " + m.group(3) + "," + "String " + m.group(4)) Podajesz konstruktorowi jeden argument(Stringa), a on przyjmuje, cztery (trzy inty i String). Musisz sparsować te informacje wyłuskane regexem do odpowiedniego typu i podać konstruktorowi, to będzie działać.

0
lion137 napisał(a):

Jak Masz nie mieć błędu, skoro tutaj new Wiadomosc("Int " + m.group(1) + "," + "Int " + m.group(2) + "," + "Int " + m.group(3) + "," + "String " + m.group(4)) Podajesz konstruktorowi jeden argument(Stringa), a on przyjmuje, cztery (trzy inty i String). Musisz sparsować te informacje wyłuskane regexem do odpowiedniego typu i podać konstruktorowi, to będzie działać.

Zmieniłem zgodnie z sugestią i bangla aż miło!

for(int i = 0;i <= lista.size();i++){
			while(m.find()){
				lista.add(String.valueOf(new Wiadomosc(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)),  Integer.parseInt(m.group(3)), m.group(4))));// = m.group("wiadomosc");
				System.out.println(lista.get(i));

Tylko w klasie Wiadomosc trzeba było jeszcze przeciazyc metodę toString();
Wielkie dzięki za pomoc @lion137!

0

Może mi ktoś wytłumaczyć dlaczego nie działa mi poniższy regex:
Wszystko działało pięknie do momentu kiedy dodałem w regex grupa("ip") oraz grupa("wiadomosc")
dodam tylko, że obie grupy jeżeli uruchamiam je samodzielnie a nie w ponizszym kodzie działają swietnie...
Ze zmian vs wersja poptrzednia to arrayList jest typu Wiadomosc a nie string, ale to nie powinno mieć wpływu, ponieważ tak jak wspominałem wcześniej bez IP i Wiadomosci dzialało ok.

		Pattern p = Pattern.compile("([0-9]{1,2})/([0-9]{2})/([0-9]{4}) (?<data>([0-9]{1,2}:){2}[0-9]{2} [A-Z]{2}) - (?<user>\\(?([a-z]{2,} ?){2,} ?\\)?) (?<ip>([0-9]{1,3}\\.){3}[0-9]{3}) ?>(?<wiadomosc>[^\n]*)\r?\n");// >(?<wiadomosc>[^\n]*)\r?\n");// pattern wybierający wiadomosc
		Matcher m = p.matcher(sb.toString());
		
		//System.out.println(m.group(1)+"\n"+m.group(2)+"\n"+m.group(3)+"\n"+m.group(4));
		
		for(int i = 0;i <= lista.size();i++){
			if(m.find()){// musi być if, bo przy while w jednej iteracji petli przeliatuje przez cały ServerLog, tak, że na drugą interacje już nic nie zostaje
				lista.add(new Wiadomosc(Integer.parseInt(m.group(1)), Integer.parseInt(m.group(2)),  Integer.parseInt(m.group(3)), m.group("data"), m.group("user"), m.group("ip"), m.group("wiadomosc")));//, m.group("wiadomosc")));// = m.group("wiadomosc");
				System.out.println(lista.get(i));
1

Twój regex nie znajduje takiego ip: 172.16.254.1, za to ten: https://regex101.com/r/JMxdBt/1 tak.
Regex wiadomosc, nie wiem jak on Ci działa, musi być jakaś literówka gdzieś, bo on ma niezamknięty nawias prawy: [^\n]*)\r?\n, Sprawdź to jeszcze raz czy z tą składnią jest wszystko OK.

1 użytkowników online, w tym zalogowanych: 0, gości: 1