Odczyt z pliku do tablicy

Odczyt z pliku do tablicy
BA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 6 lat
  • Postów:7
0

Witam,
męczę się już solidne parę godzin nad prostym projektem z Javy, jestem początkujący i błędy chyba mogą się zdarzać. Chcę zrobić odczyt danych z pliku i przyporządkować je odpowiednim komórkom tablicy powiązanych z klasą Pracownik. Klasa pracownik składa się ze stringa nazwisko, integera pensja i booleana urlop. Chcę to zrobić za pomocą Scannera i nie wiem czy to odpowiednie podejście. Nie wiem czy zły jest mój odpowiednik EOF w C czy błąd leży gdzieś indziej. Ułatwiając sobie pracę zapisuję kolejne dane w nowych liniach pliku (zapis działa bez problemu). Odczyt dla jednego pracownika bez tego while działał dobrze i dobrze przypisywał więc gdzieś tam dopatruję się błędu. Kompilator wypluwa:

Exception in thread "main" java.lang.NullPointerException.

Fragment mojego kodu z funkcją odczytu.

Kopiuj
static void odczytPlik() {
		String nazw;
		int pen;
		boolean url;
		int i=0;
		
		File plik = new File("odczyt.txt");
		
		try {
			odczyt = new Scanner(plik);
		} catch (FileNotFoundException e) {
			System.out.println("Błąd odczytu pliku!");
		}
		
		while(odczyt.hasNextLine()){
			nazw = odczyt.nextLine();
			pen = odczyt.nextInt();
			url = odczyt.hasNext();
			
			praca[i].nazwisko = nazw;
			praca[i].pensja = pen;
			praca[i].urlop = url;
			
			i++;
		}
		
		liczba=i;
	}
O1
  • Rejestracja:ponad 14 lat
  • Ostatnio:dzień
1

Tutaj prawdopodobnie jest błąd:

Kopiuj
url = odczyt.hasNext();

Daj

Kopiuj
odczyt.nextBoolean();
edytowany 2x, ostatnio: olek1
BA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 6 lat
  • Postów:7
0

O, na ten błąd nie zwróciłem uwagi, dzięki :)
Jednak cały czas wypluwa ten sam error. Eclipse wskazuje na tą linię kodu

Kopiuj
praca[i].nazwisko = nazw;
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1

Błąd jest wcześniej. W wierszu

Kopiuj
pen = odczyt.nextInt();

podczas odczytywania ostatniego wiersza, jesteś wtedy poza plikiem. Zrób to tak:

Kopiuj
                while(odczyt.hasNextLine()){
                        String line = odczyt.nextLine();
                        Scanner sc = new Scanner(line);
                        nazwa = sc.next();
                        pen = sc.nextInt();
                        url = sc.nextBoolean();
 
                        praca[i].nazwisko = nazw;
                        praca[i].pensja = pen;
                        praca[i].urlop = url;
 
                        i++;
                }

Btw, czy http://4programmers.net/Forum/Newbie/151743-metoda_wczytujaca_dane_z_pliku_do_listy, to kolega z grupy.


To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
edytowany 3x, ostatnio: bogdans
0

a sprobuj przy czytaniu nazw dac next(); zamiast nextLine(); :P

bogdans
Poprzedni pytający miał w pliku nazwa : jasiu pensja: 2300 urlop: true i takie proste rozwiązanie by nie przeszło. :D
BA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 6 lat
  • Postów:7
0

Mój plik 'odczyt.txt' wygląda tak:

Kopiuj
Kowalski
3500 
false
Nowak
4000 
false

Po przerobieniu kodu na Twój sposób eclipse podaje takie błędy:

Kopiuj
Exception in thread "main" java.util.NoSuchElementException
	at java.util.Scanner.throwFor(Unknown Source)
	at java.util.Scanner.next(Unknown Source)
	at java.util.Scanner.nextInt(Unknown Source)
	at java.util.Scanner.nextInt(Unknown Source)
	at Obsluga.odczytPlik(Obsluga.java:97)

Linia 97 to:

Kopiuj
pen = sc.nextInt();

Z tego co rozumiem to nie do końca łapie powiązanie Scannera sc z plikiem .txt?
Nie do końca też rozumiem czemu te instrukcje wychodzą poza plik. Myślałem, że działają mniej więcej w ten sposób:

Kopiuj
while (sprawdza czy istnieje w pliku następna linia) {
 trzy kolejne instrukcje czytają trzy kolejne linie w pliku
 wpisują wartości tych linijek do tablicy
 zwiększenie i
}

więc kiedy nie ma następnej linii to ten while powinien się zakończyć. Gdzie jest błąd w moim rozumowaniu? :)

ah, no i tamten ktoś to raczej nie kolega z grupy, podobieństwo zadania każe myśleć, że może ktoś z roku.

edytowany 1x, ostatnio: Bartush
dam1an
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa
  • Postów:1589
0

A pokaż jak i gdzie inicjujesz tablice praca.

bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1
  1. Wypadało strukturę pliku podać od razu.
  2. Błędnie zakładasz, że metoda nextBoolean() czyta wszystko, łącznie z końcem linii. A to nieprawda.
Kopiuj
                while(odczyt.hasNextLine()){
                        nazw = odczyt.nextLine();
                        pen = odczyt.nextInt();
                        url = odczyt.hasNextBoolean();
                        odczyt.nextLine(); //odczytanie końca wiersza
 
                        praca[i].nazwisko = nazw;
                        praca[i].pensja = pen;
                        praca[i].urlop = url;
 
                        i++;
                }

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
edytowany 1x, ostatnio: bogdans
BA
Dziękuję za wszystkie uwagi, myślałem, że strukturę pliku można było wywnioskować po pierwszym poście. O nextBoolean nie wiedziałem.
BA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 6 lat
  • Postów:7
0

Klasa Obsługa

Kopiuj
import java.io.*;
import java.util.*;

public class Obsluga {
	
	static int liczba=0;
	
	static Pracownik[] praca = new Pracownik[10];
	
	private static Scanner czyt;
	private static Scanner odczyt;
	private static PrintWriter zapis;
	
	static void wyswietlMenu(){
	(...)
	}
	
	static void wyswietlPracownika(){
	(...)
	}
	
	static void dodajPracownika(){
	(...)
	}

	
	static void podwyzkaPracownik(){
	(...)
	}
	
	static void urlopPracownik(){
	(...)
	}
	
	static void odczytPlik() throws FileNotFoundException {
		String nazw;
		int pen;
		boolean url;
		int i=0;
		
		File plik = new File("raport.txt");
		odczyt = new Scanner(plik);
		
		while(odczyt.hasNextLine()){
			nazw = odczyt.nextLine();
			pen = odczyt.nextInt();
			url = odczyt.hasNextBoolean();
			odczyt.nextLine(); //odczytanie końca wiersza

			praca[i].nazwisko = nazw;
			praca[i].pensja = pen;
			praca[i].urlop = url;

			i++;
		}	
		
		liczba=i;
	}
	
	static void zapisPlik() throws FileNotFoundException{
		int i;
		
		zapis = new PrintWriter("raport.txt");
		for(i=0;i<liczba;i++){
			zapis.println("" + praca[i].nazwisko);
			zapis.println("" + praca[i].pensja); 
			zapis.println("" + praca[i].urlop);
		}
		zapis.close();
	}
	
	public static void main(String[] args) throws IOException {
	
		boolean x=true;
		Scanner wybor;

		odczytPlik();
		
		while(x){
			wyswietlMenu();
			System.out.print("Twoj wybor: ");
			wybor = new Scanner(System.in);
			char c = wybor.next().charAt(0);
			
			switch(c){
			case 'a': wyswietlPracownika(); break;
			case 'b': dodajPracownika(); break;
			case 'c': podwyzkaPracownik(); break;
			case 'd': urlopPracownik(); break;
			case 'e' : zapisPlik(); break;
			case 'x': x=false; break;
			default: break;
			}
		
		}
		
	}

}

Błędy dotyczą:

Kopiuj
 
Exception in thread "main" java.lang.NullPointerException
	at Obsluga.odczytPlik(Obsluga.java:93) // praca[i].nazwisko = nazw;
	at Obsluga.main(Obsluga.java:123) // odczytPlik();

Do tego klasa Pracownik:

Kopiuj
public class Pracownik {

	public Pracownik(String string, int i, boolean b) {
		// TODO Auto-generated constructor stub
		nazwisko=string;
		pensja=i;
		urlop=b;
	}
	
	String nazwisko;
	int pensja;
	boolean urlop;	
	
}

Nie mam pomysłu co więcej mogę poprawić w odczytywaniu danych z pliku tak więc może błąd leży gdzieś indziej. Nie widzę spoilerów więc nie wiem jak zmniejszyć kod, żeby nie przeszkadzał.

edytowany 1x, ostatnio: Bartush
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1

Nie widzę nigdzie inicjacji elementów tablicy praca.

Kopiuj
for(int i=0;i<praca.length;i++)
{
    praca[i] = new Pracownik();
}

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
edytowany 1x, ostatnio: bogdans
O1
  • Rejestracja:ponad 14 lat
  • Ostatnio:dzień
1
Kopiuj
         while(odczyt.hasNextLine()){
                 nazw = odczyt.next();
                 pen = odczyt.nextInt();
                 url = odczyt.nextBoolean();
                 praca[i] = new Pracownik();
                 praca[i].nazwisko = nazw;
                 praca[i].pensja = pen;
                 praca[i].urlop = url;

                 i++;
         }  
bogdans
niestety, źle
O1
@bogdans Co źle? Testowałem i u mnie działało prawidłowo. Można dać jeszcze praca[i] = new Pracownik(nazw, pen, url); żeby skrócić zapis.
bogdans
A u mnie nie. Po odczytaniu nextBoolean() z ostatniego wiersza zostaje jeszcze znak przejścia do kolejnego wiersza, zatem hasNextLine() zwraca true, zaczyna się kolejne czytanie, które wyrzuca NoSuchElementException. Można ten wyjątek zignorować, bo wszystko zostało odczytane, ale to jest nieeleganckie.:P
BA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 6 lat
  • Postów:7
0

To rozumiem, że ta część nie spełnia takiej roli?
static Pracownik[] praca = new Pracownik[10];

Wstawiając tego while'a trzeba utworzyć nowy constructor?

dam1an
  • Rejestracja:prawie 12 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Warszawa
  • Postów:1589
0

Tworzysz w ten sposób 10 elementową pustą tablice typu Pracownik.
Kiedy robisz int[] liczby = new int[10]; to czy tablica sama wypełnia?

BA
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad 6 lat
  • Postów:7
0

olek1 - dziękuję bardzo, Twój post wespół z postami bogdans'a otworzył mi oczy i zrozumiałem o co w tym wszystkim chodzi. Właśnie wpadłem na to, że przecież tworząc pracownika robię to w podobny sposób
praca[i] = new Pracownik(nazw, pen, url);

Jeszcze raz dziękuję za całą Waszą pomoc :)

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.