Erste Schritte Einlesen und Arbeiten einer Datei

mashroomer

Mitglied
Hallo Javaforum!
Ich habe folgendes Problem, es soll ein Programm entstehen, welches u-Werte und q-Werte der Wände berechnet. Die Innen- und Außentemperatur muss vom Nutzer eingegeben und die Dicke und Lambda der Wände müssen aus einer Excell-Datei eingelesen werden. Das eigentliche Problem besteht für mich darin, dieses "Einlesen" in das Programm zu integrieren, sodass Java dann damit arbeiten kann. Was mache ich falsch und wie kann ich es richtig machen. Ich habe das Gefühl ich bin sehr nah dran aber ich verstehe es einfach nicht.

Hauptprogramm:

Java:
    package programm;

     

    import java.io.BufferedReader;

    import java.io.File;

    import java.io.FileReader;

    import java.io.IOException;

    import java.util.Scanner;

    import java.util.StringTokenizer;

     

    public class Wearmestrom {

     

    		// Scanner importiert

     

    			public static void main (String args[]){

    				Scanner sc = new Scanner(System.in);

     

    				//Informieren des Nutzers über den Anforderungsbereich

     

    				System.out.println ("Mit Hilfe dieses Programmes können Sie die U-Werte und q-Werte Ihrer Wände berechnen.");

     

    				System.out.println("");

     

    				// Objekt vom Typ Wand

     

    				Wand w= new Wand();

     

    				// While-Schleife beginnt

     

    				while (true){

     

    				//Einlesen der Dicke der Wandschicht und der Lambdawerte und Zuweisung an Wandschicht

    					//in jedem Durchlauf wird ein Objekt vom Typ Wandschicht erzeugt

     

    					Wandschicht ws;

    					ws = new Wandschicht();

     

    					File file = new File("./src/wand1.csv");

    					String line;

    					try {

    						FileReader fileReader = new FileReader(file);

    						BufferedReader bufferedReader  = new BufferedReader(fileReader);

    						// so lange lesen, wie Zeilen in der Datei vohanden sind

    							while ((line = bufferedReader.readLine()) != null ){

     

    							//die string token geschichte passiert innerhalb der while schleife

     

    							StringTokenizer stringTokenizer = new StringTokenizer(line, ";");

     

    							String token1 = stringTokenizer.nextToken (); 

    							String token2 = stringTokenizer.nextToken();

     

    							double x = Double.parseDouble(token1);

    							double y = Double.parseDouble(token2);

     

    					ws.dicke = Double.parseDouble(token1);

     

     

    					// Schleife wird so lange wiederholt, bis negative Zahl für Dicke eingegeben wird

     

    					if (ws.dicke<0 )break;

     

    					ws.lambda = Double.parseDouble(token2);

     

    					// Datenstrom schließen

    					bufferedReader.close(); }

     

     

    					// Übergabe des Objektes an Wand-Objekt

     

    					w.addSchicht(ws);	

     

    				// Ende der while-Schleife

     

    				} catch (IOException e) { e.printStackTrace();}{

     

    				}

     

    				// Innen- und Außentemperaturen werden mittels Scanner-Objekt eingelesen

    				// Übergabe der Werte an das Wand-Objekt

     

    				System.out.println("Geben Sie Außentemperatur ein! ");

    				w.setAussenTemp(sc.nextDouble());

     

    				System.out.println("Geben Sie Innentemperatur ein! ");

    				w.setInnenTemp(sc.nextDouble());

     

    				// toString()-Methode des Wand-Objektes um Zeichenkette auszugeben

     

    				System.out.println(w.toString());

     

     

     

     

     

     

    		}

     

    }

    }

Nebenprogramm Wandschicht:

Java:
    package programm;

     

    //Nebenprogramm Wandschicht

     

    public class Wandschicht {

     

    	// Attribute Lambda und Dicke

     

    	double lambda;

    	double dicke;

     

    	Wandschicht(){

     

    	}

     

     

     

     

    }

Nebenprogramm Wand:

Java:
    package programm;

     

    import java.util.ArrayList;

     

    public class Wand{

     

    //Sichtbarkeitskriterien und Datentypen zuweisen / Attribute

     

    	//Liste für Datentyp Wandschicht

    	private ArrayList<Wandschicht> m_schichten;

     

    	//Außen- und Innentemp. mit Datentyp double

    	private double m_temp_aussen;

    	private double m_temp_innen;

     

     

    	// zuweisung für Zwischenrechnungen und U und q Werte

    	private String zR1;

    	private String zR2;

    	private double u_Wert;

    	private double q_Wert;

     

     

    	public Wand(){

    		m_schichten = new ArrayList<Wandschicht>();

    		zR1 = "";

    		zR2 = "";

    		u_Wert = 0;

    		q_Wert = 0;

    	}

     

    	// diese Methode trägt übergebene Wandschicht in die Liste ein

     

    	void addSchicht(Wandschicht s){

    		m_schichten.add(s);

    	}

     

    	// get und set Methoden für die Attribute

     

    	double getAussenTemp(){

    		return m_temp_aussen;

    	}

    	void setAussenTemp(double abc){

    		m_temp_aussen = abc;

    	}

    	double getInnenTemp(){

    		return m_temp_innen;

    	}

    	void setInnenTemp(double abc){

    		m_temp_innen = abc;

    	}

     

    	// diese Methode berechnet den U-Wert aller Wandschichten und gibt ihn zurück

     

    	double getU(){

    		for(int i=0; i<m_schichten.size(); i++){

    			u_Wert = u_Wert + 1/(m_schichten.get(i).dicke / m_schichten.get(i).lambda);

    			zR1 = zR1 + "Nach Schicht "+i+" beträgt der U-Wert: "+u_Wert + " W/Km².\n";

     

    		}

    		return u_Wert;

     

    	}

     

    	double getQ(){		

    		for(int i=0; i<m_schichten.size(); i++){

    		q_Wert = q_Wert + u_Wert * (m_temp_innen - m_temp_aussen);

    		zR2 = zR2 + "Nach Schicht " +i+ " beträgt der q-Wert: " +q_Wert+ " W/m².\n";

    		}

    		return q_Wert;

     

    	}

     

    	//diese Methode gibt eine Zeichenkette mit allen wichtigen Informationen der Wand zurück

    	// Wert U und Q, alle Temperaturen der Wandschichten 

    	public String toString(){ 

    		String zR = "";

    		zR = zR + "Die Außentemperatur betraegt: " + getAussenTemp()+ " C° .\n";

    		zR = zR + "Die Innentemperatur betraegt: " + getInnenTemp()+ " C° .\n";

     

    		System.out.println("");

     

    		zR = zR + "Berechnung des U-Wertes: " + getU()+ " W/Km².\n";

    		zR = zR + "Zwischenrechnung 1: \n " + zR1 + " \n";

     

    		System.out.println("");

     

    		zR = zR + "Berechnung des q-Wertes: " + getQ()+ " W/m².\n";

    		zR = zR + "Zwischenrechnung 2: \n " + zR2 + " \n";

     

     

     

     

     

     

     

    		return zR;

    	}

     

    }
 

mashroomer

Mitglied
Nun ja, wenn ich die Dicke und die Lamda vom Nutzer über den Scanner eingeben lasse, funktioniert das einwandfrei. Dementsprechend muss die Klasse Wand beispielsweise richtig sein. Mein Problem besteht eben darin, diese zwei Werte aus einer Datein einlesen zu lassen, sodass nach jedem ";" eine neue Wandschicht erzeugt wird. Ich habe es mir so vorgestellt, dass nach dem Erzugen der Klasse Wandschicht die Zahlen aus der Datein eingelesen und den Variablen aus der Wandschicht zugeordnet werden können, sodass diese dann in der Klasse Wand in einer Formel gesetzt und berechnet werden können.
 

turtle

Top Contributor
Ich würde einen Test schreiben, der die Datei liest und die Werte, die gelesen wurden, mal testweise ausgeben. Beim Debuggen kannst du die Werte natürlich auch sehen;)

Bedeutet, in deiner Schleife
Java:
while ((line = bufferedReader.readLine()) != null ){
würde ich
Java:
System.out.println(line);
eingeben und auch token1 bzw token2 ausgeben.
 

mashroomer

Mitglied
Ich würde einen Test schreiben, der die Datei liest und die Werte, die gelesen wurden, mal testweise ausgeben. Beim Debuggen kannst du die Werte natürlich auch sehen;)

Bedeutet, in deiner Schleife
Java:
while ((line = bufferedReader.readLine()) != null ){
würde ich
Java:
System.out.println(line);
eingeben und auch token1 bzw token2 ausgeben.


Hm, aber möchte die eingelesenen Sachen nicht einfach ausgeben, sondern die sollten ja einem Datentypen zugeschrieben werden um weiter verarbeitet werden zu können. (Wahrscheinlich verstehe ich nicht ganz, was du meinst..) Ich dachte vielleicht


Java:
StringTokenizer stringTokenizer = new StringTokenizer(line, ";");
							
					String token1 = stringTokenizer.nextToken (); 
					String token2 = stringTokenizer.nextToken();

							
					ws.dicke = Double.parseDouble(token1);
					ws.lambda = Double.parseDouble(token2);

Ich dachte, dann wäre token 1 als ws.dicke deklariert und token 2 als Lambda und es würde gerade weil
Java:
	while ((line = bufferedReader.readLine()) != null ){
so lange passieren, so oft eben zwei Zahlen hintereinander in der Excel-Datein vorkommen und nach jedem ";" würde eine neue Schicht erzeugt werden.

Ansonsten, wenn ich es mir über System.out.println(line) ausgeben lasse, kann ich zwar sehen, was drin ist aber ich will es ja verabeiten lassen. ;(
 

turtle

Top Contributor
Java:
Ansonsten, wenn ich es mir über System.out.println(line) ausgeben lasse, kann ich zwar sehen, was drin ist
GENAU:toll:

Du kannst ja erst mit den Werten arbeiten, wenn sichergestellt hast, das es die richtigen Werte sind, oder?

Schritt für Schritt vorgehen, heisst hier die Devise. Was nützt dir die tollste Berechnung wenn bereits die Eingabewerte Murks sind?

Dann musst du also dafür sorgen, das die Werte korrekt sind. Danach prüfst du, ob die Berechnung passt.

Daher hätte ich angefangen, zwei verschiedene Tests zu schreiben. die beides überprüfen. Erst DANACH kannst du beides zusammenbauen und weisst bereits, das die Teile funktionieren.
 

mashroomer

Mitglied
Dann musst du also dafür sorgen, das die Werte korrekt sind. Danach prüfst du, ob die Berechnung passt.

Daher hätte ich angefangen, zwei verschiedene Tests zu schreiben. die beides überprüfen. Erst DANACH kannst du beides zusammenbauen und weisst bereits, das die Teile funktionieren.

Ich dachte eigentlich, es ist recht einfach eine Excelltabelle lesen zu lassen, in es eben vier mal zwei verschiedene Werte (siehe Anhang) vorkommen.

Eigentlich ist es doch so:
x;y
x;y
x;y
x;y

das sind vier Schichten, getrennt durch " " - also Leerzeichen. Und Java hat den StringTokenizer um solche Sachen zu lesen und in Token umwandeln zu lassen, sodass man diese dann deklarieren und weiterverarbeiten kann.

Java:
StringTokenizer stringTokenizer = new StringTokenizer(line, " ");
							
	String token1 = stringTokenizer.nextToken (); 
	String token2 = stringTokenizer.nextToken();

Danke auf jeden Fall erstmal für die bereitsgeleistete Hilfe, ich arbeite schon seit einigen Wochen daran und weiß einfach nicht weiter. Wenn ich keinen Reader einbauen müsste, wäre alles Prima, aber so entstehen jetzt Schwierigkeiten, die ich irgendwie nicht verstehe. Außerdem ist meine Syntax einfach zu schelcht.

Ich dachte durch
Java:
ws.dicke = Double.parseDouble(token1);
                    ws.lambda = Double.parseDouble(token2);
und die Schleife, die immer eine neue Schicht erzeugt, solange Werte vorhanden sind, würde das ziemlich locker über die Bühne gehen aber ich übersehe etwas, was das unmöglich macht.
 

Anhänge

  • werte.PNG
    werte.PNG
    3,5 KB · Aufrufe: 13

turtle

Top Contributor
Ich dachte eigentlich, es ist recht einfach eine Excelltabelle lesen zu lassen,
Was DU mit ExcelTabelle bezeichnest, nennen WIR eine CSV Datei (comma-separated values), wobei bei dir nicht ein Komma sondern das Semikolon steht, wird aber trotzdem so genannt;)

Eigentlich ist es doch so:
x;y
x;y
x;y
x;y

das sind vier Schichten, getrennt durch " " - also Leerzeichen
Das sieht für mich anders aus, als das was du schreibst. In deinem Beispiel sind die multiplen Werte durch Zeilentrenner getrennt. Es wäre hilfreich, wenn du mal Beispeile aus deiner CSV-Datei posten könntest.

Ich bin ein Verfechter von TDD, also Schreiben eines Testes BEVOR man anfängt irgendetwas zu implementieren. Deine "Annahmen" könnte man also schön in einen Test überprüfen.

Das habe ich mal gemacht, wobei ich nicht genau weiss, ob die Namen so richtig "passen".

Jedenfalls siehst du, werden die richtigen Werte in Wand gespeichert und du kannst damit weiter rechnen.
Java:
public class SplitTest {

	@Test
	public void test() {
		String csvTest = "12.34;56.78 21.54;65.87";
		List<Wand> listWand = new ArrayList<>();
		StringTokenizer stringTokenizer = new StringTokenizer(csvTest, " ");
		while (stringTokenizer.hasMoreTokens()) {
			String token1 = stringTokenizer.nextToken();
			String[] split = token1.split(";");
			double dicke = Double.parseDouble(split[0]);
			double lamda = Double.parseDouble(split[1]);
			Wand wand = new Wand(dicke, lamda);
			listWand.add(wand);
		}
		assertEquals(2, listWand.size());
		assertEquals(12.34, listWand.get(0).getDicke(), 0.001);
		assertEquals(56.78, listWand.get(0).getLambda(), 0.001);

		assertEquals(21.54, listWand.get(1).getDicke(), 0.001);
		assertEquals(65.87, listWand.get(1).getLambda(), 0.001);
	}
}

class Wand {
	private double dicke;
	private double lambda;

	public Wand(double dicke, double lambda) {
		this.dicke = dicke;
		this.lambda = lambda;
	}

	public double getDicke() {
		return dicke;
	}

	public void setDicke(double dicke) {
		this.dicke = dicke;
	}

	public double getLambda() {
		return lambda;
	}

	public void setLambda(double lambda) {
		this.lambda = lambda;
	}

}
Bleibt noch zu klären, wie das ganze aussieht, wenn die Daten aus einer CSV-Datei kommen.

Vorgehensweise: Einen Test schreiben und prüfen, ob richtig gelesen wird
Java:
import static org.junit.Assert.assertEquals;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.junit.Test;

public class SplitTest {

	@Test
	public void test() {
		// Eine Zeile getrennt durch Leerzeichen
		String csvTest = "12.34;56.78 21.54;65.87";
		List<Wand> listWand = new ArrayList<>();
		StringTokenizer stringTokenizer = new StringTokenizer(csvTest, " ");
		while (stringTokenizer.hasMoreTokens()) {
			String token1 = stringTokenizer.nextToken();
			String[] split = token1.split(";");
			double dicke = Double.parseDouble(split[0]);
			double lamda = Double.parseDouble(split[1]);
			Wand wand = new Wand(dicke, lamda);
			listWand.add(wand);
		}
		assertEquals(2, listWand.size());
		assertEquals(12.34, listWand.get(0).getDicke(), 0.001);
		assertEquals(56.78, listWand.get(0).getLambda(), 0.001);

		assertEquals(21.54, listWand.get(1).getDicke(), 0.001);
		assertEquals(65.87, listWand.get(1).getLambda(), 0.001);
	}

	@Test
	public void fileTest() throws IOException {
		File testFile = new File("test.csv");
		// hier zwei Zeilen
		// 12.34;56.78
		// 21.54;65.87
		List<Wand> listWand = new ArrayList<>();
		try (BufferedReader bufferedReader = new BufferedReader(new FileReader(testFile))) {
			String line = null;
			while ((line = bufferedReader.readLine()) != null) {
				String[] split = line.split(";");
				double dicke = Double.parseDouble(split[0]);
				double lamda = Double.parseDouble(split[1]);
				Wand wand = new Wand(dicke, lamda);
				listWand.add(wand);
			}
		}
		assertEquals(2, listWand.size());
		assertEquals(12.34, listWand.get(0).getDicke(), 0.001);
		assertEquals(56.78, listWand.get(0).getLambda(), 0.001);

		assertEquals(21.54, listWand.get(1).getDicke(), 0.001);
		assertEquals(65.87, listWand.get(1).getLambda(), 0.001);
	}
}

class Wand {
	private double dicke;
	private double lambda;

	public Wand(double dicke, double lambda) {
		this.dicke = dicke;
		this.lambda = lambda;
	}

	public double getDicke() {
		return dicke;
	}

	public void setDicke(double dicke) {
		this.dicke = dicke;
	}

	public double getLambda() {
		return lambda;
	}

	public void setLambda(double lambda) {
		this.lambda = lambda;
	}

}
 

mashroomer

Mitglied
Ui, vielen Danke erstmal für die geleistete Arbeit!

Wie die Werte in der CSV-aussehen, habe ich im Anhang drangeheftet.

Ich bin mit meiner Methode zwar weiter gekommen:

Java:
package programmBeleg;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Wearmestrom {

		// Scanner importiert
	
	public static void main (String [] args){
		
		Scanner sc = new Scanner(System.in);
		
		//Informieren des Nutzers über den Anforderungsbereich
		
		System.out.println ("Mit Hilfe dieses Programmes können Sie die U-Werte und q-Werte Ihrer Wände berechnen.");
		
		System.out.println("");
		
		// Objekt vom Typ Wand

	Wand w = new Wand();

	
		// Eine Wandschicht wird erzeugt
	Wandschicht ws;
	ws = new Wandschicht();

		// Die Werte aus der Excel-Datei werden eingelesen
	File file = new File("./src/wand1.csv");
	String line;
		try {
			
		//Initialisieren von Reader und Buffer
	FileReader fileReader = new FileReader(file);
	BufferedReader br  = new BufferedReader(fileReader);
		//Lesen solange die Datei nicht ihr Ende erreicht
	while ((line = br.readLine()) != null ){
		
		//Abgrenzen der Datenströme durch Semikolon
		
		StringTokenizer stringTokenizer = new StringTokenizer(line,";");
		
		//die erste Zahl soll token 1 und die zweite toke 2 werden
		//dann soll token 1 zu dicke und token 2 zu lambda zugeordnet werden
		
		String token1 = stringTokenizer.nextToken (); 
		String token2 = stringTokenizer.nextToken();  
		
		ws.dicke = Double.parseDouble(token1);
		ws.lambda = Double.parseDouble(token2);
		
		}
		// Datenstrom schließen
		br.close();
	} catch (IOException e) { e.printStackTrace(); }
	
	// Übergabe des Objektes an Wand-Objekt
		w.addSchicht(ws);	
		
	
	//Manuelle Eingabe von Innen und Außentemperatur über den Scanner. Für den Test sitzen da aber -10 und 22 fest.

		System.out.println("Geben Sie Außentemperatur ein! ");
		w.setAussenTemp(-10);
		
		System.out.println("Geben Sie Innentemperatur ein! ");
		w.setInnenTemp(22);
	
		// toString()-Methode des Wand-Objektes um Zeichenkette auszugeben
		
		System.out.println(w.toString());
		
		
	}
}

Und das kommt daraus:

Die Außentemperatur betraegt: -10.0 C° .
Die Innentemperatur betraegt: 22.0 C° .
Berechnung des U-Wertes: 93.33333333333333 W/Km².
Zwischenrechnung 1:
Nach Schicht 0 beträgt der U-Wert: 93.33333333333333 W/Km².

Berechnung des q-Wertes: 2986.6666666666665 W/m².
Zwischenrechnung 2:
Nach Schicht 0 beträgt der q-Wert: 2986.6666666666665 W/m².



Was an sich ganz okay ist aber offenbar arbeitet das Programm bloß mit den ersten zwei Werten. Aber ehrlich gesagt weiß ich es nicht. :bahnhof: Ich habe gedacht durch w.addSchicht(ws); würde eine neue Schicht erzeugt werden, solange die Werte da sind. Aber ich sehe gerade du hast mit Array gearbeitet und ich habe gestern auch diesen Weg versucht, leider ist es mir einfach nicht gelungen. :bloed: Naja, ich werde mir gleich das von dir gepostete genauer anschauen! Vielen lieben Dank soweit!
 

Anhänge

  • werte.PNG
    werte.PNG
    3,5 KB · Aufrufe: 13
Zuletzt bearbeitet:

Neue Themen


Oben