# Wörter aus Datei einlesen



## Dramago (26. Mai 2014)

Guten Abend,

ich habe die Aufgabe einen Gedichtgenerator zu schreiben. Der Generator an sich funktioniert, es geht nur um das einlesen der Wörter.
Diese sollen aus einer Textdatei mit folgendem vorläufigem Aufbau eingelesen werden:


```
:SUBSTANTIVE
Haus
Maus
Katze
:VERBEN
läuft
spielt
:ADJEKTIVE
schön
neu
alt
```

Es gibt noch mehr Wortarten usw.
Mein erster Ansatz war die Datei zeilenweise auszulesen, dann an den Leerzeichen zu splitten und die Wörter in Listen zu speichern und dann von dort aus weiterverarbeiten.
Jetzt hab ich aber erfahren, dass wir das nicht so machen sollen, denn es könnte ja sein, dass die Datei riesig groß ist und wir uns so den ganzen Arbeitsspeicher voll hauen. Deshalb sollen wir die benötigten Wörter direkt aus der Datei lesen ohne sie nochmals alle zwischenzuspeichern. Es geht halt darum, dass ich immer die benötigte Wortart übergebe und dazu dann ein Wort dieser Wortart aus der Datei zurückbekomme. Habt ihr eine Ahnung wie ich das lösen könnte? 

Vielen Dank


----------



## Ruzmanz (26. Mai 2014)

Einfach und sehr unperformant:
- Jede Zeile einlesen die Positionen der Wortarten abspeichern.


```
int i = 0;
while ((line = reader.readLine()) != null) {
	if(":SUBSTANTIVE".equals(line)) {
		pos1 = i;
	} else if(":VERBEN".equals(line)) {
		pos2 = i;
	}
}
```
- Aufgrund irgendeiner Logik kannst du sicherlich im Vorfeld schon sagen, wie viele Verben etc. du brauchen wirst. Wenn die Verben im Bereich 0 bis 42 liegen, lässt du dir X zufällige Zahlen in dem Bereich ausgeben. Wenn die Substantive im Bereich 43 bis 99 liegen, lässt du dir Y zufällige Zahlen in dem Bereich ausgeben.
- Anschließend gehst du nochmal mit der while-Schleife über die Datei und packst die Wörter in ein Array
- Dann baust du dir dein Gedicht zufällig zusammen


----------



## Dramago (26. Mai 2014)

So ähnlich hatte ich das auch, aber es wäre theoretisch möglich, dass auch die ganze Datei in einer Zeile steht. Und ich kann auch nicht vorher sagen wie viele Verben und so es sein werden, das müsste ich dann irgendwie aus der Datei berechnen. Was mir noch einfällt ist vor jedes Wort ein Trennzeichen zu machen...


----------



## Ruzmanz (26. Mai 2014)

Wenn du das nicht Zeilenweise einlesen möchtest, kannst du es auch in byte[] machen. Zum Beispiel mit RandomAccessFile.


----------



## strußi (27. Mai 2014)

oder du machst drei ArrayList<String> auf und speicherst das zeug einfach da rein, damit hast du den wenigsten ärger

du kannst die gesammte Zeile einlesen und mittels des scanners schaun ob mehr als ein wort in der zeile steht, dann aufteilen und die nächste zeile einlesen, teste, wortweise in die arraylist packen, wenn es eine andere wortart ist, die passende arraylist nehmen und die wörter hinzuschreiben, ...


----------



## Dramago (28. Mai 2014)

Das ist ja gerade das Problem, dass ich alle Wörter zu keiner Zeit speichern soll, sondern ein Wort direkt aus der Datei holen und verarbeiten und dass nächste auch wieder aus der Datei.


----------



## strußi (30. Mai 2014)

hab ich es richtig verstanden, dass du folgendes machen willst

benutzer sagt:
gib mit substantiv und du liest einfach das oberste aus deiner Datei ein und löscht dieses anschließend? um so an das nächste zu kommen?

sonst kannst du so was auch machen indem du nur die ersten 10 von jeder wortart einliest und aus der datei schmeißt, und sobald nur noch 2 oder 3 drin sind, kannst du automatisch nachladen. Wenn ein wort aus einer liste verwendet wird, schmeißt du es raus. damit kommst du nur selten an die ram-grenze


----------



## Dramago (30. Mai 2014)

Nein, so sollte das nicht funktionieren. Ich versuchs nochmal etwas verständlicher zu machen:

Ich habe eine Klasse bzw. mehrere Klassen, die aus einer gegebene Vokabelliste ein zufällig erzeugtes Gedicht erstellen sollen. Der Satzbau und so weiter ist alles vorgegeben. Jetzt brauch ich eine Klasse "FileHandler" oder so, welche eine Methode besitzt, zB.: "getWort(int wortart)", welche ich in der "Generator"-Klasse aufrufe und die mir dann zu einer gegebenen Wortart ein zufälliges Wort zurückgibt. Diese Methode soll also in der Datei ein Wort der gesuchten Wortart finden und es zurückgeben. Dabei soll nur dieses eine Wort gespeichert werden und nicht alle Wörter aus der Datei, oder einer Wortart. Ich darf auch nicht eine ganze Zeile einlesen, da es ja theoretisch möglich ist, dass die ganze Datei in einer Zeile steht.
Meine Idee war es jetzt verschiedene Delimiter einzufügen, die vor jedem Wort stehen und so. aber wie kann ich das dann realisieren, dass ich ein zufälliges Wort der gegebenen Wortart bekomme und nicht immer nur das erste? Das Problem ist ja auch, dass es vollkommen variable ist, wie viele Wörter pro Wortart in der Datei stehen.
Wenn das erstmal alles funktioniert muss es dann auch noch möglich sein, ein Wort mit bestimmter Wortart und bestimmter Endung zu finden. Das sollte aber keine Problem sein, denn wenn die Endung nicht passt wird die Suche einfach wiederholt usw.


----------



## Ruzmanz (30. Mai 2014)

> Meine Idee war es jetzt verschiedene Delimiter einzufügen, die vor jedem Wort stehen und so. aber wie kann ich das dann realisieren, dass ich ein zufälliges Wort der gegebenen Wortart bekomme und nicht immer nur das erste? Das Problem ist ja auch, dass es vollkommen variable ist, wie viele Wörter pro Wortart in der Datei stehen.



Ich möchte nur nochmal auf meinen Ansatz verweisen. Du musst die komplette Datei parsen (entspricht NICHT im RAM speichern) und dir die Anzahl der Wörter pro Wortart merken. Natürlich brauchst du einen Delimiter. Wenn die Wörter nicht Zeilenweise in der Datei stehen musst du diese Byte-Weise einlesen, siehe Hinweis mit RandomAccessFile.

1. Ganze Datei durchlaufen und folgende Werte auslesen:
int[] woerter mit [5, 45, 90, 4, ...] // 5 Nomen, dann kommen 45 Verben, dann 90 positve Wörter, usw.

2. Wenn du ein zufälliges Verb suchst, dann rufst du zufall = new Random.nextInt(woerter[1]) = 2 auf.

3. Jetzt musst du die Datei nochmal durclaufen und wenn du am (woerter[0] + zufall)ten (z.B. 7) Wort angekommen bist, dann nimmst du den Wert und brichst das Einlesen der Datei ab.

... Kann man optimieren, wenn man es erstmal zum laufen gebracht hat.


----------



## Dramago (30. Mai 2014)

Super, vielen Dank für deine Antwort 

Das werde ich so umsetzen.

Wenn ich die Datei byteweise durchlaufe, wie mach ich dass denn am geschicktesten, weil ich lese doch immer nur eine bestimmte Anzahl von Bytes auf einmal ein und was ist wenn ich dann ein Wort zerteile, also wenn nach der Hälfte der Einlesepuffer voll ist?


----------

