Visualizzazione dei risultati da 1 a 2 su 2
  1. #1
    Utente di HTML.it
    Registrato dal
    Nov 2012
    Messaggi
    50

    [JAVA] Ordinamento righe di un file di testo. Alcune righe vengono cancellate.

    Salve a tutti. Devo implementare una classe NaturalMergeSort che ordina le linee di un file di testo(in senso lessicografico).
    Il mio problema è che quando leggo il file con varie righe che ho scritto, mi stampa le righe e non me le ordina e alcune volte mi cancella anche alcune righe.
    Il contenuto del mio file test è questo:
    ciao
    zio
    foca
    gilda
    trave
    bocca

    Alla prima esecuzione il programma mi da come risultato:






    trave
    zio
    bocca


    Questo comunque è il codice:
    codice:
    package it.uniba.itps.labinf.lab;
    
    
    
    
    import java.io.File;
    import java.io.IOException;
    import java.io.PrintStream;
    import java.util.Scanner;
    
    
    /**
     * Ordina le linee di un file di testo in senso lessicografico.
     * Utilizza l'algoritmo Natural Merge Sort per l'ordinamento.
     */
    public class NaturalMergeSorter {
    	/**
    	 * Contatore del numero di confronti
    	 */
    	private int compsNum; 
    	
    	/**
    	 * File da ordinare
    	 */
    	private java.io.File fileToSort;
    	
    	/**
    	 * Prefisso del primo file di supporto
    	 */
    	private static String STRATCHA_PREFIX = " SCRATCH-A";
    	
    	/**
    	 * Prefisso del secondo file di supporto
    	 */
    	private static String STRATCHB_PREFIX = " SCRATCH-B";
    	
    	/**
    	 * Il costruttore - specifica il file da ordinare
    	 * 
    	 * @param fileToSort - il File da ordinare
    	 */
    	public NaturalMergeSorter(java.io.File fileToSort) {
    		this.fileToSort = fileToSort;
    		compsNum = 0;
    	}
    	
    	/**
    	 * Confronta due stringhe e aggiorna il contatore di confronti
    	 * 
    	 * @param a - prima stringa del confronto
    	 *        b - seconda stringa del confronto
    	 *        
    	 * @return true se a>b (unsensitive)        
    	 */
    	protected boolean greaterThan(String a, String b) {
    		compsNum ++;
    		if(a.compareToIgnoreCase(b) > 0) return true;
    		else return false;
    	}
    	
    	/**
    	 * Fonde i file scratchA e scratchB in dest.
    	 * La fusione avviene prendendo elementi di scratchA
    	 * e scratchB e inserendo in dest l'elemento minore.
    	 * Quando uno dei due file si esaurisce, si copia il rimanente
    	 * file in dest
    	 * 
    	 * @param scratchA - il primo File da fondere
    	 * 		  scratchB - il secondo File da fondere
    	 *        dest - il file che deve contenere la fusione        
    	 * @return true se il file dest risulta ordinato
    	 * @throws Java.io.IOException      
    	 */
    	private boolean merge(java.io.File scratchA, java.io.File scratchB,
    			java.io.File dest) throws IOException {
    			Scanner scanA = new Scanner(scratchA); //leggo il file A
    			Scanner scanB = new Scanner(scratchB); //leggo il file B
    			PrintStream destStream = new PrintStream(dest); 
    										//dirigo il flusso verso dest
    			
    			String bufferA = "";
    			String bufferB = "";
    			boolean nextA = true; //linee consumamte
    			boolean nextB = true; //linee consumate
    			boolean sorted = true;
    			
    			while(scanA.hasNext() || scanB.hasNext()) {
    				//almeno uno dei due file deve avere linee
    				if(scanA.hasNext() && scanB.hasNext()) {
    					//se entrambi hanno linee, si inserisce in
    					//dest la minore
    					sorted = false;
    					bufferA = nextA ? scanA.nextLine() : bufferA;
    					bufferA = nextB ? scanB.nextLine() : bufferB;
    					nextA = false;
    					nextB = false; //le linee non sono ancora consumate
    					
    					//ora metto il minore in dest
    					if(greaterThan(bufferA, bufferB)) {
    						destStream.println(bufferB);
    						nextB = true;
    					} else {
    						destStream.println(bufferA);
    						nextA = true;
    					} 
    				} else { //uno dei due file è esaurito
    					//bisogna consumare le linee non consumate
    					if(nextA == false) {
    						destStream.println(bufferA);
    					}
    					if(nextB == false) {
    						destStream.println(bufferB);
    					}
    					//poi si scarica il file non esaurito
    					while (scanB.hasNext()) {
    						bufferB = scanB.nextLine();
    						destStream.println(bufferB);
    					}
    					while (scanA.hasNext()) {
    						bufferA = scanA.nextLine();
    						destStream.println(bufferA);
    					}
    				}
    			}
    			destStream.close();
    			scanA.close();
    			scanB.close();
    			
    			return sorted;
    		
    	}
    	
    	/**
    	 * Esegue l'ordinamento del file. Utilizza l'algoritmo 
    	 * Natural Merge Sort per l'ordinamento che opera come suegue:
    	 * <ol>
    	 * <li> Sia F il file da ordinare </li>
    	 * <li> Fintanto che file non è ordinato: 
    	 * 		<ol>
    	 * 		<li> crea due file di supporto A e B </li>
    	 * 		<li> separa il file da ordinare in A e B </li>
    	 * 		<li> fonde i file A e B in F </li>
    	 * 		</ol>
    	 * </li>
    	 * </ol>
    	 * @throws java.io.IOException 
    	 */
    	public void sort() throws java.io.IOException {
    		//fileToSort è il file da ordinare
    		File A, B;
    		boolean sorted = false;
    		compsNum = 0;
    		while(!sorted) {
    			A = new File(fileToSort.getName() + STRATCHA_PREFIX);
    			B = new File(fileToSort.getName() + STRATCHB_PREFIX);
    			
    			split(fileToSort, A, B);
    			sorted = merge(A, B, fileToSort);
    			sorted = true;
    		}
    	}
    	
    	/**
    	 * separa il file source in due file separati
    	 * Il criterio di separazione si basa sulla regola
    	 * che se la linea i è lessicograficamente precedente
    	 * alla linea i+1, allora quest'ultima va nello stesso
    	 * file in cui è inserita la linea i, altrimenti essa
    	 * va memorizzata nell'altro file.
    	 * 
    	 * @param source il file da separare
    	 * @param scratchA il primo file destinazione
    	 * @param scratchB il secondo file destinazione
    	 * @throws IOException
    	 */
    	private void split(java.io.File source, java.io.File scratchA,
    			java.io.File scratchB) throws IOException {
    		
    		PrintStream[] scratchStream = new PrintStream[2];
    		//gli stream sono in posizione 0 e 1 e quindi si può usare 
    		//il complemento per alternarli
    		
    		scratchStream[0] = new PrintStream(scratchA);
    		scratchStream[1] = new PrintStream(scratchB);
    		Scanner inStream = new Scanner(source);
    		
    		String previousString = "";
    		int currentStreamIndex = 0;
    		
    		while(inStream.hasNext()) {
    			String currentString = inStream.nextLine();
    			if(greaterThan(previousString, currentString)) {
    				//switch del file
    				currentStreamIndex = 1 - currentStreamIndex;
    			}
    			previousString = currentString;
    			scratchStream[currentStreamIndex].println(currentString);
    		}
    		scratchStream[0].close();
    		scratchStream[1].close();
    		inStream.close();
    	}
    	
    
    
    	public static void main(String[] args) throws Exception {
    		
    		File newFile =new File("test.txt");
    		NaturalMergeSorter nms = new NaturalMergeSorter(newFile);
    		nms.sort();
    		
    		//Stampa file ordinato
    		Scanner fileInput = new Scanner(newFile);
    		
    		while (fileInput.hasNextLine()){
    			System.out.println(fileInput.nextLine());
    		}
    
    
    		fileInput.close();
    		
    	}
    
    
    }


    Grazie!!
    Ultima modifica di ReaSanka; 30-01-2014 a 09:58

  2. #2
    Utente di HTML.it
    Registrato dal
    Nov 2012
    Messaggi
    50
    Ho riletto il codice un sacco di volte e finalmente ho trovato l'errore. Che stupida! Avevo scritto due volte bufferA, è normale che alcune righe andavano perse. Scusate per la discussione inutile!
    codice:
                while(scanA.hasNext() || scanB.hasNext()) {
                    //almeno uno dei due file deve avere linee
                    if(scanA.hasNext() && scanB.hasNext()) {
                        //se entrambi hanno linee, si inserisce in
                        //dest la minore
                        sorted = false;
                        bufferA = nextA ? scanA.nextLine() : bufferA;
                        bufferA = nextB ? scanB.nextLine() : bufferB;
                        nextA = false;
                        nextB = false; //le linee non sono ancora consumate

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.