Wczytywanie danych z pliku - wielopoziomowa pętla

0

Wczytuję dane z pliku.
Mam w nim 3 linie, w których są zapisane współrzędne 8-miu punktów. Współrzędne punktu są przedzielone przecinkami, a dwóch różnych punktów - średnikiem.

public class Odczyt {
	
	Punkt[][] linie = new Punkt[3][9];
	
	public void Odczytaj() throws FileNotFoundException {
		
		File file = new File("linie");
		Scanner in = new Scanner(file);
		
		String zdanie = null;
		String[] splitedZdanie = null;
		String[] splitedPunkt = null;
		
		int i = 0;


		while (in.hasNextLine()){	
			zdanie = in.nextLine();
			splitedZdanie = zdanie.split(";");
			
			
			for(int j=0; j <9; j++)
			{
						splitedPunkt = splitedZdanie[j].split(",");
						
						linie[i][j] = new Punkt(Integer.parseInt(splitedPunkt[0]), Integer.parseInt(splitedPunkt[1]));
						
			}
			i++;		
		}
	}	
}

Do tej pory działa.

Chciałbym każdemu zbiorowi 3-ch linii dodać godzinę, do której jest on przypisany.
Dodaję więc do pliku nad każdym z nich godzinę (tylko 0, 1, 2, ..., 23 - bez minut).
Dodaję więc zmienną

int h = 0;

oraz warunek if(zdanie==Integer.toString(h)

. W klamrze dodaję, że ma następnie wczytać kolejną linię.

```java
public class Odczyt {
	
	Punkt[][] linie = new Punkt[3][9];
	
	public void Odczytaj() throws FileNotFoundException {
		
		File file = new File("linie");
		Scanner in = new Scanner(file);
		
		String zdanie = null;
		String[] splitedZdanie = null;
		String[] splitedPunkt = null;
		
		int h = 0;
		int i = 0;
		
		while (in.hasNextLine()){	
			zdanie = in.nextLine();
			
			if	(zdanie == Integer.toString(h)){
				
				zdanie = in.nextLine();
				splitedZdanie = zdanie.split(";");
			
				for(int j=0; j <9; j++)
				{
							splitedPunkt = splitedZdanie[j].split(",");
						
							linie[i][j] = new Punkt(Integer.parseInt(splitedPunkt[0]),             Integer.parseInt(splitedPunkt[1]));
						
				}
				i++;
			}	
		}
	}	
}

Na razie miałoby umożliwiać wczytanie jednego tylko zbioru linii, któremu odpowiada godzina 0.
W pliku są zatem na razie tylko 4 linijki - 1. - godzina (0), z następne 3 to zbiór linii.

Nie działa i tak.

0

Przemyśl dokładnie ten fragment kodu:

        while (in.hasNextLine()){    
            zdanie = in.nextLine();
 
            if    (zdanie == Integer.toString(h)){
 
                zdanie = in.nextLine();

Co się dzieje gdy ilość linii w pliku jest nieparzysta.
Druga sprawa, Stringi porównuje się inaczej:

if (zdanie.equals(Integer.toString(h)))

Pętla czytająca powinna chyba mieć taka budowę:

        while (in.hasNextLine()){    
            zdanie = in.nextLine();
           //tutaj rozpoznanie godziny
           for(int i=0;i<3;i++){  
               zdanie = in.nextLine();
               ....
           }
        }
0

Zrobiłem tak, a w pliku dałem 2 linie, tablicę zadeklarowałem tak:

Punkt[][] linie = new Punkt[3][9];

Nie działa nadal.

Wywala się przy funkcji rysowania, a jej kod (nic w nim nie zmieniałem) wygląda tak:

public void RysujLinie(Graphics2D g2d) {
	
        int x_1;
        int y_1;
        
        int x_2;
        int y_2;
        
		for(int i = 0; i< odczyt.linie.length; i++)
		{
			System.out.println("WW");
			for(int j = 0; j< odczyt.linie[i].length - 1 ; j++)
			{
				
                x_1 = odczyt.linie[i][j].x;
                y_1 = odczyt.linie[i][j].y;
                 
                x_2 = odczyt.linie[i][j+1].x;
                y_2 = odczyt.linie[i][j+1].y;
                System.out.println( x_1 + "," + y_1 + " -> " + x_2 +","+y_2);
               
                g2d.drawLine(x_1, y_1, x_2, y_2);
         
			}	
		}
	}
0

Wywala się przy funkcji rysowania, a jej kod (nic w nim nie zmieniałem) wygląda tak:

Jakie są objawy wywalania się, co funkcja wypisuje na konsoli, gdzie zadeklarowałeś tablicę linie, jeśli w klasie Odczyt, to podczas rysowania korzystasz z innej tablicy.

0

Włączam program, wyyświetla się obraz, po naciśnięciu butonu jest wywoływana funkcja RysujLinie(Graphics2D).
Oto tekst z konsoli:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at ObrazPanel.RysujLinie(ObrazPanel.java:82)
	at ObrazPanel.paintComponent(ObrazPanel.java:58)
	at javax.swing.JComponent.paint(JComponent.java:1045)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5210)
	at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:295)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1249)
	at javax.swing.JComponent._paintImmediately(JComponent.java:5158)
	at javax.swing.JComponent.paintImmediately(JComponent.java:4969)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:808)
	at javax.swing.RepaintManager$3.run(RepaintManager.java:796)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796)
	at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:769)
	at javax.swing.RepaintManager.prePaintDirtyRegions(RepaintManager.java:718)
	at javax.swing.RepaintManager.access$1100(RepaintManager.java:62)
	at javax.swing.RepaintManager$ProcessingRunnable.run(RepaintManager.java:1677)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
	at java.awt.EventQueue.access$200(EventQueue.java:103)
	at java.awt.EventQueue$3.run(EventQueue.java:694)
	at java.awt.EventQueue$3.run(EventQueue.java:692)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

W kodzie panelu jest wywołany odczyt, więc tablica z liniami jest ta sama.

@Override
	public void paintComponent(Graphics g) {
		
		g2d = (Graphics2D) g;
		
		//narysowanie obrazu z dysku
		g2d.drawImage(diskImage, 0, 0, this);
		try {
			odczyt.Odczytaj();
		} catch (FileNotFoundException e) {
		    throw new RuntimeException(e);
		}
		
		if(rysujLinie){  
            RysujLinie(g2d);
		}
	}

Wcześniej (kiedy było tak, jak napisałem na samej górze), działało.

dodanie znacznika <code class="none"> - @furious programming

0

Zgadywanie jest męczące, daj cały kod klasy Odczyt i zaznacz wiersz 82 w metodzie RysujLinie.

0

Klasa Odczyt jest w całości, a oto klasa ObrazPanel:

public class ObrazPanel extends JPanel {

	protected BufferedImage diskImage;
	private BufferedImage netImage;

	public int panelWidth;
	public int panelHeight;
	
	public Graphics2D g2d;
	
	public Odczyt odczyt = new Odczyt();
	
	public static boolean rysujLinie = false;

	public ObrazPanel() {
		super();
		
		try {

			File imageFile = new File("Mapa.jpg");
			diskImage = ImageIO.read(imageFile);

		} catch (IOException e) {
			System.err.println("Blad odczytu obrazka");
			e.printStackTrace();
		}

		panelWidth = diskImage.getWidth();
		panelHeight = diskImage.getHeight();
		Dimension dimension = new Dimension(panelWidth, panelHeight);
		setPreferredSize(dimension);
	}

	@Override
	public void paintComponent(Graphics g) {
		
		g2d = (Graphics2D) g;
		
		//narysowanie obrazu z dysku
		g2d.drawImage(diskImage, 0, 0, this);
		try {
			odczyt.Odczytaj();
		} catch (FileNotFoundException e) {
		    throw new RuntimeException(e);
		}
		
		if(rysujLinie){  
            RysujLinie(g2d);
		}
	}
	
	protected void RysujLinie(Graphics2D g2d) {
	
        int x_1;
        int y_1;
        
        int x_2;
        int y_2;
        
		for(int i = 0; i< odczyt.linie.length; i++)
		{
			System.out.println("WW");
			for(int j = 0; j< odczyt.linie[i].length - 1 ; j++)
			{
				
                x_1 = odczyt.linie[i][j].x;
                y_1 = odczyt.linie[i][j].y;
                 
                x_2 = odczyt.linie[i][j+1].x;
                y_2 = odczyt.linie[i][j+1].y;
                System.out.println( x_1 + "," + y_1 + " -> " + x_2 +","+y_2);
               
                g2d.drawLine(x_1, y_1, x_2, y_2); //oto 82. wiersz
         
			}	
		}
	}
}
0

Jaja sobie robisz? Gdzie jest pełny i aktualny kod klasy Odczyt?
Twierdzisz, że to

System.out.println( x_1 + "," + y_1 + " -> " + x_2 +","+y_2);

się wykonuje, a tu

g2d.drawLine(x_1, y_1, x_2, y_2);

jest NPE. Nie wierzę.

0

W Odczycie zmieniłem tylko 1. wymiar tablicy na 2, a w pliku wyciąłem ostatnią linijkę, żeby były rysowane 2 linie.

Oto kod:


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


public class Odczyt {
	
	Punkt[][] linie = new Punkt[2][9];
	
	public void Odczytaj() throws FileNotFoundException {
		
		File file = new File("linie");
		Scanner in = new Scanner(file);
		
		String zdanie = null;
		String[] splitedZdanie = null;
		String[] splitedPunkt = null;
		
		int h = 0;
		int i = 0;
		
		while (in.hasNextLine()){	
			zdanie = in.nextLine();
			
			if (zdanie.equals(Integer.toString(h))){
				
				zdanie = in.nextLine();
				splitedZdanie = zdanie.split(";");
			
				for(int j=0; j <9; j++)
				{
							splitedPunkt = splitedZdanie[j].split(",");
						
							linie[i][j] = new Punkt(Integer.parseInt(splitedPunkt[0]), Integer.parseInt(splitedPunkt[1]));
						
				}
				i++;
			}	
		}
	}	
}
1

W pliku linie jest takie coś:

0
1,3;4,6;....
5,7;9,45;...

Czytasz pierwszy wiersz (zdanie.equals("0"))
=> czytasz drugi wiersz i wypełniasz liczbami pierwszy wiersz tablicy linie
czytasz trzeci wiersz (!zdanie.equals("0")) i nic nie robisz.
Drugi wiersz tablicy, to nulle.
Napisałem wcześniej

Pętla czytająca powinna chyba mieć taka budowę:

    while (in.hasNextLine()){    
        zdanie = in.nextLine();
       //tutaj rozpoznanie godziny
       for(int i=0;i<3;i++){  
           zdanie = in.nextLine();
           ....
       }
    }
0
public class Odczyt {
	
	Punkt[][][] linie = new Punkt[24][3][9];
	
	public void Odczytaj() throws FileNotFoundException {
		
		File file = new File("Izolinie(kopia)");
		Scanner in = new Scanner(file);
		
		String zdanie = null;
		String[] splitedZdanie = null;
		String[] splitedPunkt = null;
		
		while (in.hasNextLine()){    
			zdanie = in.nextLine();
		            
		    for (int i = 0; i<24; i++){
		            	
		    	if (zdanie.equals(Integer.toString(i))){
		            	
		            for(int j=0;j<3;j++){
		            		
		            	zdanie = in.nextLine();
		            		
		            	splitedZdanie = zdanie.split(";");
			
		            	for(int k=0; k <9; k++){
		            			
		            		splitedPunkt = splitedZdanie[k].split(",");
						
		            		linie[i][j][k] = new Punkt(Integer.parseInt(splitedPunkt[0]), Integer.parseInt(splitedPunkt[1]));
		            	}
		           
		            }
		        }
	    
		    }
		}	
	}			
}

Zmieniłem tak i wyświetla tylko po pół linii (zmieniałem tylko tą klasę).

Oto schemat krokowy algorytmu pętli:

  1. dopóki jest w pliku następna linia
  2. { wczytaj linię do zdania
  3. jeżeli i {0,...,23) == zdanie
  4.     3x{ wczytaj kolejną linię do zdania
    
  5.       podziel zdanie na podstawie ';'	
    
  6.        8x podziel wynik na podstawie ',' i stwórz nowe punkty w tablicy na podstawie wyniku tego podziału
              }
      }
    
  7. idź do kroku 0.
0
  1. Kto (co) wyświetla pól linii? W klasie Odczyt nie ma wyświetlania, jeśli wyświetlasz w innej klasie, to musiałeś tę klasę zmienić, bo zmieniła się struktura tablicy linie.
  2. Daj link do pliku z danymi: "Izolinie(kopia)".
0

Linie rysuje funkcja RysujLinie, którą zamieściłem na początku tematu. Tablica w niej nie ma jeszcze 3. (czyli w tym wypadku 1.) wymiaru (godzin), ale powinna i tak działać.

Przysięgam, że oprócz Odczytu nic nie zmieniałem.

http://przeklej.org/file/QupxbK/Izolinie.kopia.

1

Nie można pobrać, dodaj plik jako załącznik do postu na forum.
W funkcji rysującej jest takie coś:

x_1 = odczyt.linie[i][j].x;

ale tablica linie jest trójwymiarowa, zatem

odczyt.linie[i][j]

jest tablicą obiektów typu Punkt a nie pojedynczym obiektem. Czym zatem jest odczyt.linie[i][j].x

?
0

Przepraszam, coś zmieniłem.
Dobrze, że nie przysięgałem na głowę.

Zmieniłem jeszcze coś i tak to wygląda teraz:

protected void RysujLinie(Graphics2D g2d) {
		
        int x_1;
        int y_1;
        
        int x_2;
        int y_2;

        for(int h=0; h<24; h++)
        {	
        	for(int i = 0; i< odczyt.linie[h].length; i++)
        	{
        		System.out.println("WW");
        		for(int j = 0; j< odczyt.linie[h][i].length - 1 ; j++)
        		{
				
        			x_1 = odczyt.linie[h][i][j].x;
        			y_1 = odczyt.linie[h][i][j].y;
                 
        			x_2 =  odczyt.linie[h][i][j+1].x;
        			y_2 =  odczyt.linie[h][i][j+1].y;

        			System.out.println( x_1 + "," + y_1 + " -> " + x_2 +","+y_2);
               
        			g2d.drawLine(x_1, y_1, x_2, y_2);
         
        		}	
        	}	
        }
}

Teraz działa jak należy, rysuje całe linie.

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