Zwei Textdateien vergleichen und Gemeinsamkeiten auflisten [Java] |
matt99
Jungspund
Dabei seit: 23.07.2016
Beiträge: 10
|
|
|
08.10.2016 22:11 |
|
|
|
Mir ist noch nicht klar, wie der Vergleich ablaufen soll.
Kann ich davon ausgehen, dass du Zeile x der einen Datei mit Zeile x der anderen vergleichen willst? Oder kann es sein, dass bei einer Datei dazwischen etwas eingefügt wurde?
Geht es nur um gleich/verschieden, oder willst du auch wissen, was verschieden ist?
Zitat: |
Mein Problem sind aber Textdateien, dessen Inhalt nebeneinander hinweg geschrieben sind. |
verstehe ich nicht, kannst du ein Beispiel geben?
Übrigens, solche Vergleichsprogramme gibt es schon (z.B. meld)
__________________ Syntax Highlighting fürs Board (Link)
|
|
09.10.2016 07:52 |
|
|
matt99
Jungspund
Dabei seit: 23.07.2016
Beiträge: 10
|
|
Zitat: |
Original von eulerscheZahl
Kann ich davon ausgehen, dass du Zeile x der einen Datei mit Zeile x der anderen vergleichen willst? Oder kann es sein, dass bei einer Datei dazwischen etwas eingefügt wurde?
Geht es nur um gleich/verschieden, oder willst du auch wissen, was verschieden ist? |
Die Textdateien sind Listen. Diese sehen ungefähr so aus:
Liste P
Dies
ist
eine
Liste
Liste W
Hier
stehen
Wörter
in
der
Liste
Die Anzahl der Wörter in beiden Listen variiert. Nun will ich schauen, welche Wörter in W auch in P vorkommen. In diesem Fall das Wort "Liste". Und dies hätte ich gern auch als Ausgabe. Die Wörter welche in beiden vorkommen und die Anzahl dieser Wörter (in diesem Fall 1).
Zitat: |
Original von eulerscheZahl
Zitat: |
Mein Problem sind aber Textdateien, dessen Inhalt nebeneinander hinweg geschrieben sind. |
verstehe ich nicht, kannst du ein Beispiel geben? |
Bisher bin ich gedanklich nur das Szenario durchgegangen, dass alle Liste (welche als Parameter eingeladen werden) untereinander hinweg geschrieben sind, wie das Beispiel. Mein Problem sind nun aber auch Listen, deren Wörter nacheinander hinterlegt sind, oder gar komplett durcheinander. z.B.
Liste P:
Dies ist eine
Liste
Ich müsste also über ein Tokenization die Leerzeichen erkennen und auch diese als "Trenner" beachten. Mit dem derzeitigen Code erkennt er ja nur Zeile für Zeile. Er würde also in diesem Beispiel sagen "Dies ist eine" und "Liste", Anzahl der Wörter: 2.
|
|
09.10.2016 10:47 |
|
|
|
Innerhalb der Zeile kannst du mit split (also line.split(' ')) die Zeile in Worte zerlegen.
Zerlege erst die eine Datei, schreibe die Worte in ein HashSet (da ist die Reihenfolge dann auch egal) und prüfe bei der zweiten Datei mit HashSet.contains(), ob das Wort vorkommt.
Oder erst für beide Dateien getrennt HashSets und dann mit retainAll den Schnitt aus beiden bestimmen.
Wenn du die Anzahl auch noch haben willst, kannst du statt HashSet eine HashMap<String, Integer> nehmen.
Schau mal, ob du das hinkriegst. Sonst kann ich dir heute Abend ein paar Zeilen zusammentippen.
__________________ Syntax Highlighting fürs Board (Link)
|
|
09.10.2016 10:56 |
|
|
matt99
Jungspund
Dabei seit: 23.07.2016
Beiträge: 10
|
|
Vielen Dank für den Gedankenanstoss. line.split und HashSet funktionieren prima für diesen Fall. Alles sieht bisher so aus:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
|
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
public class testerfuerforum {
public static void main(String[] args) throws IOException {
Date startzeit = new Date();
// Dateipfade übergeben
String w_dateipfad = "pfad\\w_test.txt";
String p_dateipfad = "pfad\\p_test.txt";
File w_datei = new File(w_dateipfad);
File p_datei = new File(p_dateipfad);
BufferedReader bufferedReaderW;
BufferedReader bufferedReaderP;
bufferedReaderW = new BufferedReader(new FileReader(w_datei));
bufferedReaderP = new BufferedReader(new FileReader(p_datei));
String zeilenW;
String zeilenP;
HashSet<String> hashset_Z = new HashSet<String>();
HashSet<String> hashset_w = new HashSet<String>();
HashSet<String> hashset_p = new HashSet<String>();
// W durchgehen, Integer a für Anzahl der Wörter
int a = 0;
while (null != (zeilenW = bufferedReaderW.readLine())) {
// mit String split alle Wörter beim Leerzeichen trennen
for (String leerzeichen_teiler_W : zeilenW.split(" ")) {
a++;
hashset_w.add(leerzeichen_teiler_W);
}
}
// P durchgehen, Integer b für Anzahl der Wörter
int b = 0;
while (null != (zeilenP = bufferedReaderP.readLine())) {
// mit String split alle Wörter beim Leerzeichen trennen
for (String leerzeichen_teiler_P : zeilenP.split(" ")) {
b++;
hashset_p.add(leerzeichen_teiler_P);
}
}
//HashSet, Wörteranzahl und Zeit ausgeben
System.out.println(leerzeichen_teiler_P);
System.out.println(hashset_w);
System.out.println(hashset_p);
System.out.println("\n\nDauer: "
+ (System.currentTimeMillis() - startzeit.getTime()) + " ms"
+ "\nGesamtanzahl der Wörter: " + a + " und " + b);
bufferedReaderW.close();
bufferedReaderP.close();
}
} |
|
Ich habe seperat W und P gelesen. Nun hänge ich noch am HashSet.contains(). Im Internet habe ich gelesen, dass dies als boolean funktioniert. Mein Gedanke war daher die komplette Liste W erst als HashSet einzulesen, danach die Liste P. Nach jeder eingelesenen Zeile soll dann über den boolean geschaut werden, ob das aktuelle Wort in P in der gesamten Liste in W vorkommt. Ist dem so, dann bekomme ich ein true zurück und in diesem Fall wird ein neuer HashSet (nennen wir diesen einfach Z) um genau dieses Wort ergänzt.
Soviel zur Theorie. Den folgenden Code-Ausschnitt habe ich daher über dem Kommentar
code: |
1:
|
//HashSet, Wörteranzahl und Zeit ausgeben |
|
gelegt.
Am Anfang des Codes habe ich
code: |
1:
|
HashSet<String> hashset_Z = new HashSet<String>(); |
|
definiert.
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
|
// P durchgehen, Integer b für Anzahl der Wörter
int b = 0;
while (null != (zeilenP = bufferedReaderP.readLine())) {
// mit String split alle Wörter beim Leerzeichen trennen
for (String leerzeichen_teiler_P : zeilenP.split(" ")) {
b++;
hashset_p.add(leerzeichen_teiler_P);
boolean treffer = hashset_p.contains(hashset_w);
if (treffer) {
hashset_Z.add(leerzeichen_teiler_P);
}
}
} |
|
(und das mit dem Einrücken müsste ich auch noch einmal üben~)
Wenn ich nun über
code: |
1:
|
System.out.println(hashset_Z); |
|
mein hashset_Z abfrage, ist dies leer. Wird wohl auch daran liegen, dass ich den hashset_z nicht mit leerzeichen_teiler_P ergänzen sollte, sondern mit einem anderen String an einer bestimmten Stelle (?).
Eventuell hast du da auch eine weitere Idee?
Dieser Beitrag wurde 3 mal editiert, zum letzten Mal von matt99: 09.10.2016 20:28.
|
|
09.10.2016 20:21 |
|
|
|
So wäre ich die Sache angegangen:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
|
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
public class Main {
static HashSet<String> readWords(String filename) throws IOException {
HashSet<String> words = new HashSet<String>();
BufferedReader reader = new BufferedReader(new FileReader(filename));
String line;
while ((line = reader.readLine()) != null) {
String[] wordsInLine = line.split(" ");
for (String word : wordsInLine)
words.add(word);
}
return words;
}
public static void main(String[] args) {
try {
HashSet<String> list1 = readWords("/home/eulerschezahl/Dokumente/liste1.txt");
HashSet<String> list2 = readWords("/home/eulerschezahl/Dokumente/liste2.txt");
list1.retainAll(list2);
for (String word : list1)
System.out.println(word);
} catch (IOException e) {
System.out.println("Fehler beim Einlesen");
}
}
} |
|
Was bei dir schiefläuft:
code: |
1:
|
while (null != (zeilenP = bufferedReaderP.readLine())) { |
|
bufferedReaderP hat bereits bis zum Dateiende gelesen. also kommt nichts mehr, readLine gibt null zurück.
Und hier bringst du die Listen durcheinander:
code: |
1:
2:
3:
4:
5:
6:
7:
|
for (String leerzeichen_teiler_P : zeilenP.split(" ")) {
hashset_p.add(leerzeichen_teiler_P);
boolean treffer = hashset_p.contains(hashset_w);
if (treffer) {
hashset_Z.add(leerzeichen_teiler_P);
}
} |
|
Vorschlag:
code: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
|
for (String leerzeichen_teiler_P : hashset_p) { //gehe über dir Einträge in der einen Liste
//hashset_p enthält diesen Eintrag bereits
//hashset_p.add(leerzeichen_teiler_P);
//prüfe, ob Eintrag in der anderen Liste vorhanden
boolean treffer = hashset_w.contains(leerzeichen_teiler_P);
if (treffer) {
hashset_Z.add(leerzeichen_teiler_P);
}
} |
|
__________________ Syntax Highlighting fürs Board (Link)
|
|
10.10.2016 07:57 |
|
|
matt99
Jungspund
Dabei seit: 23.07.2016
Beiträge: 10
|
|
Super, dank dem Vorschlag funktioniert alles! Die Schnittstelle zwischen P und W haut damit auch hin. Besten dank für deine Hilfe.
|
|
10.10.2016 10:37 |
|
|
|