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!!![]()

Rispondi quotando
