# Speicherung von Spieldaten



## Der kuhle Tüp (14. Jul 2019)

Hallo Leute,
ich schreibe gerade an einer GameEngine und bin gerade dabei die Spieldaten-Speicherung zu coden. Doch ich habe ein Problem:
Das erstellen einer neuen txt Datei und das beschreiben dieser Funktioniert einwandfrei. Doch wenn ich das Programm schließe und erneut öffne ist die Textdatei wieder leer. Ich vermute das die Datei überschrieben wird, aber ich weiss nicht wie ich den Fehler beheben soll. Deshalb bitte ich euch um Hilfe.
Hier mein Testcode:

```
package main;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class Main {
    
    public static void main(String[] args) {
        
        String path = "test.txt";
        PrintWriter writer;
        
        File file = new File(path);
        try {
            writer = new PrintWriter(new BufferedWriter(new FileWriter(path)));
            writer.println("Hallo");
            writer.println("na du kleiner Fratz");
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
    
}
```

Danke schon im Vorraus! Euer kuhler Tüp!


----------



## Javinner (14. Jul 2019)

Startet das Programm das erste Mal, existiert die Datei noch nicht. Also prüfst du beim Starten, ob die Datei existiert. Wenn nicht, erstellen, wenn ja, einlesen.


----------



## Der kuhle Tüp (14. Jul 2019)

Das Problem dabei ist aber um zu Testen ob die Datei existiert muss ich file erst Initialisieren und dabei wird immer automatisch die Datei überschrieben


----------



## httpdigest (14. Jul 2019)

Ein einfaches `File file = new File(path);` wird *garantiert* *nicht* die Datei anfassen, geschweige denn überschreiben.


----------



## Der kuhle Tüp (14. Jul 2019)

Das dachte ich auch aber in dem Code wird auch nirgendwo ein file.createNewFile() genannt


----------



## httpdigest (14. Jul 2019)

In welchem Code und warum machst du das? Lass das doch einfach weg.
Ups, sorry, verlesen. Du hast ja _nirgendwo_ geschrieben.
Übrigens: `new FileWriter(path)` setzt den Dateiinhalt ebenfalls zurück.
Also: Wenn du nur und ausschließlich `File file = new File(path);` machst und auf dem File Objekt per exists() prüfst, ob es die Datei schon gibt, ist alles okay.


----------



## Xyz1 (14. Jul 2019)

Man würd das kapseln:

```
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public class Iwas {
	private static Iwas iwas = null;
	public final Properties probs; // can be private

	public static Iwas newIwas(String[][] defaults) throws IOException {
		if (iwas == null)
			iwas = new Iwas(defaults);
		return iwas;
	}

	private Iwas(String[][] defaults) throws IOException {
		probs = new Properties();
		for (String[] e : defaults) {
			probs.put(e[0], e[1]);
		}
		File file = new File("toll.txt");
		if (file.canRead())
			probs.load(new FileInputStream(file));
	}

	public void store() throws IOException {
		probs.store(new FileOutputStream("toll.txt"), "Hier steht ein Kommentar.");
	}

	public String get(String k) {
		return probs.getProperty(k);
	}

	public void put(String k1, String k2) {
		probs.put(k1, k2);
	}

	public static void main(String[] args) throws IOException {
		Iwas i = newIwas(new String[][] { { "text_a", "Hier steht dein Toller Text" } });
		i.probs.list(System.out);
		i.store();
	}
}
```


Deine Programmdaten stehen dann in der Textdatei "toll.txt".


----------



## Der kuhle Tüp (15. Jul 2019)

httpdigest hat gesagt.:


> Übrigens: `new FileWriter(path)` setzt den Dateiinhalt ebenfalls zurück.



Gibt es denn einen Writer der dies nicht tut, weil FileOutputReader tut dies wie ebend getestet auch?!


----------



## httpdigest (15. Jul 2019)

Instanziiere den doch erst gar nicht.


----------



## kneitzel (15. Jul 2019)

Was genau willst Du denn machen? Wenn Du eine Datei zum Schreiben öffnest, dann ist bei FileWriter die Datei sofort leer, weil eine neue Datei erzeugt wird.
Ein FileOutputStream meinst Du ansonsten, denn Output und Reader widerspricht sich etwas, oder liege ich da falsch?

Bei dem FileOutputStream kannst Du auch was anfügen. Dazu dann den Konstruktor mit 2 Argumenten benutzen und den zweiten Parameter (append) auf true setzen.

Aber generell ist die Frage, was Du machen willst. Ich fürchte, dass wir hier sogenannte xy Probleme diskutieren (Du willst x machen und meinst, y wäre die richtige Lösung. Aber y klappt nicht.... Da kann man dann lange y diskutieren, aber x wirst Du nicht wirklich gelöst bekommen....)


----------



## kneitzel (15. Jul 2019)

Oder versuchst Du zu lesen und nutzt nur die falschen Klassen? Alles was Output oder Writer im Namen hat, ist schon falsch. Zum Lesen brauchst Du dann Klassen mit Input oder Reader, also FileInputStream oder FileReader!


----------



## Der kuhle Tüp (15. Jul 2019)

Ich möchte ein paar Methoden schreiben mit dennen man eine Datei erstellen, in diese herreinschreiben und auch wieder auslesen kann.
Aber das Problem in meinem Code ist, dass der FileWriter beim initialisieren die Datei leert. Jetzt stehe ich also vor der frage wie ich das verhindere.


----------



## Xyz1 (15. Jul 2019)

guckst du mal hier:





						Java: How to append text to a file with the FileWriter class | alvinalexander.com
					






					alvinalexander.com


----------



## kneitzel (15. Jul 2019)

Wo ist das Problem genau?
FileWriter / FileOutputStream = Datei schreiben. Also schreibst Du die Datei! Wenn Du auf einen Zettel schreibst, dann brauchst Du einen leeren Zettel, oder nicht?

FileReader / FileInputStream = Datei lesen. Wenn Du einen Zettel liest, dann verändert sich das, was auf dem Zettel steht, ja nicht.

Also wo genau ist das Problem?

Du hast eine Datei mit Spieldaten. Diese liest Du komplett ein und kannst diese anpassen.
Dann speicherst Du die Spieldaten, d.h. die alte Daten kommen weg und Du speicherst die Daten komplett neu.

Wenn Du nicht die alten Daten wegwerfen willst, dann kannst Du mit FileOutputStream auch Daten an die Datei anhängen (siehe eine frühere Antwort von mir). Wenn Das nicht ausreicht, dann musst Du die Daten aus der Datei lesen, anpassen wie Du es neu haben willst und dann komplett schreiben.

Es gibt natürlich auch noch deutlich mehr Möglichkeiten, aber diese sind dann deutlich schwerer zu nutzen. RandomAccessFile z.B. - Da kann man dann gezielt einzelne Bytes überschreiben und so. Aber da muss man dann deutlich mehr aufpassen. Das geht z.B. sehr gut, wenn Du z.B. Datensätze einer festen Größe hast....


----------



## Xyz1 (15. Jul 2019)

kneitzel hat gesagt.:


> Wo ist das Problem genau?
> FileWriter / FileOutputStream = Datei schreiben. Also schreibst Du die Datei! Wenn Du auf einen Zettel schreibst, dann brauchst Du einen leeren Zettel, oder nicht?


Du scheinst das Problem noch nicht erkannt zu haben aber dennoch zu antworten...


----------



## kneitzel (15. Jul 2019)

Tobias-nrw hat gesagt.:


> Du scheinst das Problem noch nicht erkannt zu haben aber dennoch zu antworten...


Wenn das reine Anhängen sein Problem gewesen wäre, dann wäre meine Antwort #10 schon die Lösung. Somit hast Du das Problem ganz offensichtlich auch nicht verstanden und zudem dem Thread nicht einmal richtig gelesen.

Und ich versuche erneut zu ermitteln, wo sein Problem ist - im Gegensatz zu Dir! Aber toll, wie Du auch direkt einem Neuling irgendwelche Codeschnipsel von Dir um die Ohren haust ... hat ihm ganz offensichtlich auch nicht geholfen ....

Also bleib einfach bei der Sache, wenn Du dies kannst - aber das kannst Du offensichtlich nicht!


----------



## Der kuhle Tüp (15. Jul 2019)

Leute bitte streitet nicht! Ihr versucht mir beide zu helfen dafür auch erstmal danke!


----------



## Xyz1 (15. Jul 2019)

Ich streite mich nicht, ich habe seinen Beitrag gemeldet, mehr kann man hier zur Deeskalation nich machen.


----------



## kneitzel (15. Jul 2019)

Du reagierst ständig auf meine Posts. Habe ich Dich in der Vergangenheit so sehr getroffen? Und dann diese Vorwürfe, ohne dabei zu erkennen, dass diese doch 1:1 auch auf dich zutreffen...


----------



## Der kuhle Tüp (16. Jul 2019)

Ich habe jetzt nocheinmal ein wenig herumprobiert und ENDLICH geht es. Un für die, die sich dafür interessieren, hier meine Methoden:

```
package main;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class SaveFile {
    
    private boolean isWriterRunning;
    private String[] strings = new String[10000];
    private int lenght = 0;
    
    private File file;
    private PrintWriter writer;
    private BufferedReader reader = null;
    
    //File-Erstellungs-Konstruktor
    
    public SaveFile(String path) {
        file = new File(path);   
        if(!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    //Write Methoden
    
    public void println(String string) {
        if(!isWriterRunning) {
            isWriterRunning = true;
            try {
                writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        writer.println(string);
    }
    
    public void print(String string) {
        if(!isWriterRunning) {
            isWriterRunning = true;
            try {
                writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        writer.print(string);
    }
    
    public void write() {
        writer.flush();
    }
    
    public void reset() {
        writer.close();
        try {
            writer = new PrintWriter(new BufferedWriter(new FileWriter(file)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void closeWriter() {
        isWriterRunning = false;
        writer.close();
    }
    
    public void openWriter() {
        
        for(int i = 1; i <= getLines(); i++) {
            strings[i] = readLine(i);
            lenght = i;
        }
        for(int i = 1; i <= lenght; i++) {
            println(strings[i]);
        }
    }
    
    //Read Methoden
    
    public String readLine(int line) {
        if(line <=0) {
            return null;
        }
        try {
            reader = new BufferedReader(new FileReader(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        String string = null;
        int zeile = 0;
        try {
            while ((string = reader.readLine()) != null) {
                zeile++;
                if(zeile == line) {
                    reader.close();
                    return string;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
        
    }
    
    public void closeReader() {
        try {
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public int getLines() {
        
        int line = 1;
        
        while(readLine(line) != null) {
            line++;
        }
        line--;
        return line;
        
    }
    
}
```
Danke nochmal an alle für ihr bemühen mir zu helfen!


----------



## fhoffmann (16. Jul 2019)

Hallo,

hast du einmal überlegt, wie oft du eine Datei mit beispielsweise 1.000 Zeilen öffnest und wieder schließt und wieviele Zeilen du liest, wenn du getLines() aufrufst?


----------



## Meeresgott (16. Jul 2019)

Wenn ich einen Gedanken in die Diskussion werfen darf.
Nach meinem Verständnis ließt und schreibst nur deine Software in diese Datei rein, also kannst du auch das Dateiformat bestimmen. Um an @fhoffmann Gedanken anzuknüpfen würde ich dir eine Embedded Datenbank vorschlagen wie z.B. H2 diese kann performanter Arbeiten, als ein simpler Textfile. 

Falls du nicht über die Datei Suchen musst sondern in deiner Anwendung immer alle Daten beim Start lädst was spricht gegen das Arbeiten mit einem POJO und dem Interface Serializable ? Also was spricht gegen die Binäre Speicherung deiner Daten, da diese Art der Speicherung den Vorteil hat, dass keine Formatierung zu den lese bzw. schreib Vorgängen gehört. Was deine Anwendung Zeit beim laden und speichern spart.


----------

