String index out of range: -1 beim Datei Parsen

rookie94

Neues Mitglied
Hey Leute habe folgendes Problem: Ich möchte eine Methode schreiben, die ein Drehbuch als .txt-Dokument Zeile für Zeile einließt und anhand des jeweils ersten Wortes der Zeile zählt welche Rolle wie oft gesprochen hat.
Ein Auszug aus dem Drehbuch:
"KELLY Let go of my hair, you little psychopath!

BUD Die, commie bimbo!

Bud pretends to cut her throat with a toy knife.

PEGGY Now, Bud, I thought we talked about this before."

Hier mein Lösungsversuch:
Java:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class scriptreader {

    public static void countRedeanteil(File file) {
 

        if (!file.canRead() || !file.isFile())
            System.exit(0);

            BufferedReader in = null;
            
            int Al=0;
            int Peg=0;
            int Steve=0;
            int Marcy=0;
            int Kelly=0;
            int Bud=0;
            int Buck=0;
      
            
       try {
          
            in = new BufferedReader(new FileReader(file));
            String zeile = new String();
            String Rolle = new String();
            while ((zeile = in.readLine()) != null) {
              Rolle = zeile.substring(0,zeile.indexOf(" "));  //Zeile 30 (FehlerQuelle)
              switch (Rolle) {
              case "AL":
                  Al++;
                  break;
              case "PEGGY":
                  Peg++;
                  break;
              case "STEVE":
                  Steve++;
                  break;
              case "MARCY":
                  Marcy++;
                  break;
              case"KELLY":
                  Kelly++;
                  break;
              case"BUD":
                  Bud++;
                  break;
              case"BUCK":
                  Buck++;
                  break;
             default:
                 break;
            }
            }
        
       } catch (IOException e) {
            e.printStackTrace();
            
       System.out.println("Al's Redeanteil: " +Al+"Peg's Redeanteil: "+Peg+"Steve's Redeanteil: "+Steve+"Marcy's Redeanteil: "+Marcy+"Kelly's Redeanteil: "+Kelly+"Bud's Redeanteil: "+Bud+"Buck's Redeanteil: "+Buck);     
      
       } finally {
            if (in != null)
      
                try {
                    in.close();
                
                } catch (IOException e) {
                
                }
        }
    }


}

Nun wird beim ausführen jedoch folgende Fehlermeldung ausgegeben:

"Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(Unknown Source)
at scriptreader.countRedeanteil(scriptreader.java:30)"

Jemand eine Idee zur Lösung meines Problems?

Viele Grüße
 
Was ich mir vorstellen könnte: Das Script enthält leere Zeilen, die insbesondere keine Leerstellen enthalten. Bei denen meckert Zeile 30 dann.
Schau dir mal die String.split Funktion an. Sie splittet einen String bei einem (oder mehreren) angegebenen Zeichen (hier Leerstellen) und gibt dir ein Array aus Strings zurück. Das erste Element des Arrays würde hier dann den Namen enthalten. Meines Wissens sollte bei den leeren Zeilen da nix passieren, da split() dann einfach nichts macht bzw. die leere Zeile als einziges Element des Arrays zurückgibt.
 
Was ich mir vorstellen könnte: Das Script enthält leere Zeilen, die insbesondere keine Leerstellen enthalten. Bei denen meckert Zeile 30 dann.
Schau dir mal die String.split Funktion an. Sie splittet einen String bei einem (oder mehreren) angegebenen Zeichen (hier Leerstellen) und gibt dir ein Array aus Strings zurück. Das erste Element des Arrays würde hier dann den Namen enthalten. Meines Wissens sollte bei den leeren Zeilen da nix passieren, da split() dann einfach nichts macht bzw. die leere Zeile als einziges Element des Arrays zurückgibt.

Danke erst mal für die schnelle Antwort.
Habe Versucht die split() Methode zu verwenden doch leider wird eine ähnliche Fehlermeldung ausgegeben:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at scriptreader.countRedeanteil(scriptreader.java:30)

Hier nochmal mein veränderter Code:


Java:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class scriptreader {

    public static void countRedeanteil(File file) {
 

        if (!file.canRead() || !file.isFile())
            System.exit(0);

            BufferedReader in = null;
            int Al=0;
            int Peg=0;
            int Steve=0;
            int Marcy=0;
            int Kelly=0;
            int Bud=0;
            int Buck=0;
      
            
       try {
          
            in = new BufferedReader(new FileReader(file));
            String zeile = new String();     
            while ((zeile = in.readLine()) != null) {
            String[] Rolle = zeile.split(" ");
              switch (Rolle[0]) {
              case "AL":
                  Al++;
                  break;
              case "PEGGY":
                  Peg++;
                  break;
              case "STEVE":
                  Steve++;
                  break;
              case "MARCY":
                  Marcy++;
                  break;
              case"KELLY":
                  Kelly++;
                  break;
              case"BUD":
                  Bud++;
                  break;
              case"BUCK":
                  Buck++;
                  break;
             default:
                 break;
            }
            }
        
       } catch (IOException e) {
            e.printStackTrace();
            
       System.out.println("Al's Redeanteil: " +Al+"Peg's Redeanteil: "+Peg+"Steve's Redeanteil: "+Steve+"Marcy's Redeanteil: "+Marcy+"Kelly's Redeanteil: "+Kelly+"Bud's Redeanteil: "+Bud+"Buck's Redeanteil: "+Buck);     
      
       } finally {
            if (in != null)
      
                try {
                    in.close();
                
                } catch (IOException e) {
                
                }
        }
    }

    
    
}
 
Also bei mir funktioniert es, poste vielleicht mal deine Textdatei mit der du es testest.

PS: Die System.out.println Zeile zwischen dem try/catch/finally Block wird dort übersprungen. Verschieb sie lieber in den try-Block (hinter die while-Schleife).
 
Du solltest dir wirklich mal angewöhnen Methode auf Ihre Rückgabewerte zu testen...

indexOf gibt -1 zurück wenn es den gesuchten String nicht findet. Also warum nicht einfach erstmal den indexOf machen und dann testen ob was er zurück gibt?

Gleiches beim Split. Du gehst einfach davon aus, dass Rolle[0] einen String enthält. Der kann aber auch leer sein. Was denn dann?

Gruß

Claus
 
Gleiches beim Split. Du gehst einfach davon aus, dass Rolle[0] einen String enthält. Der kann aber auch leer sein. Was denn dann?
In welchem Fall kann das leer sein? (Ernstgemeinte Frage, ich wüsste keinen Fall, das Javadoc gibts nicht her und Code am Handy durchgucken ist echt ekelig)

Edit: selber gefunden, sollte in diesem Fall mit 'nem trim lösbar sein.
 
Zuletzt bearbeitet:
Streams sind doch manchmal was feines...

Java:
        Map<String, Long> counts = Files.lines(Paths.get("test.txt"))
            .map(String::trim)
            .map(line -> line.split(" ")[0])
            .filter(line -> !line.isEmpty())
            .filter(line -> line.equals(line.toUpperCase()))
            .collect(groupingBy(String::toString, counting()));
        System.out.println(counts);
 
Und was habe ich oben geschrieben? "Der kann aber auch leer sein"

Wir könnten uns da jetzt ich länger im Kreis drehen, vermutlich haben wir einfach aneinander vorbei geredet...
Du gehst einfach davon aus, dass Rolle[0] einen String enthält
Wenn es Rolle[0] gibt, steht da auch ein String drin - das problem ist ja eben, dass es Rolle selbst leer ist (und Rolle[0] nicht existiert).

Der kann aber auch leer sein.

Das könnte sich jetzt entweder auf das Array selbst oder auf den String an Index 0 aus dem Vorsatz beziehen.
Wenn es sich auf den String bezieht: Ja, der String kann leer sein, wird aber in dem Code vollkommen korrekt behandelt, die Fehlermeldung bezieht sich ja auch auf das leere Array.
Oder aber du meinst das Array: dann ist das vollkommen richtig und ist vermutlich auch das, was du meintest. Meine Frage, wann das passiert, bezog sich ja auch auf genau diesen Fall - allerdings ist dann deine Antwort auf die Frage falsch:

Wenn die Zeile nichts enthält dann kriegst du einen leeren String zurück oder nicht?
Einen String bekommt man bei split nie zurück, deshalb bin ich davon ausgegangen, dass du ein leeres Array meinst (außerdem deutet die Fehlermeldung, auf die du dich bezogen hast, ja auf ein leeres Array hin).

Das Array kann in Ausnahmefällen leer sein (dann, wenn der gesamte String vom Pattern "gematched" wird, Ausnahme ist dabei der leere String), ist aber nie leer, wenn man einen leeren String splittet.

Falls du doch die Stings meintest: die Strings in dem Array können auch leer sein, leerer String wäre da eine Möglichkeit für (gibt auch noch ein paar andere, in diesem Fall zB ein String, der in der Mitte zwei Leerzeichen enthält wie "a b").



Deshalb gehe ich einfach mal davon aus, dass wir aneinander vorbei geredet haben. Du hast dich ursprünglich auf das leere Array bezogen, meine Rückfrage aber auf die leeren Strings in einem nicht leeren Array bezogen, und ich dann deine Aussage zu leeren Strings auf ein leeres Array bezogen.
Oder du meintest ursprünglich den leeren String, ich hab gedacht du meinst das Array, du hast gedacht ich denke du meinst den String usw...

Weil das vermutlich wieder unfreundlich aufgefasst wird: ist nicht so gemein, wirklich nicht 🙂

Zumindest sind das Problem in diesem Fall Zeilen, die nur aus Leerzeichen bestehen.
Das kann man wie gesagt mit einem einfachem trim vor dem Split lösen, so wie @mihe7 das auch macht, dann hätte man in diesem Fall einen leeren String, der im Code oben passend behandelt wird. Oder aber prüfen, ob ein Array mit Elementen zurück kommt.
 
Brown, du wirst mich nie verstehen so wie ich dich nie verstehen werde.... Wir beide in einem Team wäre der OberGAU. Wobei ich nicht glaube das einer von uns besser ist als der andere. Wir denken nur komplett anders, das liegt wahrscheinlich einfach an der einen Generation die uns trennt. Wobei die Jugend von heute natürlich glaubt das sie alles besser macht als wir alten es gemacht haben, das ist aber ok das war schon immer so 🙂
 
Brown, du wirst mich nie verstehen so wie ich dich nie verstehen werde....
Mich würde allerdings wirklich interessieren, wo da jetzt das Missverständnis lag 🙂

Wir denken nur komplett anders, das liegt wahrscheinlich einfach an der einen Generation die uns trennt.
Die ganzen Paradigmen, Prinzipien, Pattern, Whatever, die ich so gut finde, stammen allerdings eher aus deiner Generation - zumindest trennen mich von den entsprechenden Leuten eher zwei als eine Generation 😉

Außer, du hast noch Ada Lovelace kennen gelernt, dann ist das wirklich eine Generationsfrage 😛

Wobei die Jugend von heute natürlich glaubt das sie alles besser macht als wir alten es gemacht haben, das ist aber ok das war schon immer so 🙂
Und die ältere glauben, es sein nicht so - ist auch schon immer so 😉
 
Mich würde allerdings wirklich interessieren, wo da jetzt das Missverständnis lag 🙂

Ehrlich gesagt weiß ich es eben auch nicht. Ich finde nicht das ich irgend etwas falsches gesagt habe nur für deine Verhältnisse wahrscheinlich einfach nicht präzise genug.
Wenn man davon ausgeht, das der String an Position 0 des Arrays, das von Split zurück gegeben wird, eine Länge von mehr als 0 Zeichen hat, dann macht an etwas falsch. Wäre das für dich genauer gewesen?
Die ganzen Paradigmen, Prinzipien, Pattern, Whatever, die ich so gut finde, stammen allerdings eher aus deiner Generation - zumindest trennen mich von den entsprechenden Leuten eher zwei als eine Generation 😉

Also zu der Zeit als ich angefangen habe da gab es noch nicht einmal OOP. Diese ganzen Paradigmen, Prinzipen...... gab es also zu der Zeit als ich an Deinem Punkt meiner Entwicklung war sicherlich noch nicht 😉

Und die ältere glauben, es sein nicht so - ist auch schon immer so 😉

Das wollte ich damit sagen 🙂
 
Wenn man davon ausgeht, das der String an Position 0 des Arrays, das von Split zurück gegeben wird, eine Länge von mehr als 0 Zeichen hat, dann macht an etwas falsch. Wäre das für dich genauer gewesen?
Das ist vollkommen richtig 🙂
(Allerdings trifft zumindest der Code oben mit split nicht die Annahme, deshalb überhaupt erst mein Einwand 🙂 )

Also zu der Zeit als ich angefangen habe da gab es noch nicht einmal OOP. Diese ganzen Paradigmen, Prinzipen...... gab es also zu der Zeit als ich an Deinem Punkt meiner Entwicklung war sicherlich noch nicht 😉

OOP ist deutlich älter als die meisten denken 😉

Terminology invoking "objects" and "oriented" in the modern sense of object-oriented programming made its first appearance at MIT in the late 1950s and early 1960s.
Smalltalk is an object-oriented, dynamically typed reflective programming language. Smalltalk was created [...] during the 1970s.
 
OOP ist deutlich älter als die meisten denken 😉

Deine Spitzfindigkeiten machen es einem wirklich schwer dich zu mögen 😉

Natürlich hast du Recht aber es gab auch schon 100 oder gar 1000 Jahre vor Gallileo Menschen die wußten, dass die Erde keine Scheibe ist. Aber trotzdem spricht keiner drüber.
Genauso wissen wir beide, dass OOP wie wir es kennen (Klassen, Kapselung, Konstruktoren, Getter/Setter, Methoden etc,), erst mit C++ „Salonfähig“ und damit von der breiten Masse genutzt wurde. Und das war nach 1980.

Gruß

Claus
 

Neue Themen


Zurück
Oben