2010-02-09 5 views
10

Ich schreibe ein Programm in Java, das erfordert, dass ich die Daten in 2 Dateien vergleiche. Ich muss jede Zeile von Datei 1 gegen jede Zeile von Datei 2 überprüfen und wenn ich eine Übereinstimmung finde, schreibe sie in eine dritte Datei. Nachdem ich bis zum Ende von Datei 2 gelesen habe, wie setze ich den Zeiger auf den Anfang der Datei zurück?Wie kann ich den Dateizeiger auf den Anfang der Datei in Java zurücksetzen?

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 - Ich habe die Rechtschreibung und die Grammatik, ich mache nicht die Formatierung. – danben

+0

Ich vermute, dass das Originalposter die Aufgabe falsch interpretierte und was eigentlich verlangt wurde, war ein degeneriertes 'diff'. Diese Schätzung basiert auf früheren Fragen des OP und der vergleichenden Schwierigkeit der Lösungen. – msw

Antwort

4

Ich denke, das Beste, was jede Zeile aus der Datei 1 in ein HashMap zu setzen wäre, zu tun; Dann könnten Sie jede Zeile der Datei 2 auf Mitgliedschaft in Ihrem HashMap überprüfen, anstatt die gesamte Datei einmal für jede Zeile der Datei 1 durchzulesen.

Aber um Ihre Frage zu beantworten, wie man zum Anfang der Datei zurückgeht, Am einfachsten ist es, einen anderen InputStream/Reader zu öffnen.

+1

+1 - es ist viel effizienter zuerst Datei 1 zu laden. Es sei denn, die Dateien können sehr groß sein. –

11

Ich glaube, RandomAccessFile ist, was Sie brauchen. Es enthält: RandomAccessFile#seek und RandomAccessFile#getFilePointer.

rewind() ist seek(0)

1

gut, Gennady S. Antwort ist, was würde ich Ihr Problem zu lösen verwenden.

Ich bin ein Programm in Java zu schreiben, die mich die Daten in zwei Dateien

jedoch zum Vergleich erfordert, würde ich lieber dies wieder nicht kodieren up .. ich eher so etwas wie http://code.google.com/p/java-diff-utils/

verwenden würde,
+1

Es ist großartig zu wissen, dass es eine Open-Source-Lösung gibt, die diese Art von Problemen angeht, obwohl der GPL-Lizenztyp zu einem ernsthaften Problem bei der Verwendung werden könnte. –

+0

@Gennady - nur im Land der Dinosaurier :-). Aber im Ernst, wenn Sie mit der GPL unzufrieden sind, können Sie Ihre eigenen Nicht-GPL-Bibliotheken entwickeln. –

+0

@Stephen C, es ist nicht ich, es ist die Rechtsabteilung der Firma :-) Aber irgendwie verlangt GPL, dass dein Code GPL wird, was in vielen Fällen nicht angemessen ist. –

2

Offensichtlich konnte man nur schließen und öffnen Sie die Datei wie folgt aus:

 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() 
    } 

Aber Sie wirklich nicht wollen, dass es so zu tun, da dieser alg Die Laufzeit des Omithms ist O (n). Wenn in Datei A 1000 Zeilen und in Datei B 10000 Zeilen vorhanden wären, würde Ihre innere Schleife 1.000.000 Mal ausgeführt.

Was Sie tun sollten, ist jede Zeile zu lesen und in einer Sammlung zu speichern, die eine schnelle Überprüfung ermöglicht, um festzustellen, ob ein Element bereits enthalten ist (wahrscheinlich ein HashSet).

Wenn Sie nur überprüfen müssen, dass sich jede Zeile in Datei 2 in Datei 1 befindet, fügen Sie einfach jede Zeile in Datei eins zu einem HashSet hinzu und prüfen dann, ob sich jede Zeile in Datei 2 darin befindet einstellen.

Wenn Sie einen Kreuzvergleich durchführen müssen, bei dem Sie jede Zeichenfolge in einer, aber nicht in der anderen finden, benötigen Sie zwei Hash-Sätze, einen für jede Datei. (Obwohl es einen Trick gibt, den Sie verwenden könnten, um nur einen zu verwenden)

Wenn die Dateien so groß sind, dass Sie nicht genügend Arbeitsspeicher haben, dann hätte Ihre ursprüngliche Methode nie funktioniert.

0

Wie andere vorgeschlagen haben, sollten Sie andere Ansätze für das Problem in Betracht ziehen. Für die spezifische Frage der Rückkehr zu einem vorherigen Punkt in einer Datei erbt java.io.FileReadermark() und reset() Methoden, die dieses Ziel adressieren.

0

Wie bereits erwähnt, gibt es bessere Algorithmen - untersuchen diese

beiseite:

Filereader nicht Zeichen implementieren und zurückgesetzt, so trashgod Kommentare sind ungenau. Sie müssten entweder eine Version von diesem implementieren (mit RandomAccessFile oder was nicht) oder in einen BufferedReader umbrechen. Letzteres wird jedoch das ganze Ding in den Speicher laden, wenn Sie es markieren

0

Nur eine kurze Frage. Können Sie nicht ein Objekt auf den Anfang der Datei zeigen und die Datei mit einem anderen Objekt durchqueren? Wenn Sie dann zum Ende kommen, zeigen Sie einfach auf das Objekt am Anfang der Datei (Stream). Ich glaube, C++ hat solche Mechanismen mit Datei-I/O (oder ist Stream I/O)

0

Ich glaube, dass Sie nur die Datei 2 Dateireader neu initialisieren und sollte es zurückgesetzt werden.

0

Wenn Sie klar die Dimension indentify kann Ihrer Datei können Sie mark (int readAheadLimit) und reset() aus der Klasse BufferedReader verwenden. Die Methode mark (int readAhedLimit) fügen Sie einen Marker an der aktuellen Position Ihres BufferedReader und Sie können zurück zum Marker mit reset().

Mit ihnen muss man vorsichtig sein, auf die Anzahl der Zeichen bis zum reset() zu lesen, müssen Sie sie als Argument der Funktion Zeichen angeben (int readAhedLimit).

Unter der Annahme einer Grenze von 100 Zeichen sollten Sie den Code wie folgt aussehen:

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

Wenn Sie nur den Dateizeiger auf den Anfang der Datei zurückgesetzt werden soll, neu zu initialisieren Ihre Puffer Leser. Ich nehme an, dass Sie auch den try and catch-Block verwenden, um nach dem Ende der Datei zu suchen.

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

Nehmen wir an, so haben Sie Ihren Pufferleser definiert. Jetzt können Sie nach Dateiende = null suchen.

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"))); 
} 

durch den Puffer Leser neu initialisiert werden Sie die Datei Leser Zeichen/Zeiger auf den Anfang der Datei zurückgesetzt, und Sie werden die Datei müssen, um den Dateileser Markierung/Zeiger auf Anfang/Oberseite nicht neu kompilieren die Datei. Sie müssen den Pufferleser nur neu initialisieren, wenn Sie den gleichen Stunt nicht im selben Lauf neu kompilieren und abziehen wollen. Wenn Sie die Schleife jedoch nur einmal ausführen möchten, müssen Sie nicht alles wiederholen, indem Sie die Datei einfach neu kompilieren. Der Datei-Lesemarker wird auf den Anfang/Anfang der Datei gesetzt.

Verwandte Themen