Erste Schritte Suche nach Zeichenkette

GGK_01

Bekanntes Mitglied
Hallo,

Status:
Ich habe eine Lise von 0-n Elementen. (1.3.5.45.342.77854.0.1.1.443.5, 1.23.22343.522,44232.2342...) bei denen ich wissen will, ob und wie oft diese in einem Textfile in Kombination mit dem String "Namen" vorkommen.


Problem:
die zweite Suche mit dem line.contains greift mir leider nicht bzw. kann es auch sein, dass wenn die Suche nach dem ersten Listenelement fertig ist, die Iteration auf das zweite Element gar nicht mehr durchgeführt wird.

Anbei der Code:
Java:
FileReader freader = new FileReader(file);
BufferedReader reader = new BufferedReader(freader);
int counter = 0;
		
		for (int i = 0; i < list.size(); i++) {
			while (reader.readLine() != null) {
				line = reader.readLine();
				if (line.contains("Name")) {
					System.out.println("Listenelement: "+list.get(i));
					if (line.contains(list.get(i))) {
						counter++;
						System.out.println(counter +list.get(i) +" found");
						
					}
					
				}
				
			}
			
		}
		freader.close();

geworfen wird eine NullPointerException.

Ich wäre euch sehr dankbar.

LG, GGK
 
Java:
 while (reader.readLine() != null) {
     line = reader.readLine();

Du liest 2 x Daten.
Da überspringst du jede 2. Zeile,
und landest bei ungerader Anzahl auf Null.

Java:
 while ((line = reader.readLine()) != null)
sollte es beheben.
 
Wo genau tritt die NPE denn auf? Kann da jetzt nur spekulieren, aber tendenziell würde ich mal sagen, dass entweder
Code:
list
nicht initialisiert wurde (das wäre also Zeile 9) oder in deinem File nichts drin ist oder du beim Datei-Ende bist und deshalb
Code:
line
null ist.

Edit:
Code:
line
kann ja deshalb null sein, weil du zwei Überprüfungen machst, so wie AquaBall schon sagte.
 
PS: Ich würde auch nicht 3 x
Code:
+list.get(i)
benutzen.
Schreib lieber 1x
Code:
String myText=list.get(i);
, und verwende das dann. Ist leichter lesbar und erzeugt 1/3 des Garbage-Traffics.
 
Du rufst in jedem Schleifendurchlauf einmal zu oft readLine() auf. Du könntest es zB so machen:

Java:
(...)
for (int i = 0; i < list.size(); i++) {
            while ( (line=reader.readLine()) != null) {
                if (line.contains("Name")) {
(...)
 
jetzt hat sich noch ein Problem eingeschlichen.

Ich möchte letzten Durchlauf bei dem die Variable counter den maximalen Wert erreicht mit unten genannter Zeile ausgeben.

Wie geh ich denn das an?
Java:
System.out.println(counter +list.get(i) +" found");

Danke GGK
 
Nicht sehr schön, aber klappt:

Java:
System.out.println(""+counter +list.get(i) +" found");

Gruß Fant
 
Ich hab mich vielleicht unklar ausgedrückt. Im folgenden Code...
Java:
FileReader freader = new FileReader(file);
BufferedReader reader = new BufferedReader(freader);
int counter = 0;
        
        for (int i = 0; i < list.size(); i++) {
            while (line = reader.readLine() != null) {
                if (line.contains("Name")) {
                    //*System.out.println("Listenelement: "+list.get(i));
                    if (line.contains(list.get(i))) {
                        counter++;
                        System.out.println(counter +list.get(i) +" found");
                        
                    }
                    
                }
                
            }
            
        }
        freader.close();

bringt bei jedem Fund die Zeile
Code:
System.out.println(counter +list.get(i) +" found");
Ich möchte aber nicht, dass bei jedem Fund angezeigt wird, dass ein Listenelement gefunden wurde, sondern nur den maximalen Wert.

Bsp: 6. 12323.3422.1234234.52425.2 found

Danke GGK
 
Java:
FileReader freader = new FileReader(file);
BufferedReader reader = new BufferedReader(freader);
int counter = 0;
        
        for (int i = 0; i < list.size(); i++) {
            while (line = reader.readLine() != null) {
                if (line.contains("Name")) {
                    //*System.out.println("Listenelement: "+list.get(i));
                    if (line.contains(list.get(i)))  counter++;
                }
            }
        }
        System.out.println(counter +" Elemente geunden.");
        freader.close();

Wenn du irgendwas mit "max" haben willt, dann musst du erstmal definieren, was für dich "größer" bedeutet. Wer größer als was? Wie vergleichst du? ...
Davon ist im Programm nichts zu erkennen.
Bisher zählst du nur!
 
Zuletzt bearbeitet:
ich möchte wissen, wie oft ein Listenelement in der Datei vorkommt...
also:
Code:
6. 23423.342..324.134 mal gefunden
3. 1.3.2343.23445.3 mal gefunden


ich möchte nicht wissen:
Code:
1. 23423.342..324.134 gefunden
2. 23423.342..324.134 gefunden
3. 23423.342..324.134 gefunden
4. 23423.342..324.134 gefunden
5. 23423.342..324.134 gefunden
6. 23423.342..324.134 gefunden

1. 1.3.2343.23445.3 gefunden
2. 1.3.2343.23445.3 gefunden
3. 1.3.2343.23445.3 gefunden
 
Zuletzt bearbeitet:
Java:
FileReader freader = new FileReader(file);
BufferedReader reader = new BufferedReader(freader);
int counter = 0;
        
        for (int i = 0; i < list.size(); i++) {
            while (line = reader.readLine() != null) {
                if (line.contains("Name")) {
                    if (line.contains(list.get(i))) {
                        counter++;                                         
                    }                    
                }                
            }
            System.out.println(counter +list.get(i) +" found");
            counter = 0;
        }
        freader.close();

So?
 
Etwas OT, aber ich finde diese [c]while (line = reader.readLine() != null)[/c]-Idiom einfach grauenhaft. Warum nicht [c]for(String line= reader.readLine(); line != null; line = reader.readLine())[/c]?
 
Päng!

Damit der Reader neu starten kann:
Java:
        for (String element : list) {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            int counter = 0;
            while ( (line = reader.readLine()) != null) {
                if (line.contains("Name")) {
                    if (line.contains(element)) {
                        counter++;                                         
                    }                    
                }                
            }
            System.out.println("'" + element +"' found "+counter +" times.");
        }

(Und etwas verkürzt in div. Schreibweisen.)
 
Zuletzt bearbeitet:
Etwas OT, aber ich finde diese [c]while (line = reader.readLine() != null)[/c]-Idiom einfach grauenhaft. Warum nicht [c]for(String line= reader.readLine(); line != null; line = reader.readLine())[/c]?

Findest du das eleganter??

Sieht meiner Mainung nach viel schrecklicher aus, und beinhaltet den eigentlichen readLine-Vorgang wieder 2 x, was wesentlich schlechter zu lesen und schlechter zu warten ist.

(Kürzer ist es auch nicht. Schneller soundso nicht.)
 
Zum einen finde ich die klare "Aufgabenteilung" besser (Initialisierung, Schleifen-Test, Schleifen-Schritt), zum anderen wird der Scope von line auf die Schleife beschränkt (es kann also niemand hinter der Schleife auf die Idee kommen, mit line - das ja nun null ist - irgendetwas dummes zu machen).

Dass das so "lang" ist, liegt auch an der verkrüppelten API. Warum nicht [c]BufferedReader implements Iterable<String>[/c]? Dann könnte man [c]for(String line : reader)[/c] schreiben.
 
Stimmt! Gute Idee!
(Hab ich auch wieder was dazugelernt)

Langsam wird's richtig elegant:
Java:
for (String element : list) {
   BufferedReader reader = new BufferedReader implements Iterable<String>(new FileReader(file));
   int counter = 0;
   for (String line : reader) 
       if (line.contains("Name") && line.contains(element)) 
           counter++;                                         
   System.out.println("'" + element +"' found "+counter +" times.");
}

Wobei
Code:
BufferedReader reader = new BufferedReader implements Iterable<String>(new FileReader(file));
ungeprüft ist (damit arbeite ich nie), vielleicht gehts noch besser.
 
Das ist nicht "ungeprüft", das ist einfach keine gültige Syntax.

Entweder Oracle ändert BufferedReader irgendwann mal entrsprechend, oder man schreibt sich einen Wrapper (ungetestet):

Java:
import java.io.BufferedReader;
import java.util.Iterator;
import java.util.NoSuchElementException;

public class BRIterable implements Iterable<String> {

    private final BufferedReader reader;

    public BRIterable(BufferedReader reader) {
        this.reader = reader;
    }

    @Override
    public Iterator<String> iterator() {
        return new Iterator<String>() {
            
            private String line;  { read(); }
            
            private void read(){
               try {
                 line = reader.readLine();
               } catch (Exception ex) {
                   throw new RuntimeException(ex);
               }
            }
            
            @Override
            public boolean hasNext() {
                return line != null;
            }

            @Override
            public String next() {
                if(! hasNext()) {
                    throw new NoSuchElementException();
                }
                String result = line;
                read();
                return result;
            }

            @Override
            public void remove() {
               throw new UnsupportedOperationException();
            }
        };
    }
}

Damit kann man jetzt schreiben
Java:
for(String line : new BRIterable(reader)) {
   ...
}
 
Päng!

Damit der Reader neu starten kann:
Java:
        for (String element : list) {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            int counter = 0;
            while ( (line = reader.readLine()) != null) {
                if (line.contains("Name")) {
                    if (line.contains(element)) {
                        counter++;                                         
                    }                    
                }                
            }
            System.out.println("'" + element +"' found "+counter +" times.");
        }

(Und etwas verkürzt in div. Schreibweisen.)


Danke..ich hab mich für deine Variante entschieden...ist einfach im Code...und funktioniert perfekt!

GGK
 
[TIPP]Eine generelle Anmerkung: Ist es wirklich schlau, die Datei n-Mal zu lesen? Wäre es nicht sinniger, die Schleife über die Liste nach innen zu packen?[/TIPP]
 
Das hängt davon ab. IO-Methoden sind in der Regel teuer.

Bei 10.000 Zeilen und 4 Einträgen in der Liste wäre es zum Beispiel sehr viel geschickter, die Datei nur einmal zu lesen.
 
Ist sicher eine Überlegung wert...jedoch hab ich das Programm gerade released...ich plane diese Änderung ein...

Danke für den Hinweis

GGK
 
1) Bei 10.000 Zeilen wirst du bald mal an die Speichergrenze kommen. (Je nach Laufumgebung.)
Für diesen Zweck sind externe Speicher erfunden worden. 😳

2) Beim Umpacken der Schleifen wirst du dein blaues Wunder mit Counter erleben!
Weil dann nicht mehr rauskommt, wieviele Zeilen den aktuellen Suchstring enthalten,
sondern wieviele Suchstrings in der aktuellen Zeile vorkommen!

Die Moral von der Geschicht':
Schleifen tauschen tut man nicht!
 
Zuletzt bearbeitet:
Das tust du ja bereits!
Deine Datei liegt ja auf "externem Speicher" (= Festplatte, ...)
Ich wollte damit nur sagen, dass die gesamte Datei leicht größer sein kann, als du überhaupt einlesen kannst.
 

Zurück
Oben