Daten aus .txt Datei einlesen und weiterverarbeiten

Ein Fehler der gleich auffällt windenergie soll was zurückgeben aber du hast kein return.
Die letzte klammer der Methode sollte rot unterstrichen sein.
 
windenergie
Zeile 103 wo hast du das i definiert?

Java:
windenergieFeld[i] = (1/2.)*rho*flaeche*Math.pow(geschwindigkeitsFeld[i]/3.6.,3);

Kurtz um du greift in der Methode auf einige variablen zu die du da nicht hast.
 
Zuletzt bearbeitet:
Ich habe mir deinem Code einmal angesehen in IntelliJ und da fallen viele Dinge ja direkt auf:
1) dateiPruefung
  • Du fängst eine NullPointerException - Eine NPE wird nie gefangen - statt dessen prüft man Dinge, die nicht null sein dürfen aber null sein könnten. NullPointerException ist eine "DerEntwicklerIstSehrSchlampigException".
  • Du fängst aber keine IOException (Und Dinge, die davon abgeleitet sind). Da aber paar Aufrufe solche Exceptions werfen, hast Du entsprechende Fehler in dem Code.
  • Wenn Du eine Exception wirfst solltest Du immer etwas ausgeben / loggen. Sonst läuft Dein Code nicht und du hast keinen Anhaltspunkt, wieso!

Das wäre fehlerbereinigt:
Java:
    public static boolean dateiPruefung(String filename){
        boolean wahrheitswertVonZeile1 = false;

        try(FileReader fileR = new FileReader(filename+".txt");
            BufferedReader bufR = new BufferedReader(fileR)) {

            String zeile;
            zeile = bufR.readLine();
            wahrheitswertVonZeile1 = zeile.startsWith("DATA:");
        }
        catch(IOException e) {
            e.printStackTrace();
            return false;
        }
        return wahrheitswertVonZeile1;
    }

windenergie Methode

2) double flaeche = Math.PI * r^2;
Bitte schau Dir einmal die Operatoren in Java an. ^ gibt es aber das ist keine Potenzierung.
==> double flaeche = Math.PI * r*r;

3) static double windenergieFeld[] = new double [arraygroesse];
lokale Variablen können nicht static sein. arraygroesse ist nicht bekannt!
Das musst Du dann entweder als Parameter übergeben oder als Klassenvariable machen.

4) windenergieFeld[i] = (1/2.)*rho*flaeche*Math.pow(geschwindigkeitsFeld[i]/3.6.,3);
  • i nicht bekannt. Willst Du da also eine Schleife haben? Dann mach auch eine.
  • Und hinten ist ein . zu viel. Hinter dem 3.6 kommt erst ein . und dann ein , - der Punkt dürfte schlicht zu viel sein.
Das mit dem i zieht sich dann durch die Methode.
 
windenergie
Zeile 103 wo hast du das i definiert?

Java:
windenergieFeld[i] = (1/2.)*rho*flaeche*Math.pow(geschwindigkeitsFeld[i]/3.6.,3);

Java:
    //Berechnung der Windenergie
    public static double windenergie(double v) {        // v soll aus der Text-Datei-Zeile ausgelesen werden
        final int r = 20;
        final double rho = 1.2225;
        double flaeche = Math.PI*r^2;
        static double windenergieFeld[] = new double [arraygroesse];
        
        for(int i = 0; i<arraygroesse; i++) {
            
            windenergieFeld[i] = (1 / 2.) * rho * flaeche * Math.pow(geschwindigkeitsFeld[i] / 3.6., 3);
        
            if (v <= 2) {
                System.out.println(uhrzeitenFeld[i] + "vWind = " + geschwindigkeitsFeld[i] + " km/h \t pWind = 0kW \t Wind zu schwach ");
            }
            else if (v >= 40) {
                System.out.println(uhrzeitenFeld[i] + "vWind = " + geschwindigkeitsFeld[i] + " km/h \t pWind = 0kW \t Wind zu stark ");
            }
            else {
                System.out.println(uhrzeitenFeld[i] + "vWind = " + geschwindigkeitsFeld[i] + " km/h \t pWind = " + windenergieFeld[i] + " kW");
            }
    }
}
 
Die for Schleife hast jdu jetzt gemacht war vorher nicht.

Schaue unsere anderen Posts du hast noch einige Fehler.

Im Editor sind bestimmt viele sachen rot. Alt +Enter gibt dir ewentuel hilfe wenn du den cursor auf den roten bereich setzt.

Ps mit der for und arraygroesse hast du dir den nechste fehler geholt.
arraygroesse ist eine lokale Variable einer anderen Methode.
 
Zuletzt bearbeitet:
Bitte schau Dir einmal die Operatoren in Java an. ^ gibt es aber das ist keine Potenzierung.
Das war tatsächlich nur ein Flüchtigkeitsfehler. Paar Zeilen drunter habe ich die richtige mathematische Operation mit Math.pow() verwendet.

lokale Variablen können nicht static sein. arraygroesse ist nicht bekannt!
Das habe ich auch umgeändert, weil das intelliJ automatisch vorgeschlagen hat.

i nicht bekannt. Willst Du da also eine Schleife haben? Dann mach auch eine.
Das habe ich jetzt auch eingefügt mit einer for Schleife.

Und hinten ist ein . zu viel. Hinter dem 3.6 kommt erst ein . und dann ein , - der Punkt dürfte schlicht zu viel sein.
Ich dachte immer, dass ich bei Bruchrechnungen ein Punkt noch zusätzlich hinten setzen muss (ganz am Anfang bei den Übungen, wurde nämlich bspw. 1/2. gefordert, damit ein double rauskommt, sonst wirds ein int) Aber intelliJ hat den auch bemängelt und hab den jetzt rausgemacht.

arraygroesse ist eine lokale Variable einer anderen Methode.
Wie kann ich die arraygroesse übergeben?
Eine Frage nebenbei: Kann ich in einer Methode, eine weitere Methode verschachteln?

Java:
import javax.swing.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TextDateienEinlesenVerarbeiten {
    public static void main(String[] args) throws Exception {

        System.out.println("==============================");
        System.out.println("=== Auswertung Windenergie ===");
        System.out.println("==============================");

        String filename = eingabeDateiname();
        boolean pruefung = dateiPruefung(filename);

        if (pruefung == true) {
            datenAuslesen(filename);
        } else {
            System.out.println("Datei startet nicht mit DATA: -> Programmabbruch.");
            System.exit(0);
        }
        windenergie(double v, double arraygroesse);



    }



    /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    Ab hier drunter Methoden:
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

    //Eingabe des Dateinamens
    public static String eingabeDateiname() {
        String eingabe = JOptionPane.showInputDialog("Geben Sie den Dateinamen ohne .txt ein:");
        return eingabe;
    }

    //Pruefen, ob die Datei mit DATA: startet -> Wahrheitswert zurueckgeben

    public static boolean dateiPruefung(String filename) {
        boolean wahrheitswertVonZeile1 = false;

        try (FileReader fileR = new FileReader(filename + ".txt");
             BufferedReader bufR = new BufferedReader(fileR)) {

            String zeile;
            zeile = bufR.readLine();
            wahrheitswertVonZeile1 = zeile.startsWith("DATA:");
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return wahrheitswertVonZeile1;
    }


    //Datei ab Zeile 2 auslesen, falls dateiPruefung true zurueckgibt
    static String[] uhrzeitenFeld;
    static double[] geschwindigkeitsFeld;

    public static boolean datenAuslesen(String filename) {

        int zeile1Laenge = 0, arraygroesse = 0;

        try (FileReader fileR = new FileReader(filename + ".txt");
             BufferedReader bufR = new BufferedReader(fileR)) {

            String zeile;
            while ((zeile = bufR.readLine()) != null) { // so nicht notwendig

                zeile1Laenge = zeile.length();
                arraygroesse = Integer.parseInt(zeile.substring(6, zeile1Laenge + 1));

                uhrzeitenFeld = new String[arraygroesse];
                geschwindigkeitsFeld = new double[arraygroesse];

                for (int i = 0; i < arraygroesse; i++) {
                    String zeileDaten;
                    zeileDaten = bufR.readLine();
                    uhrzeitenFeld[i] = zeileDaten.substring(0, 5);
                    geschwindigkeitsFeld[i] = Double.parseDouble(zeileDaten.substring(7, 12));
                }

            }
        } catch (FileNotFoundException e) {
            return false;

        } catch (IOException e) {
            return false;
        }
        return true;
    }


    //Berechnung der Windenergie
    public static void windenergie(double v, double arraygroesse) {        // v soll aus der Text-Datei-Zeile ausgelesen werden
        final int r = 20;
        final double rho = 1.2225;
        double flaeche = Math.PI * Math.pow(r, 2);
        double[] windenergieFeld = new double[arraygroesse];

        for (int i = 0; i < arraygroesse; i++) {

            windenergieFeld[i] = (1 / 2.) * rho * flaeche * Math.pow(geschwindigkeitsFeld[i] / 3.6, 3);

            if (v <= 2) {
                System.out.println(uhrzeitenFeld[i] + "vWind = " + geschwindigkeitsFeld[i] + " km/h \t pWind = 0kW \t Wind zu schwach ");
            } else if (v >= 40) {
                System.out.println(uhrzeitenFeld[i] + "vWind = " + geschwindigkeitsFeld[i] + " km/h \t pWind = 0kW \t Wind zu stark ");
            } else {
                System.out.println(uhrzeitenFeld[i] + "vWind = " + geschwindigkeitsFeld[i] + " km/h \t pWind = " + windenergieFeld[i] + " kW");
            }
        }
    }
}


Dieser Code gibt mir plötzlich nur noch 3 errors aus. Das kann doch nicht sein. Von meinem Gefühl her, müssten es doch irgendwie mehr sein noch oder habe ich eine falsche Einstellung noch drin?
 

Anhänge

  • intelliJ2.png
    intelliJ2.png
    25,6 KB · Aufrufe: 1
Java:
windenergie(double v, double arraygroesse);

Diese variablen hast du nicht in der main.
Geht nicht.
 
Java:
windenergie(double v, double arraygroesse);

Diese variablen hast du nicht in der main.
Geht nicht.
Ja genau, deswegen meine Frage, wie kann ich die arraygroesse und geschwindigkeit übergeben von der Methode datenAuslesen in die main?

Wie kann ich die arraygroesse übergeben?







Noch eine Frage zu intelliJ:
Was ist dieser weiße senkrechte Balken mitten im Bildschirm? Kann ich den irgendwie deaktivieren? Der stört nur und hat keinen Mehrwert.
 

Anhänge

  • InkedintelliJ Fenste.jpg
    InkedintelliJ Fenste.jpg
    1 MB · Aufrufe: 4
Java:
windenergieFeld[i] = (1 / 2.)....

// dann 2.0 damit es ein double wird eine KommaZahl.

// Sonst machst du eine Ganzzahl Division Ergebnis wäre da 0
 
Zuletzt bearbeitet:
Du könntest nicht einen boolean aus der Methode zurückgeben. Sondern einen int. Der im positiven fall die arraygroesse enthält. Im fehlerfall -1.
Natürlich musst du dann auf minus 1 prüfen.

Oder eine Klassenvariable für arraygroesse.
 
Ich dachte immer, dass ich bei Bruchrechnungen ein Punkt noch zusätzlich hinten setzen muss (ganz am Anfang bei den Übungen, wurde nämlich bspw. 1/2. gefordert, damit ein double rauskommt, sonst wirds ein int) Aber intelliJ hat den auch bemängelt und hab den jetzt rausgemacht.
Das ist soweit richtig. Statt 1 / 2 schreibst Du 1. / 2 und dieses 1. steht für 1.0. Aus dem Integer Literal 1 wird so ein Double Literal.

Aber jetzt hast Du ja schon einen Dezimalpunkt in 3.6. Mit 3.6. hättest Du ja zwei Dezimalpunkte. Du kannst also nur einen Dezimalpunkt haben.

Noch eine Frage zu intelliJ:
Was ist dieser weiße senkrechte Balken mitten im Bildschirm? Kann ich den irgendwie deaktivieren? Der stört nur und hat keinen Mehrwert.
Der Mehrwert dieses Streifens ist, dass Du einen Hinweis bekommst, wie lang so eine Zeile maximal sein sollte.
In den Einstellungen von IntelliJ findest Du unter Editor > General > Appearance "Show hard wrap and visual Guides". Wenn Du da den Haken heraus nimmst, dann wird die Linie nicht mehr angezeigt.

Was die Array Größe angeht: Du kannst diese als Variable in der Klasse halten. Aber Du hast ja auch das Array geschwindigkeitsFeld - du kannst die Größe ja auch da heraus lesen. Generell wäre auch denkbar, dass Du an der Stelle, an der Du dieses andere Array erstellst auch direkt das andere Array erstellst. Die Daten gehören ja etwas zusammen und daher macht es sinn, die Datenstrukturen dafür auch an einer Stelle zu erzeugen. Bei Anpassungen hast Du dann nur eine Stelle.
 
Aber jetzt hast Du ja schon einen Dezimalpunkt in 3.6. Mit 3.6. hättest Du ja zwei Dezimalpunkte. Du kannst also nur einen Dezimalpunkt haben.
Ahhh, okay verstanden. Dann habe ich wieder was Neues dazugelernt.

Der Mehrwert dieses Streifens ist, dass Du einen Hinweis bekommst, wie lang so eine Zeile maximal sein sollte.
Ach dafür ist der gedacht. Dannn nehme ich das von vorher zurück, dann bietet mir der Streifen doch einen Mehrwert. 😆


Ich hab auch noch eine neue Erkenntnis gewonnen. Wenn ich substring(anfang,ende) verwende, dann kann ich ende weglassen, damit der mir quasi vom Anfangswert bis zum Endwert der Zeile den Wert ausgibt. Dann muss ich nicht extra noch die Variable zeile1Laenge definieren.
Java:
                arraygroesse = Integer.parseInt(zeile.substring(6));

Du kannst diese als Variable in der Klasse halten.
Java:
public class TextDateienEinlesenVerarbeiten {
    public static void main(String[] args) throws Exception {
        int arraygroesse = 0;
Meinst du das so?
Aber Du hast ja auch das Array geschwindigkeitsFeld - du kannst die Größe ja auch da heraus lesen. Generell wäre auch denkbar, dass Du an der Stelle, an der Du dieses andere Array erstellst auch direkt das andere Array erstellst.
Dem Teil kann ich noch nicht so ganz folgen, was ich in meinem programm dafür ändern muss.
 
Meinst du das so?
Nein nicht ganz. So ist das immer noch eine lokale Variable.

Kleine Übersicht:
Java:
class ClassName {
    SomeType var1; // Instance variable / Instanzvariable - Derzeit noch uninteressant, da bei dir noch alles static ist.
    static SomeType var2; // class variable / Klassenvariable - Das meinte ich.
   
    SomeReturnType someMethod(....) {
        SomeType var3; // local variable / Lokale Variable.
    }
}


Die andere Idee meinte etwas in der Art:
Java:
public class TextDateienEinlesenVerarbeiten {
    static String[] uhrzeitenFeld;
    static double[] geschwindigkeitsFeld;
    static double[] windenergieFeld; // Hier kommt das eine Array mit dazu
    
    public static boolean datenAuslesen(String filename) {
        // ...
        uhrzeitenFeld = new String[arraygroesse];
        geschwindigkeitsFeld = new double[arraygroesse];
        windenergieFeld = new double[arraygroesse];  // Hier wird es direkt mit initialisiert
        // ...
    }
}
 
Kleine Übersicht:
Java:
import javax.swing.*;
import java.io.*;
import java.util.*;

public class Uebung{
    
    //Deklaration / Initialisierung
    
    static final int r = 20; //m
    static final double dichte = 1.2225; //kg/m^3
    static String[] geleseneZeilen;
    static int zahl = 0;
    static double P_Wind;
    public static void main(String[] args) {
        
        //Programmkopf
        System.out.println("==============================");
        System.out.println("=== Auswertung Windenergie ===");
        System.out.println("==============================");
        
        //Programmstart
        String eingabe = JOptionPane.showInputDialog("Dateiname:");    //ohne txt
        eingabe = eingabe + ".txt";
        
        Daten_einlesen(eingabe);
        
        //Initialisiert
        geleseneZeilen = new String[zahl];
        
        //Datei in Array geschrieben
        try{
            FileReader fr = new FileReader(eingabe);
            BufferedReader br = new BufferedReader(fr);
            
            for(int i = 0; i < zahl; i++) {
                geleseneZeilen[i] = br.readLine();
            }
            
            br.close();
        }
        catch(IOException e) {
            
        }
        
        //Zahlen filtern und Ausgabe
        Ausgabe();
    
    }    //Ende der main-Methode
    
    public static double Berechnung_Windleistung(double v) {
        
        //Umrechnung in m/s
        v = v/3.6;
        double A = Math.PI*Math.pow(r,2);
        double P_Wind = 0.5*dichte*A*Math.pow(v,3)/1000;
        P_Wind = Math.round(P_Wind*10.0)/10.0;     //Runden auf eine Nachkommastelle
        
        return P_Wind;         //ans Ende
    }
    
    public static void Daten_einlesen (String eingabe) {
        //Daten einlesen
        
        try{
            FileReader fr = new FileReader(eingabe);
            BufferedReader br = new BufferedReader(fr);
            String zeile = br.readLine();
            if(zeile.startsWith("DATA:")) {
                String Data = zeile.substring(6);
                zahl = Integer.parseInt(Data);
            }
            
            else{
                System.out.println("Kaputter Datensatz\n--> Programmende");
                System.exit(0);
            }
            
        }
        catch(IOException e) {
            System.out.println(e);
        }
    }
    
    public static void Ausgabe() {
        for(int i = 0; i < zahl; i++) {
            String Zeit = geleseneZeilen[i].substring(0,5);
            String Geschwindigkeit = geleseneZeilen[i].substring(7);
            double v = Double.parseDouble(Geschwindigkeit);
            System.out.print(Zeit+" vwind = "+v+" km/h\t");
            P_Wind = Berechnung_Windleistung(v);
            
            if(v<2) {
                P_Wind = 0.0;
                System.out.print(P_Wind+" kW\t\tWind zu schwach");
            }
            if(v>=40) {
                P_Wind = 0.0;
                System.out.println(P_Wind+" kW\t\tWind zu stark");
            }
            
            else{
                System.out.println(P_Wind+" kW");
            }
        }
    }
}

Der obige Code funktioniert FAST einwandfrei. Ich habe noch ein Problem beim genauen Auslesen. Und zwar wird mir die Zeile DATA: ebenfalls ausgegeben und die letzte Zeile ausgelassen.
Hab geguckt, wie die Schleifen sind und habe mal probiert, aber keine Lösung gefunden, sonst sieht es momentan gut aus.
Will ja, dass mir erst ab Zeile 2 die Werte ausgegeben und berechnet werden bis hin zur letzten.
 
Du fängst ja wieder an, die Datei von Anfang an zu lesen. Also musst Du in Zeile 34 die erste Zeile überspringen. Dies könntest Du machen, indem Du die erste Zeile einfach liest (ohne etwas mit ihr zu machen).

Aber man könnte die Struktur auch ändern, denn wenn Du den Ablauf beschreiben würdest, dann würdest Du doch nicht ständig die Datei neu öffnen.

Du würdest die Datei öffnen und dann:
  • die erste Zeile prüfen
  • die folgenden Zeilen einlesen
dann die Datei wieder schließen

(Stell Dir das so vor, als ob es ein Aktenordner wäre. Derzeit hast Du Dinge wie:
  • Ordner aus Regal nehmen
  • Erstes Blatt prüfen
  • Ordner ins Regal zurück stellen
  • Ordner aus Regal nehmen
  • n Zettel durchgehen
  • Ordner ins Regal zurück stellen

Da wird es deutlich - der Fix, den ich zuerst beschrieben habe, lässt den Ablauf so, aber vor das "n Zettel durchgehen" überspringst Du die erste Seite. Aber das lässt den komplexen Ablauf unverändert.
 
Also musst Du in Zeile 34 die erste Zeile überspringen. Dies könntest Du machen, indem Du die erste Zeile einfach liest (ohne etwas mit ihr zu machen).
Ahhh, da war der Fehler, du hast recht, ich danke dir.

(Stell Dir das so vor, als ob es ein Aktenordner wäre. Derzeit hast Du Dinge wie:
  • Ordner aus Regal nehmen
  • Erstes Blatt prüfen
  • Ordner ins Regal zurück stellen
  • Ordner aus Regal nehmen
  • n Zettel durchgehen
  • Ordner ins Regal zurück stellen
Das Beispiel war hilfreich zur gedanklichen Darstellung, dankeschön.

Endlich macht dieses Drecksprogramm das, was ich möchte. Für euch mag das eine einfache Aufgabe gewesen sein, aber ich sitze da jetzt seit 5 Tagen dran, nur damit ich die paar Zeilen Code richtig habe. Das ist frustrierend. Naja, jetzt kann ich mich den anderen Aufgaben widmen. 😀

Ich danke euch allen!
 
Ich muss das Thema nochmal kurz ausgraben.

Wenn ich eine Datei habe, bei der die Geschwindigkeit v<2 ist, dann wird mir komischerweise in der Kommandozeile immer hinter dem Ausdruck " Wind zu schwach " nochmal die Leistung 0.0 kW ausgespuckt (siehe Anhang).
Bei v>=40 macht es das nicht.
Hat das was mit dem System.out.println zu tun?
Und wenn eine leere Datei eingelesen wird, dann bekomme ich eine NullPointerException in Zeile 26 und 85. Aber ich habe doch in der Methode Daten_einlesen einen catch Block drin?


Java:
import javax.swing.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class Uebung {

    static final int r = 20; // [m]
    static final double RHO = 1.2225; // [kg/m3]
    static String[] geleseneZeilen;
    static int a = 0;
    static int zahl = 0;
    static double P_Wind;

    public static void main(String[] args) {

        //Programmkopf
        System.out.println("================================");
        System.out.println("=== Auswertung Windenenergie ===");
        System.out.println("================================");

        String filename = "";
        String eingabe = JOptionPane.showInputDialog("Dateiname:"); // ohne .txt
        filename = eingabe+".txt";

        Daten_einlesen(filename);

        geleseneZeilen = new String[zahl];

        //Datei in Array schreiben
        try{
            FileReader fileR = new FileReader(filename);
            BufferedReader bufR = new BufferedReader(fileR);
            bufR.readLine(); //damit erste Zeile gelesen wird, aber nichts angestellt wird, somit kann unten ab Zeile 2 abgearbeitet werden
            for(int i = 0; i < zahl; i++){
                geleseneZeilen[i] = bufR.readLine();
            }

        }
        catch(IOException e){
            System.out.println("Fehler in Dateibehandlung.\n" +e);
        }

        Ausgabe();


    } //Ende main-Methode

    private static void Ausgabe() {
        for(int i = 0; i < zahl; i++){
            String Zeit = geleseneZeilen[i].substring(0,5);
            String Geschwindigkeit = geleseneZeilen[i].substring(7);
            double v = Double.parseDouble(Geschwindigkeit);
            System.out.print(Zeit + " vWind = " +v + " [km/h]\t pWind = ");
            P_Wind = Berechnung_Windleistung(v);

            if(v<2){
                P_Wind = 0.0;
                System.out.print(P_Wind + " kW\t\tWind zu schwach");        //print ohne ln, damit hinten dran gehangen wird
            }
            if(v>=40){
                P_Wind = 0.0;
                System.out.print(P_Wind + " kW\t\tWind zu stark");          //println mit ln, damit neue Zeile
            }
            else{
                System.out.println(P_Wind + " kW");                         //println mit ln, damit neue Zeile
            }
        }
    }

    private static double Berechnung_Windleistung(double v) {
        v = v/3.6;
        double A = Math.PI*Math.pow(r,2);
        double P_Wind = ((1/2.)*RHO*A*Math.pow(v,3))/1000;              // geteilt durch 1000, damit von W in kW
        P_Wind = Math.round(P_Wind*10.0)/10.0;                              // damit auf 1 Nachkommastelle gerundet (*10.0/10.0)
        return P_Wind;
    }

    private static void Daten_einlesen(String filename) {
        try{
            FileReader fileR = new FileReader(filename);
            BufferedReader bufR = new BufferedReader(fileR);
            String line = bufR.readLine();

            if(line.startsWith("SIZE:")){
                String Size = line.substring(6);
                zahl = Integer.parseInt(Size);
            }
            else{
                System.out.println("Kaputter Datensatz\n-> Programmende");
                System.exit(0);
            }
        }
        catch(IOException e){
            System.out.println("Fehler in Dateibehandlung.\n" +e);
        }
    }
}
 

Anhänge

  • Windenergie.png
    Windenergie.png
    37,1 KB · Aufrufe: 2
Zwei Dinge:

1) Du hast zwei Unabhängige if Anweisungen. Du prüfst erst auf v < 2 und machst dann ggf. etwas. Dann kommt ein anderes if und dann machst Du - je nachdem ob die Bedingung wahr ist, entweder den Block vom if oder den Block vom else.
Du willst also vermutlich ein if else if else Konstrukt haben.

2) Du fängst eine IOException und keine NullPointerException. Eine NPE sollte man auch nicht fangen sondern statt dessen an Stellen, bei denen etwas null sein kann, dies vorher prüfen. Eine NPE ist also ein "EntwicklerHatGeschamptException" 🙂
 
1) Du hast zwei Unabhängige if Anweisungen. Du prüfst erst auf v < 2 und machst dann ggf. etwas. Dann kommt ein anderes if und dann machst Du - je nachdem ob die Bedingung wahr ist, entweder den Block vom if oder den Block vom else.
Du willst also vermutlich ein if else if else Konstrukt haben.
Okay, das habe ich jetzt damit erfolgreich gelöst. 😀

2) Du fängst eine IOException und keine NullPointerException. Eine NPE sollte man auch nicht fangen sondern statt dessen an Stellen, bei denen etwas null sein kann, dies vorher prüfen. Eine NPE ist also ein "EntwicklerHatGeschamptException" 🙂

Aber das macht es mir doch leichter, wenn ich einfach einen catch(NPE e) hinten dran hänge, oder nicht? 😁

Java:
    private static void Daten_einlesen(String filename) {
        try{
            FileReader fileR = new FileReader(filename);
            BufferedReader bufR = new BufferedReader(fileR);
            String line = bufR.readLine();                                //erste Zeile wird eingelesen

            if(line.startsWith("SIZE:")){                                //wenn erste Zeile mit "SIZE:" beginnt:
                String Size = line.substring(6);               // Wert hinter Size (Anfangsindex 6 bis unendlich)
                zahl = Integer.parseInt(Size);                          // Wert in einen INT parsen, damit damit gearbeitet werden kann
            }
            else{
                System.out.println("Kaputter Datensatz\n-> Programmende");
                System.exit(0);
            }
        }
        catch(NullPointerException e){
            System.out.println("Fehler in Dateibehandlung.\n" +e);
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
 
Aber das macht es mir doch leichter, wenn ich einfach einen catch(NPE e) hinten dran hänge, oder nicht? 😁
Nein, das macht nichts leichter. Es geht ja darum, vernünftigen Code zu schreiben.

Und du nutzt die Methode BufferedReader.readLine. Und die Dokumentation ist eindeutig:
Returns:
A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached without reading any characters
Da steht, dass da entweder der Inhalt der Zeile oder eben null zurück gegeben wird.

Daher solltest Du mit genau dem Ergebnis weiter arbeiten.
 
Da steht, dass da entweder der Inhalt der Zeile oder eben null zurück gegeben wird.
Bei einer leeren Datei würde ich ja dann logischerweise null zurückbekommen, da nichts drin steht in der Zeile, die da gerade ausgelesen wird.

Und da line = null, kann auch kein .startsWith gestartet werden.



Java:
    private static void Daten_einlesen(String filename) {
        try{
            FileReader fileR = new FileReader(filename);
            BufferedReader bufR = new BufferedReader(fileR);
            String line = bufR.readLine();                                //erste Zeile wird eingelesen
            if(line != null) {
                if (line.startsWith("SIZE:")) {                                //wenn erste Zeile mit "SIZE:" beginnt:
                    String Size = line.substring(6);               // Wert hinter Size (Anfangsindex 6 bis unendlich)
                    zahl = Integer.parseInt(Size);                          // Wert in einen INT parsen, damit damit gearbeitet werden kann
                }
            }
            else{
                System.out.println("Kaputter Datensatz\n-> Programmende");
                System.exit(0);
            }
        }catch (IOException e){
            System.out.println("Fehler in Dateibehandlung.\n" +e);
        }

    }

Wäre das so erlaubt? Ich sage, dass er meine innere if-Bedingung nur starten soll, wenn die gelesene Zeile line != null ist.
Funktionieren tut es, auch ohne NPE dann, aber wäre das jetzt schöner Code?
 
Das ist so schon deutlich besser als das Fangen der NPE. (Erlaubt wäre aber beides!)

Bei dem Code fallen schon noch ein paar Dinge mehr auf, aber ich bin mir nicht sicher, in wie weit die schon jetzt für Dich interessant sind.

Ich liste mal einfach paar Punkte, die mir so direkt auffallen. Aber wie gesagt: Wenn Du gerade ganz am Anfang bist, dann geht es vor allem um die Java Sprache und noch nicht so sehr um solche Feinheiten!

  • Du veränderst da eine Instanzvariable zahl - die besagt nicht wirklich so viel aus.
  • Der Methodenname entspricht den den üblichen Standards (Nach Naming Konventionen wäre es: datenEinlesen)
  • So ein Exit mitten in einer Methode die etwas macht ist eher unüblich. Da könnte man eine andere Exception werfen um diese dann im Hauptprogramm diese zu fangen und dann darauf zu reagieren.
  • Fehlerbehandlung ist nicht optimal - bei einer IOException kommt eine Fehlermeldung aber danach geht es normal weiter. zahl ist dann halt unverändert
  • Reader werden nicht geschlossen (Das wäre in einem finally sinnvoll oder man nutzt try with resources
  • ...
 
Wenn Du gerade ganz am Anfang bist, dann geht es vor allem um die Java Sprache und noch nicht so sehr um solche Feinheiten!
Aber lieber lerne ich es von Anfang dann direkt richtig, anstatt mich am Ende schwierig umgewöhnen bzw. schlechte Angewohnheiten abeignen zu müssen.

Du veränderst da eine Instanzvariable zahl - die besagt nicht wirklich so viel aus.
zahl soll den Wert hinter dem Wort "SIZE:" darstellen. SIZE: 12 -> zahl = 12.
Ich habe static int zahl = 0 direkt unter der Klasse stehen, damit ich darauf im gesamten Programmcode drauf zugreifen kann. Würde ich das unter main schreiben, dann könnte ich darauf ja nicht mehr zugreifen. Da wusste ich noch nicht genau, wie ich das anders lösen sollte.
Reader werden nicht geschlossen
Habe ich das hier irgendwo geschlossen? Ich dachte, ich müsste dafür bufR.close() verwenden, anderenfalls habe ich das eher unbewusst gemacht.
 
Der wichtigste Punkt zuerst:
"Reader werden nicht geschlossen" meinte: Du schliesst in Deinem Code die Reader nicht ... Das sollte nicht heissen: Reader sollten nicht geschlossen werden. Alles, was das Interface AutoClosable implementiert sollte auch geschlossen werden. Das ist eine goldene Regel, die man beherzigen sollte.

Das Pattern ist/war (ehe es try with resources gab):
Java:
BufferedReader reader
try {
  reader = ....
  // ..
} finally {
  try {
      if (reader != null) reader.close();
  } catch (Exception ex) { }
}

Was sehr umständlich ist. Daher gibt es try with resources:
Java:
try (BufferedReader reader = .... ) {
  // ...
}
Und wie Du siehst: Das ist schon deutlich kleiner und weniger zu schreiben 🙂

Aber lieber lerne ich es von Anfang dann direkt richtig, anstatt mich am Ende schwierig umgewöhnen bzw. schlechte Angewohnheiten abeignen zu müssen.
Das ist sehr lobenswert, aber man muss irgendwo eine Grenze ziehen. Der Bereich Clean Code ist sehr umfangreich und da muss man immer überlegen, was Sinn macht oder nicht. Aber ja - einfache Punkte sollte man zumindest richtig vormachen / erwähnen - aber das ist dann nichts, wo ich direkt erwarten würde, dass dies dann zukünftig direkt eigenständig umgesetzt wird.

zahl soll den Wert hinter dem Wort "SIZE:" darstellen. SIZE: 12 -> zahl = 12.
Ich habe static int zahl = 0 direkt unter der Klasse stehen, damit ich darauf im gesamten Programmcode drauf zugreifen kann. Würde ich das unter main schreiben, dann könnte ich darauf ja nicht mehr zugreifen. Da wusste ich noch nicht genau, wie ich das anders lösen sollte.
Also die Variable ist ein int und enthält daher eine Zahl. Aber was für eine Bedeutung hat es? Da es bei SIZE: aufgeführt wird, kann es sowas wie groesse oder anzahlDatensätze oder so sein.
Und die Methode könnte die anzahlDatensaetzeAuslesen - und daher die Zahl zurück geben.

So eine globale Variable (darauf läuft es unter dem Strich hinaus - aber streng genommen gibt es keine globalen Variablen in Java) ist immer etwas, das man gerne vermeiden möchte. Dies macht Dir später das Leben schwer. Aber um da generell sauber zu arbeiten wird schnell auch ein Grundwissen in der objektorientierten Entwicklung notwendig. Daher macht es Sinn, sich ganz am Anfang mehr auf die reinen Java Grundlagen zu konzentrieren, damit die Syntax schnell begriffen wird und man dann in Ruhe sich um das Thema Design kümmern kann.

Aber das ist meine pers. Sicht - da mag es auch abweichende Meinungen zu geben.
 
Daher gibt es try with resources:
Mal um auf den Punkt einzugehen, weil du mich da sehr oft drauf hinweist, ich das aber nur gelegentlich befolge, weil ich das andere noch gewohnt bin von Beginn an bzw. so wie es in meinen Unterlagen steht.

Würde das für mein Beispiel dann so aussehen?

Java:
    private static void datenEinlesen(String filename) {
        try(BufferedReader bufR = new BufferedReader(new FileReader(filename))) {

            String line = bufR.readLine();                                //erste Zeile wird eingelesen
            if (line != null) {                                            //wenn die ERSTE Zeile LEER ist, dann spring zu else, sonst arbeite hier drunter weiter ab
                if (line.startsWith("SIZE:")) {                              //wenn erste Zeile mit "SIZE:" beginnt:
                    String Size = line.substring(6);               // Wert hinter Size (Anfangsindex 6 bis unendlich)
                    zahl = Integer.parseInt(Size);                          // Wert in einen INT parsen, damit damit gearbeitet werden kann
                }
            } else {
                System.out.println("Kaputter Datensatz\n-> Programmende");
                System.exit(0);
            }
        } catch (IOException e) {
            System.out.println("Fehler in Dateibehandlung.\n" + e);
        }
    }

Was mir gerade aufgefallen ist, weil ich das line != null in der if-Bedingung außen stehen habe, um eine leere Datei abzufangen: wenn ich jetzt eine Textdatei auslesen möchte, die NICHT mit "SIZE:" beginnt, dann wird das Programm einfach beendet, ohne einen Text "Kaputter Datensatz\n->Programmabbruch" auszuspucken. Eigentlich will ich, dass genau dieser Text bei einer leeren als auch fehlerbehafteten Datei (also ohne "SIZE:") ausgegeben wird.
 
Würde das für mein Beispiel dann so aussehen?
Ja genau, so würde der Code mit try with resources aussehen. Den anderen Punkt hat @fhoffmann bereits gut beantwortet.

Evtl. zur Verdeutlichung einfach einmal den einen fehlenden else Zweig eingefügt:
Java:
            if (line != null) {                                            //wenn die ERSTE Zeile LEER ist, dann spring zu else, sonst arbeite hier drunter weiter ab
                if (line.startsWith("SIZE:")) {                              //wenn erste Zeile mit "SIZE:" beginnt:
                    String Size = line.substring(6);               // Wert hinter Size (Anfangsindex 6 bis unendlich)
                    zahl = Integer.parseInt(Size);                          // Wert in einen INT parsen, damit damit gearbeitet werden kann
                } else {
                    // Hier hast Du nichts ausgegeben. Daher kommt auch keine Ausgabe in diesem Fall!
                }
            } else {
                System.out.println("Kaputter Datensatz\n-> Programmende");
                System.exit(0);
            }

Das hilft evtl., um das Problem an Deinem Code zu erkennen.
 

Zurück
Oben