Początki z javą parsowanie pliku "obiektowo"

Początki z javą parsowanie pliku "obiektowo"
KA
KA
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 5 lat
  • Lokalizacja:Warszawa
  • Postów:1683
0

Hej.
Stworzyłam sobie prostą klasę "Studenci" i w klasie do testów w main()

Kopiuj
ArrayList<Studenci> studenci = new ArrayList<Studenci>();

. Chciałabym teraz wczytać sobie Imię,Nazwisko każdego studenta z pliku i wstawić do odpowiedniego obiektu Student w ArrayList. Jak prawidłowo obiektowo powinnam to zrobić? Stworzyć klasę np. ReadFile i tam metody np. getLineCounter(); getImie(int id); getNazwisko(int id); ? I potem w main() pętlę typu for(i=0;i<readFile.getLineCounter();i++)

Kopiuj
 i po kolei jechać sobie ustawiać? Czy to jest prawidłowe podejście? Tylko wtedy będę musiała w klasie ReadFile utworzyć oddzielne ArrayList<String> na przechowywanie Nazwisk, oddzielne na Imiona tak? Trochę wydajnościowo to kiepsko wygląda chyba :?
Pozdrawiam

PROGRAMY NA ZAMÓWIENIE, ZALICZENIA STUDENCKIE, KONFIGURACJA SERWERÓW, SYSTEMÓW I BAZ DANYCH, STRONY INTERNETOWE, POMOC W PROGRAMOWANIU, POPRAWIENIE I OPTYMALIZACJA APLIKACJI
JAVA, C++, LINUX, WWW, SQL, PYTHON
POSIADAM KOMERCYJNE DOŚWIADCZENIE
TANIO, SZYBKO I PORZĄDNIE
Z KOMENTARZAMI OBJAŚNIAJĄCYMI KOD
PISZ NA PRYWATNĄ WIADOMOŚĆ
CENY JUŻ OD 49,99ZŁ ZA PROGRAM
ZAJMIJ SIĘ TYM CO CIĘ NAPRAWDĘ INTERESUJE!
edytowany 1x, ostatnio: karolinaa
pats
  • Rejestracja:ponad 11 lat
  • Ostatnio:prawie 11 lat
  • Postów:12
1

Ja zawsze robiłem w ten sposób:

Kopiuj
import java.util.*;

class Student {
    private String imie;
    private String nazwisko;

    public Student(String i, String n) {
        imie = i;
        nazwisko = n;
    }

    public String toString() {
        return imie + " " + nazwisko;
    }
}


public class Prog {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList<Student> studenci = new ArrayList<Student>();

        while (sc.hasNext()) {
            String imie = sc.next();
            String nazwisko = sc.next();
            studenci.add(new Student(imie, nazwisko));
        }

        for (Student s: studenci) {
            System.out.println(s);
        }
    }
}

Później wystarczy wywołać java Prog < studenci.txt zakładając, że plik jest poprawny. Można też zmienić wczytywanie tj. zamienić System.in na np. new File("studenci.txt").

Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
1

@karolinaa to zależy jak te dane przechowujesz. No jeśli to coś na wzór "jedna linia - jeden obiekt" to możesz zrobić konstruktor Student który potrafi zrobić studenta na podstawie takiej linii. Jeśli wymaga ona jakichś cudów na kiju, regexpów etc to mozesz zrobić też jakiegoś helpera który w tej konstrukcji będzie pomagał.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
KA
KA
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 5 lat
  • Lokalizacja:Warszawa
  • Postów:1683
0

@Shalom helper... czyli? hmm... jeszcze mam problemy z tą obiektowością mianowicie: co w przypadku jeśli w przyszłości zmienię sobie format pliku? Załóżmy w pierwszej linijce dodam informację o grupie tych studentów, np plik:

Kopiuj
[GRUPA G435C]
[Paweł==Trybson]
[Ania==Duża]
[Wojtek==Jakistam]

Nie chciałabym wtedy rozgrzebywać całego programu.
Czy taka klasa to jest dobry pomysł? zwłaszcza te ArrayList w tej klasie mnie martwią ;/?

Kopiuj
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class FileParse {
	private final static Charset ENCODING = StandardCharsets.UTF_8;
	private final Path FilePath;
	private ArrayList<String> names = new ArrayList<String>();
	private ArrayList<String> surnames = new ArrayList<String>();
	private int recordsCounter = 0;


	public FileParse(String FilePath) {
		this.FilePath = Paths.get(FilePath);
	}

	public String getName(int id) {
		return names.get(id);
	}

	public String getSurname(int id) {
		return surnames.get(id);
	}

	public int getRecordCounter() {
		return recordsCounter;
	}

	public final void parse() throws IOException {
		try {
			Scanner scanner = new Scanner(FilePath,ENCODING.name());
			//w pierwszej linijce pojawiła się informacja o grupie, więc dodaję
			processGroupInfo(scanner.nextLine());
			while (scanner.hasNextLine()){
				processRecord(scanner.nextLine());
			}
		} catch(IOException ex) { System.out.println("do ogarnięcia"); }
	}

	protected void processRecord(String Line) {
		Pattern recordPattern = Pattern.compile("\\[(.*)==(.*)\\]");
		Matcher recordMatcher = recordPattern.matcher(Line);
		if(!recordMatcher.find())
			return;
		names.add(recordsCounter, recordMatcher.group(1));
		surnames.add(recordsCounter, recordMatcher.group(2));
		recordsCounter++;
	}

	/* format pliku zmienił się w pierwszej linii dodam informację
	odnośnie nazwy grupy tych studentów np. [M101] dodaję, więc:
	 */

	private String groupInfo;
	public String getGroupInfo() {
		return groupInfo;
	}

	protected void processGroupInfo(String Line) {
		Pattern groupPattern = Pattern.compile("\\[(.*)\\]");
		Matcher groupMatcher = groupPattern.matcher(Line);
		if(!groupMatcher.find())
			return;
		groupInfo = groupMatcher.group(1);
	}

}

potem przy parsowaniu używam np tylko:

Kopiuj
FileParse test = new FileParse("test.txt");
test.parse();
System.out.println(test.getGroupInfo());
for(i=0;i<test.getRecordCounter();i++)
      records.add(i,new Student(test.getSurname(i),test.getName(i)));

PS
proszę nie zwracać uwagi na głupie nazwy zmiennych czy brak obsługi wyjątków jestem początkująca i chodzi tylko oto jak podejść do takiego zagadnienia prawidłowo.
a i obiekt Student do którego wczytuje Imię i Nazwisko z pliku ma jeszcze inne pola, np. Numer Indeksu - ale to pobieram już z innego miejsca.


PROGRAMY NA ZAMÓWIENIE, ZALICZENIA STUDENCKIE, KONFIGURACJA SERWERÓW, SYSTEMÓW I BAZ DANYCH, STRONY INTERNETOWE, POMOC W PROGRAMOWANIU, POPRAWIENIE I OPTYMALIZACJA APLIKACJI
JAVA, C++, LINUX, WWW, SQL, PYTHON
POSIADAM KOMERCYJNE DOŚWIADCZENIE
TANIO, SZYBKO I PORZĄDNIE
Z KOMENTARZAMI OBJAŚNIAJĄCYMI KOD
PISZ NA PRYWATNĄ WIADOMOŚĆ
CENY JUŻ OD 49,99ZŁ ZA PROGRAM
ZAJMIJ SIĘ TYM CO CIĘ NAPRAWDĘ INTERESUJE!
Shalom
Srsly, ludzie z warsaw shore? Miałem o Tobie lepsze zdanie :P
KA
o jej to fajny rozrywkowy program. oglądam dla beki. niedziela 23:00 - obowiązkowo mtv :)
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

Moim zdaniem takie rozwiązanie jest mega słabe. To już lepiej by było gdyby ten twój parser potrafił jednak sam tworzyć tych studentów, bo w zasadzie to jest taki "transformer" który przetwarza jedną reprezentację obiektów (tekstową w pliku) na inną.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
0

Najlepiej w tym celu skorzystać z normalnej bazy danych albo mechamizmu serializacji (ObjectInputStream i ObjectOutputStream). Ewentualnie bibliotekę Kryo, która ponoć ma znacznie wyższą wydajność.

KA
KA
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 5 lat
  • Lokalizacja:Warszawa
  • Postów:1683
0

@Shalom a mogłabym od razu w tym "parserze" tworzyć ArrayList obiektów klasy Student? i potem zwrócić po prostu tak żebym mogła na tym operować w main()?
@niezalogowany - na razie to chciałam nauczyć się podstaw :)


PROGRAMY NA ZAMÓWIENIE, ZALICZENIA STUDENCKIE, KONFIGURACJA SERWERÓW, SYSTEMÓW I BAZ DANYCH, STRONY INTERNETOWE, POMOC W PROGRAMOWANIU, POPRAWIENIE I OPTYMALIZACJA APLIKACJI
JAVA, C++, LINUX, WWW, SQL, PYTHON
POSIADAM KOMERCYJNE DOŚWIADCZENIE
TANIO, SZYBKO I PORZĄDNIE
Z KOMENTARZAMI OBJAŚNIAJĄCYMI KOD
PISZ NA PRYWATNĄ WIADOMOŚĆ
CENY JUŻ OD 49,99ZŁ ZA PROGRAM
ZAJMIJ SIĘ TYM CO CIĘ NAPRAWDĘ INTERESUJE!
edytowany 1x, ostatnio: karolinaa
pats
  • Rejestracja:ponad 11 lat
  • Ostatnio:prawie 11 lat
  • Postów:12
1

Moim zdaniem, lepiej zrobić osobną klasę, która zawiera dane o studencie, tak jak w moim poprzednim poście. Ta klasa powinna być niezależna od rodzaju wczytywania, bo mogą być różne metody (z pliku, z bazy danych). Helper w tym przypadku jest pomocny i oznacza, aby zrobić dodatkową klasę która wczytuje dane z pliku i zwraca listę studentów. Gdy później będziesz potrzebowała obsłużyć inny format pliku, wystarczy napisać kolejny helper.

KA
łał dzięki! toteż tak zrobię, bo myślałam właśnie podobnie.
KA
KA
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 5 lat
  • Lokalizacja:Warszawa
  • Postów:1683
0

heh ,dobra mam jeszcze dwa pytania (dopiero teraz mam znowu czas na Javę);

  1. Mój projekt składa się z kilku osobnych plików (*.java). W osobnym pliku mam klasę Student, Czy klasę "StudentsFileHelper" tak samo mogę umieścić w osobnym pliku i zrobić ją public?
  2. Czy do "parsowania" z pliku informacji na temat tego pliku (1 wiersz np. Autor, Data spisu), powinnam stworzyć osobną klasę? Np. InfoFileHelper?
Kopiuj
[Jan Nowak - 15.01.2014]
[Paweł==Trybson]
[Ania==Duża]
[Wojtek==Jakistam]

Przejrzałam przed chwilą sobie pobieżnie Single Responsibility Principle, Low Coupling stąd http://www.e-point.pl/_fileserver/item/1500355 i chcę się po prostu upewnić czy prawidłowo obiektowo do tego podchodzę. tak żeby sprzyjało to przyszłej skalowalności aplikacji.
Pozdrawiam i dzieki


PROGRAMY NA ZAMÓWIENIE, ZALICZENIA STUDENCKIE, KONFIGURACJA SERWERÓW, SYSTEMÓW I BAZ DANYCH, STRONY INTERNETOWE, POMOC W PROGRAMOWANIU, POPRAWIENIE I OPTYMALIZACJA APLIKACJI
JAVA, C++, LINUX, WWW, SQL, PYTHON
POSIADAM KOMERCYJNE DOŚWIADCZENIE
TANIO, SZYBKO I PORZĄDNIE
Z KOMENTARZAMI OBJAŚNIAJĄCYMI KOD
PISZ NA PRYWATNĄ WIADOMOŚĆ
CENY JUŻ OD 49,99ZŁ ZA PROGRAM
ZAJMIJ SIĘ TYM CO CIĘ NAPRAWDĘ INTERESUJE!

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.