Vai al contenuto

Java - Loop infinito lettura dati da file


Messaggi raccomandati

Salve,
mi sto cimentando in un programma che prende degli interi da file, li memorizza in un array e li ordina mediante il metodo per fusione.
Sembrerà strano ma la cosa che più mi sta dando filo da torcere è la lettura da file.
Il mio obiettivo è quello di leggere degli interi in un file dove ci sono parole e numeri ma il problema è che i metodi
hasNext()
e
hasNextInt()

 

sembrano non funzionare e pertanto adesso sto provando semplicemente a leggere degli interi da file.
Posto un pezzo di codice per spiegare meglio la situazione:

Questo è il codice che si occupa di contare quanti numeri ci sono nel file

int numofint = 0; //questa variabile viene creata per poter salvare il numero di interi presenti nel file

while (in.hasNext())
{
   numofint++; //la variabile numofint viene incrementata
} //end of while

Questo ciclo while entra in un loop senza fine.... Non riesco comprendere il motivo...

Il resto del codice che si occupa di inserire gli interi nell'array è:

array = new int[numofint+1];

in.reset(); //reset dello scanner

int i=-1;
while (in.hasNext())
{
   i++;

   array[i] = Integer.parseInt(in.next());

} //end of while

Spero vivamente che qualcuno possa aiutarmi:angiolettoim:

Questo è il codice dell'intero programma (quello scritto fin ora):

package com_antomau_OrdFusRicBin.UserInterface;

import java.util.Scanner;
import javax.swing.*;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.io.*;
import java.util.Arrays;

/**
 * 
 * @author Antonio Maulucci
 *
 */
public class UserOrdFusRicBin {
	
	private static File file; //nuovo file
	
	private static Scanner in; //nuovo scanner
	
	/*
	 * fileLoaded -> verifica che il file sia stato correttaamente caricato
	 * arraySorted -> verifica che l'array sia stato ordinato
	 */
	private static boolean fileLoaded = false;
	private static int[] array;
	
	public static void main(String[] args) {
		
		
		JFrame f = new JFrame("OrdFus-RicBin");
		f.setSize(300, 300);
		f.setLayout(new BorderLayout());
		f.setVisible(true);
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		JPanel fileFinder = new JPanel();
		fileFinder.setLayout(new GridLayout(1,3));
		
		JFileChooser fileChooser = new JFileChooser();
		
		JLabel choosenFileName = new JLabel(""); 
		JButton openFileButton = new JButton("Open database");
		JButton exitButton = new JButton("Exit");
		
		fileFinder.add(choosenFileName);
		fileFinder.add(openFileButton);
		fileFinder.add(exitButton);
		
		
		JPanel contentPanel = new JPanel();
		contentPanel.setLayout(new BorderLayout());
		
		JPanel consolePanel = new JPanel();
		consolePanel.setLayout(new GridLayout(1,4));
		
		JButton printArrayButton = new JButton("Print data");
		JButton sortButton = new JButton("Sort");
		
		consolePanel.add(printArrayButton);
		consolePanel.add(sortButton);
		
		JPanel mainContents = new JPanel();
		
		contentPanel.add(consolePanel, BorderLayout.NORTH);
		contentPanel.add(mainContents, BorderLayout.CENTER);
		
		f.add(fileFinder, BorderLayout.NORTH);
		f.add(contentPanel, BorderLayout.CENTER);
		
		
		f.pack();
		
		class openFileListenerClass implements ActionListener {
			@Override
			public void actionPerformed(ActionEvent e) {
				fileChooser.showOpenDialog(f); //questa istruzione visualizza la finestra di dialogo per la scleta del file all'interno del frame f
				try {
					file = fileChooser.getSelectedFile();
					in = new Scanner(file); //creare uno scanner per il file "file"
					fileLoaded = true; //diventa vera perché il file è stato caricato
					
				} catch (FileNotFoundException ex) {
					ex.printStackTrace();
				} //end of try/catch
				//\\//\\//\\//\\//\\//
				if (fileLoaded)
				{

					int numofint = 0; //questa variabile viene creata per poter salvare il numero di interi presenti nel file

					while (in.hasNext())
					{
						numofint++; //la variabile values viene incrementata
					} //end of while

					array = new int[numofint+1];

					in.reset(); //reset dello scanner

					int i=-1;
					while (in.hasNext())
					{
						i++;

						array[i] = Integer.parseInt(in.next());

					} //end of while

				} //end of if fileLoaded
				//\\//\\//\\//\\//\\//
				choosenFileName.setText(fileChooser.getName(file));
			}
		} //end of selectFileListenerClass
		
		ActionListener openFileListener = new openFileListenerClass();
		openFileButton.addActionListener(openFileListener);
		
		
		class exitListenerClass implements ActionListener {
			@Override
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		} //end of openFileListenerClass
		
		ActionListener exitListener = new exitListenerClass();
		exitButton.addActionListener(exitListener);
		
		class printDataButtonListenerClass implements ActionListener {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (fileLoaded) {
					mainContents.removeAll();
					JLabel printArrayLabel = new JLabel(Arrays.toString(array));
					mainContents.add(printArrayLabel);
					f.pack();
				} //end of if
			}
		} //end of openFileListenerClass
		
		ActionListener printDataListener = new printDataButtonListenerClass();
		printArrayButton.addActionListener(printDataListener);
		
	} //end of main

} //end of class

Altri modi in cui ho provato ad implementare la lettura del numero di token e ad inserire questi nell'array sono stati:

metodo 1

if (fileLoaded) { //linea 93
   int[] k = new int[256];
   int i=-1;
   while (in.hasNext())
   {
      i++;
      k[i] = in.nextInt();
      System.out.print(i + " "); //debug
   } //end of while
   System.out.println("i = " + i); //debug
   array = new int[i+1];
   for (int j=0; j<i; j++) {
      array[i] = k[i];
   }
   System.out.println(Arrays.toString(array)); //debug
} //end of if

metodo 2

if (fileLoaded) { //linea 93
               //questa variabile salva il numero di elementi che dovrà contenere l'array di interi
               int values=0;
               while (in.hasNext()) values++;
               array = new int[values-1]; //l'array "array" viene inzializzato con n-1 posizioni dove n sono gli elementi da inserire (values) (n-1 perché le posizioni dell'array partono da 0, per 3 elementi servono 2 posizioni perché 0,1,2)
               int i = -1; //indice dell'array in cui inserire il dato corrente (vedi commento di "i++" per comprendere perché il suo valore è (-1)
               while (in.hasNext()) { // questo ciclo while verifica che nel file ci sia un dato successivo a quello seguente
                  if (in.hasNextInt()) {
                     /*
                      * l'indice dell'array viene incrementato per permettere di inserire il dato nel nuovo indice dell'array
                      * esso viene inzializzato a -1 per fare in modo che l'indice i sia incrementato prima dell'inserimento del nuovo dato
                      *  questo modo si fa prima corrispondere l'indice alla posizione corretta dell'elemento da inserire
                      *  e poi si inserisce l'elemento
                      *  altrimenti avverrebbe che all'ultimo intero il dato verebbe inserito e poi verrebbe incrementato l'indice verso una posizione inesistente il che genererebbe un errore
                      */
                     i++;
                     System.out.println("debug - i is = " + i + " /// in.nextint is = " + in.nextInt());
                     array[i] = in.nextInt(); //nella posizione i dell'array viene inserto il numero intero
                  } //end of if
               } //end of while
               //
            } //end of if

metodo 3

if (fileLoaded)
{
   in.reset(); //debug
   int values = 0;
   while (in.hasNextInt())
   {
      System.out.println("i'm incrementing values"); //debug
      values++;
      System.out.println("now values is = " + values); //debug
      if (in.hasNext()) System.out.println("next value is = " + in.next()); //debug
   } //end of while
   System.out.println("at end of while value of values is = " + values); //debug
   array = new int[values+1];
   int i = -1;
   try {
      in = new Scanner(file);
   } catch(Exception ex) {
      System.out.println("unable to make scanner"); //debug
   }
   /*
   while (in.hasNextInt()) //risulta essere falso
   {
      i++;
      System.out.println("after incrementing i it's = " + i); //debug
      array[i] = in.nextInt();
      System.out.println("ending while i is = " + i + " and nextInt is = " + in.nextInt()); //debug
   } //end of while
   */
   while(in.hasNextInt())
   {
      i++;
      System.out.println("after incrementing i it's = " + i); //debug
      array[i] = in.nextInt();
      System.out.println("ending while i is = " + i + " and nextInt is = " + in.nextInt()); //debug
   } //end of while
} //end of if fileloaded

 

Link al commento
Condividi su altri siti

Ciao. Ho provato il tuo programma e il problema è molto più semplice di quel che sembra.

tu usi hasNext() credendo che java incrementi il valore ad ogni ciclo... ma in realtà hasNext() ritorna solo true quando ci sono ancora parole nello Scanner e false quando non ce ne sono, ma non incrementa l'index e quindi non passa alla parola successiva.

Per incrementare l'index e passare quindi alla parola successiva dovresti fare qualcosa tipo in.next().

In questa maniera il programma non si blocca nel ciclo loop.

Poi ci sono altri problemi (provando a fare il print l'array indica tutti zeri, quindi è probabile che tu non salvi ciò che leggi nel tuo array... ma onestamente non ho analizzato tutto il codice al momento... se vuoi che lo faccia dimmi pure), però intanto il loop infinito non c'è più.

PS. Per l'altro problema stai utilizzando in.reset() pensando di poter resettare la posizione dello Scanner all'inizio del file (in realtà serve a tutt'altro). Dovresti usare una List/ArrayList (così da non dover contare il numero di elementi e poter immediatamente mettere tutto all'interno del tuo "array") oppure creare 2 scanner al posto di uno solo.

PS2. Il sort mi pare non sia stato ancora implementato, quindi direi che aggiustando queste due cose sei a posto

tanto per capirci qualcosa del genere (dove temp è un altro Scanner. puoi sostituire tutto con un unico while/for se usi una List/ArrayList al posto di un array standard):

int numofint = 0;
                    
while (temp.hasNext()){
	temp.next();
	numofint++;
}
                    
array = new int[numofint+1];
                    
int i=-1;
while (in.hasNext()){
	i++;                    
	array[i] = Integer.parseInt(in.next());
}

PS3. Ho provato a fare un paio di aggiunte. Prima di tutto ho aggiunto un metodo che controlla se l'input è un intero:

public static boolean isParsable(String input){
   boolean parsable = true;
   try{
   	Integer.parseInt(input);
   }catch(NumberFormatException e){
   	parsable = false;
   }
   return parsable;
}

Poi aggiungendo altri 2 Scanner nel primo while incremento numofint++; solo se if(isParsable(scanner.next()))

Nel secondo while se if(isParsable(altroScanner.next())){ allora i++; e array = Integer.parseInt(in.next()); else in.next();

Inoltre ho array = new int[numofint]; tolto l'elemento in più nell'array che non serviva.

Con questo la stampa degli elementi è solo degli interi. Mentre le eventuali lettere/altri caratteri vengono ignorati. Inoltre l'array non contiene nessun elemento in più. Ora ti basta davvero solo aggiungere il codice per ordinare e sei a posto.

Comunque il tuo programma mi ha divertito. Però ti consiglio di dividere il codice in classi... un'unico main diventa difficile da leggere.

Link al commento
Condividi su altri siti

Archiviato

Questa discussione è archiviata e chiusa a future risposte.

×
×
  • Crea Nuovo...