# BufferedReader mark() & reset()



## j_connor (4. April 2010)

Hallo Leute!
schreibe grad an eine kleines Programm, welches ein Array von Namen hat und diese in einer .txt- Datei sucht.
also entweder findet er der Reihe nach den Namen oder halt nicht:


```
public void stringSuchen() throws IOException {

        try {

            this.reader = new BufferedReader(this.nameTextDatei);
            this.line = new String();
            this.reader.mark(1);

            for (int i = 0; i < this.fileNameArray.length; i++) {

                
                boolean index = true;

                while (true) {
                    this.line = this.reader.readLine();


                    if (line != null) {


                        if (line.indexOf(this.fileNameArray[i]) > -1) {
                            System.out.println("gefunden");
                            this.reader.reset();
                            break;
                        } else {
                            index = false;
                        }

                    } else {
                        if (index == false) {
                            System.out.println("nicht gefunden");
                            this.reader.reset();
                            break;
                        } else {
                            break;
                        }

                    }
                }

              
              
            }

        } catch (NullPointerException e) {
            System.out.println("NullPointerException" + "\n" + "gui_stringSuchen");
        }
    }
```


nun zu meiner kleinen Verzweiflung:

also zunächst wenn er den z.B. ersten Namen aus dem Array in der .txt- datei findet macht der ja ein "this.reader.reset();break;"
und schon nimmt er sich den nächsten Namen aus dem Array und durchsucht die .txt datei wieder vin der ERSTEN Zeile an.

soweit so gut

findet er aber dann den Namen nicht in der .txt- datei (somit er hat die ganze .txt- datei ja duchsucht),
gibt er mir die ja auch schön aus "System.out.println("nicht gefunden");"
aber sagt mir dann:

!"MARK INVALID"!

bricht dann somit ab.

ich hab schon alle Möglich ausprobiert, ich komm aber nicht auf die Lösung.
Wäre super wenn mir einer ein Tip gibt.

DANKE im Voraus!


----------



## zeja (4. April 2010)

Fängst du gerade an mit programmieren? Dein Code sieht noch sehr unstrukturiert aus.

Du solltest dir z.B. mal anschaun, was die 1 welche du an die mark Methode übergibst, bedeutet. Dann dürfte auch klar werden, warum reset nicht funktioniert.


----------



## j_connor (4. April 2010)

ja also ein Erfahrener Programmierer bin ich ganz und garnicht.noch nicht einmal ein wirklicher Programmier^^
ich übe nur hin und wieder.

also die 1 die ich da setze, so dachte ich, bedeutet, dass wenn ein reset() auftaucht, dieser zur ersten Zeile springt
und von dort die datei wieder durchläuft.
klappt ja auch, solange er fündig wird,
nur wenn der String nicht in der datei steht, macht ers nicht


----------



## zeja (4. April 2010)

Auch für das hin und wieder mal aus Interesse programmieren, würde ich dir empfehlen ein paar Grundlagen in einem Buch zu lesen bevor du dich auf sowas wie Datei einlesen stürzt. Das ist in Java nicht so einfach.

Die Doku sagt zu mark (http://java.sun.com/javase/6/docs/api/java/io/Reader.html)


> public void mark(int readAheadLimit)
> 
> readAheadLimit - Limit on the number of characters that may be read while still preserving the mark. After reading this many characters, attempting to reset the stream may fail.


----------



## j_connor (4. April 2010)

leider ist dies mir so gar keine Hilfe.

gibt es nicht ne kleine Lösung für das Problem?
ich will ja einfach nur, dass .readLine() ab der ersten Zeile wieder und wieder durchläuft


----------



## Kai008 (4. April 2010)

Warum schließt du den alten Reader nicht einfach und startest einen neuen? Ist vielleicht nicht der beste Weg, aber imho der überschaubarste, was als Newbit imho sehr viel wichtiger ist. Außerdem dürftest du den Zeitunterschied bis zu einer gewissen Anzahl nicht spüren, und bei so einer großen Menge wäre die Verwendung einer Datenbank warscheinlich sowieso um einiges sinnvoller als eine Textdatei.

btw. Saug dir mal FindBugs von der University of Maryland, das hilft dir einige schlechte Programmierangewohnheiten gleich zu erkennen und dir garnicht anzugewöhnen (wie z. B. der Schreibzugriff von einer Klassenmethode in eine statische Variable), außerdem findet es auch manchmal syntaxische Bugs.


----------



## zeja (4. April 2010)

Die Frage ist doch ob dein Ansatz überhaupt gut ist, die Datei wieder und wieder auszulesen. Das ist eine Operation auf der Festplatte und die ist nicht gerade schnell. Sinnvoller wäre es doch, die Datei in eine geeignete, leicht durchsuchbare Datenstruktur einzulesen und dann damit zu arbeiten.

Lies doch bitte mal die folgenden Abschnitte: Kapitel 14 und 12.1 und 12.3 http://openbook.galileocomputing.de/javainsel8/index.htm


----------



## Kai008 (4. April 2010)

Klar, aber es ging mir ja nur um die Lesbarkeit des Codes für einen Anfänger. Und wenn er das größtenteils schon hat, dachte ich, dass es für ihm am einfachsten wäre. Ich denke einer der schnellsten Wege wäre es zeilenweiße in eine ArrayList zu schreiben und dort mit contains durchzugehen. Die unterscheiden sich ja von Arrays nur durch die Verwendung von Methoden statt Klammern, aber ist ja im Endeffekt irgendwie ein ganz anderes Feeling, und ich weiß nicht ob Anfänger damit zurechtkommen.


----------



## SPiKEe (5. April 2010)

wenn es nur ums (NiCHT) FiNDEN geht würd ich sogar noch n stück elementarer werden ...
die datei erstmal komplett über FileInputStream.read() einlesen und in nen ByteArrayOutputStream schreiben ...
dadurch hast du erstmal nur EINEN platten-zugriff und machst den rest im RAM ... was auch grade bei größeren listen / daten einen erheblichen unterschied macht
vom ByteArrayInputStream liest du dann die daten ein *entweder du bastelst dir n BufferedReader drum ums mit readLine() zu lesen oder dierekt als byte[]-array* ... splittest dann die komplette datei mit String.split() als trenner mit dem leerzeichen und arbeitest dann mit dem erhaltenen byte[]-array weiter ...
da lässt du nun einfach 2 for schleifen drüber laufen *1te für jedes element der liste mit dem dann die 2te , untergeordnete for durchgeführt wird* und überprüfst mit contain *vorher dann toLowerCase()* oder mit equalsIgnoreCase() *was grade bei satzzeichen scheitern dürfte*
sollte eigentlich einer der schnelleren und einfacheren wege sein ...

auf jeden fall solltest du wie oben erwähnt die datei erstmal komplett in dem RAM laden um die geschwindigkeit zu steigern und deine platte "etwas" zu schonen ...

beispiel kann ich mir jetzt leider nicht so aus den fingern saugen ...
dessweiteren werden meine code-posts hier auch net gern gesehen weil ich , obwohl ich seit nun mehr 4 jahren mit JAVA teilweise meine brötchen verdiene , einen verflucht schlechten programmier-stil hab der aber meist der performance-günstigste ist ... nur das lesen und verstehen meiner codes fällt den meisten schwer ^^


----------



## Kai008 (5. April 2010)

Warum InputStream, wenn du nur Text lesen willst? Der FileReader/BufferedReader kann ja auch read(array, start, länge), und im Endeffekt willst du ja chars und keine bytes vergleichen. Ich hoffe connor stört es nicht, wenn wir uns jetzt darüber unterhalten, aber wenn der Thread/Task von der CPU wärend der Abarbeitung des Lesevorgangs interrupted wird, wird dann nicht auch ein IRQ an die HDD gesendet? Weil der Prozessor muss beim lesen/schreiben ja genauso arbeiten. Dann wird doch im Endeffekt wieder nicht in einem durchgelesen, oder irre ich mich da? Und wenn die HDD nicht fragmentiert ist bleibt der Lesekopf ja an der Position wo er weiterlesen muss, also kann er bei zeilenweißen lesen ja auch in einen durchlesen, sofern keine andere HDD-Operation an der selben stattfindet, oder?


----------

