2010-02-09 2 views
10

Sto scrivendo un programma in Java che mi richiede di confrontare i dati in 2 file. Devo controllare ogni riga dal file 1 su ogni riga del file 2 e se trovo una corrispondenza scriverli in un terzo file. Dopo aver letto fino alla fine del file 2, come faccio a ripristinare il puntatore all'inizio del file?Come posso ripristinare il puntatore file all'inizio del file in Java?

public class FiFo { 
    public static void main(String[] args) 
    { 
     FileReader file1=new FileReader("d:\\testfiles\\FILE1.txt"); 
     FileReader file2=new FileReader("d:\\testfiles\\FILE2.txt"); 
     try{ 
      String s1,s2; 
      while((s1=file1.data.readLine())!=null){ 
       System.out.println("s1: "+s1); 
       while((s2=file2.data.readLine())!=null){ 
        System.out.println("s2: "+s2); 
       } 
      } 
      file1.closeFile(); 
      file2.closeFile(); 
     }catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

class FileReader { 
    BufferedReader data; 
    DataInputStream in; 

    public FileReader(String fileName) 
    { 
     try{ 
      FileInputStream fstream = new FileInputStream(fileName); 
      data = new BufferedReader(new InputStreamReader(fstream)); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void closeFile() 
    { 
     try{ 
      in.close(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

Ok: ho fatto l'ortografia e la grammatica, non sto facendo la formattazione. – danben

+0

Sospetto che il poster originale possa interpretare male il compito e ciò che è stato effettivamente richiesto era un diff diffe degenerato. Questa ipotesi si basa su domande precedenti dell'OP e sulla relativa difficoltà delle soluzioni. – msw

risposta

4

Credo che la cosa migliore da fare sarebbe quella di mettere ogni riga dal file 1 in un HashMap; quindi puoi controllare ogni riga del file 2 per l'appartenenza al tuo HashMap invece di leggere l'intero file una volta per ogni riga del file 1.

Ma per rispondere alla tua domanda su come tornare all'inizio del file, la cosa più semplice da fare è aprire un altro InputStream/Reader.

+1

+1: è molto più efficiente caricare prima il file 1. A meno che i file non siano molto grandi. –

11

Credo che RandomAccessFile sia quello che ti serve. Contiene: RandomAccessFile#seek e RandomAccessFile#getFilePointer.

rewind() è seek(0)

1

bene, Gennady S. risposta è ciò che vorrei utilizzare per risolvere il problema.

Sto scrivendo un programma in Java che mi obbliga a confrontare i dati in 2 file

però, preferirei non codificare questo in su di nuovo .. Avrei preferito usare qualcosa di simile http://code.google.com/p/java-diff-utils/

+1

È bello sapere che esiste un open source che affronta questo tipo di problemi, sebbene il tipo di licenza GPL possa diventare un problema serio nell'usarlo. –

+0

@Gennady - solo nella terra dei dinosauri :-). Ma seriamente, se non sei soddisfatto della GPL, sei libero di sviluppare le tue librerie non GPL. –

+0

@Stephen C, non sono io, è il reparto legale dell'azienda :-) Ma in ogni caso GPL richiede che il tuo codice diventi GPL, il che non è appropriato in molti casi. –

2

Ovviamente si può solo chiudere e riaprire il file in questo modo:

 while((s1=file1.data.readLine())!=null){ 
     System.out.println("s1: "+s1); 
     FileReader file2=new FileReader("d:\\testfiles\\FILE2.txt"); 
     while((s2=file2.data.readLine())!=null){ 
      System.out.println("s2: "+s2); 
      //compare s1 and s2; 
     } 
     file2.closeFile() 
    } 

Ma davvero non si vuole fare in questo modo, dal momento che questo ALG il tempo di esecuzione di orithm è O (n). se c'erano 1000 righe nel file A e 10000 righe nel file B, il ciclo interno sarebbe eseguito 1.000.000 volte.

Quello che dovresti fare è leggere ogni riga e memorizzarla in una raccolta che consente di verificare rapidamente se un oggetto è già contenuto (probabilmente un HashSet).

Se è solo necessario verificare che ogni riga nel file 2 sia nel file 1, quindi è sufficiente aggiungere ciascuna riga nel file uno a un hashset, quindi verificare che ogni riga nel file 2 sia in quella impostato.

Se è necessario eseguire un confronto incrociato in cui è possibile trovare tutte le stringhe in una ma non nell'altra, sono necessari due set di hash, uno per ciascun file. (Anche se c'è un trucco che potresti fare per usarne solo uno)

Se i file sono così grandi che non hai abbastanza memoria, allora il tuo metodo originale n non avrebbe mai funzionato comunque.

0

Come altri hanno suggerito, dovresti considerare altri approcci al problema. Per la domanda specifica di ritorno a un punto precedente in un file, java.io.FileReader eredita i metodi mark() e reset() che risolvono questo obiettivo.

0

Come già detto, ci sono algoritmi migliori - indagare su questi

parte:

FileReader non implementa marchio e ripristinare, quindi i commenti di trashgod inesatti. Dovresti implementare una versione di questo (usando RandomAccessFile o cosa no) o eseguire il wrapping in un BufferedReader. Tuttavia, quest'ultimo caricherà l'intera cosa in memoria se la contrassegni

0

Solo una rapida domanda. non puoi tenere un oggetto puntato all'inizio del file e attraversare il file con un altro oggetto? Quindi quando arrivi alla fine basta puntarlo sull'oggetto all'inizio del file (stream). Credo che C++ abbia meccanismi di questo tipo con I/O di file (o I/O stream)

0

Credo che si possa semplicemente inizializzare nuovamente il lettore di file 2 e che dovrebbe ripristinarlo.

0

Se è possibile identificare chiaramente il dimensione del file è possibile utilizzare segno (int readAheadLimit) e reset() dalla classe BufferedReader. Il metodo mark (int readAhedLimit) aggiungi un marker alla posizione corrente di BufferedReader e puoi tornare al marker utilizzando reset().

utilizzarli bisogna stare attenti al numero di caratteri da leggere fino alla reset(), è necessario specificare loro come l'argomento del marchio funzione di (int readAhedLimit).

Assumendo un limite di 100 caratteri il codice dovrebbe essere simile:

class MyFileReader { 
    BufferedReader data; 
    int maxNumberOfCharacters = 100; 

    public MyFileReader(String fileName) 
    { 
     try{ 
      FileInputStream fstream = new FileInputStream(fileName); 
      data = new BufferedReader(new InputStreamReader(fstream)); 
      //mark the current position, in this case the beginning of the file 
      data.mark(maxNumberOfCharacters); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void resetFile(){ 
     data.reset(); 
    } 

    public void closeFile() 
    { 
     try{ 
      in.close(); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
0

se si desidera solo per ripristinare il puntatore del file alla parte superiore del file, reinizializzare il lettore buffer. Suppongo che tu stia utilizzando anche il blocco try and catch per verificare la fine del file.

`//To read from a file. 
     BufferedReader read_data_file = new BufferedReader(new FileReader("Datafile.dat"));' 

Diciamo che questo è il modo in cui è definito il proprio lettore di buffer. Ora, questo è come puoi verificare la fine di file = null.

boolean has_data= true; 

while(has_data) 
    {  
     try 
    { 
    record = read_data_file.readLine(); 
    delimit = new StringTokenizer(record, ","); 
    //Reading the input in STRING format. 
    cus_ID = delimit.nextToken(); 
    cus_name = delimit.nextToken();' 
     //And keep grabbing the data and save it in appropriate fields. 
    } 
catch (NullPointerException e) 
    { 
     System.out.println("\nEnd of Data File... Total "+ num_of_records 
         + " records were printed. \n \n"); 
     has_data = false; //To exit the loop. 
     /* 
     ------> This point is the trouble maker. Your file pointer is pointing at the end of the line. 
    -->If you want to again read all the data FROM THE TOP WITHOUT RECOMPILING: 
     Do this--> Reset the buffer reader to the top of the file. 
     */      
     read_data_file = new BufferedReader(new FileReader(new File("datafile.dat"))); 
} 

reinizializzando il lettore di buffer si reimpostare il lettore di file marchio/puntatore all'inizio del file e non sarà necessario ricompilare il file per impostare il lettore di file marcatore/puntatore a inizio/cima il file. È necessario reinizializzare il lettore di buffer solo se non si desidera ricompilare e rimuovere la stessa stunt nella stessa esecuzione. Ma se si desidera eseguire il ciclo una sola volta, non è necessario tutto questo, semplicemente ricompilando il file, il marcatore del lettore di file sarà impostato all'inizio/all'inizio del file.