Sinnvolle Klassenhierachie zum Speichern von Dateien

Degget

Mitglied
Ich muss bei einer Aufgabe zum ersten mal eine Liste/Map in eine Datei schreiben und diese dann speichern. Quick and Dirty habe ich mir diese Methode dafür gemacht
Java:
	public static void speichereMapinTxt(String dateiname, Map map)
	{

		try
		{
			String writeString = "";
			BufferedWriter writer = new BufferedWriter(new FileWriter(dateiname + ".txt"));
			writer.write(writeString + map.toString());
			writer.close();
		} catch (IOException e)
		{
			e.printStackTrace();
		}

	}

Nun ist das eher eine Notlösung, weil der Abgabetermin der Aufgabe naht. Ich würde eigentlich lieber gleich eine vernünftige, wiederverwendbare Klassenhierachie (oder auch nur eine Klasse) schreiben, die mir gleich viele Methoden zum Speichern anbietet, die ich öfter benötigen werde. Da ich, wie gesagt, noch nicht viel mit dem Abspeichern zu tun hatte und nicht genau weiß, was dort nun wichtig ist, habe ich keine konkrete Idee für ein Konzept. Hat jemand für euch schon mal so etwas geschrieben und mag mir einen Ratschlag geben?
Danke
 
hm, kommt ganz drauf an, was für methoden du da benötigst!? kann dir ja hier keiner sagen. geht es um verschiedene collections? was haben die verschiedenen methoden für (unterschiedliche) aufgaben? vielleicht kommst du auch mit serialisierung weiter!?
 
Sagen wir einfach mal, dass es darum geht, den Inhalt verschiedener Collections zu speichern.
Was wäre da ein guter Ausgangspunkt? Von meinem jetzigen Stand aus würde ich einfach zusätzlich
public static void speichereListinTxt(String dateiname, List list)
public static void speichereSetinTxt(String dateiname, Set Set)
public static void speichereMapinCsv(String dateiname, Map map)
.
.
.

Könnte man irgendwie eine Methode speichereCollectioninDatei schreiben, die allein durch ihre Parameter so flexibel wie die obrigen Methoden reagieren würde?
An sich will ich einfach nur einen möglichst allgemeinen Ansatz für eine Klasse(nhierachie) haben, die mir das Speichern verschiedenster Datentypen auf verschiedenste Weise ermöglicht.

Weißt du, was ich meine?
 
kleines beispiel:
Java:
import java.io.*;
import java.util.*;
import java.util.Map.Entry;


public class FileManager {
	
	private BufferedWriter writer;
	
	public FileManager( String file ) throws IOException {
		writer = new BufferedWriter( new FileWriter( file ) );
	}
	public FileManager( String file, boolean append ) throws IOException {
		writer = new BufferedWriter( new FileWriter( file, append ) );
	}
	public void mapToFile( Map<?, ?> input, String delimiter ) throws IOException {
		for ( Entry<?, ?> e : input.entrySet() ) {
			writer.write( e.getKey().toString() + ", " + e.getValue().toString() + delimiter );
		}	
	}
	public void listToFile( List<?> input, String delimiter ) throws IOException {
		for ( Object o : input ) {
			writer.write( o.toString() + delimiter );
		}	
	}
	public void close() throws IOException {
		writer.close();
	}
}
Java:
import java.io.IOException;
import java.util.*;

public class TestFileManager {
	public static void main( String[] args ) throws IOException {
		FileManager fm = new FileManager( "C:/test.txt", true );
		List<String> list = new ArrayList<String>();
		list.add( "Das" );
		list.add( "ist" );
		list.add( "eine" );
		list.add( "Liste" );
		fm.listToFile( list, "\r\n" );
		
		Map<Integer, String> map = new HashMap<Integer, String>();
		map.put( 1, "Das" );
		map.put( 2, "ist" );
		map.put( 3, "eine" );
		map.put( 4, "Map" );
		fm.mapToFile( map, "\r\n" );
		fm.close();
	}
}

edit: set kannste ja anhand des beispiels selber machen
 
Oder...
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.List;

public class Test {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        
        List<String> list = read(write(Arrays.asList("foo", "bar", "baz")));
        
        for (String s : list) {
            System.out.println(s);
        }
    }
    
    static File write(Object obj) throws IOException {
        File file = File.createTempFile("foo", ".tmp");
        file.deleteOnExit();
        ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
        os.writeObject(obj);
        return file;
    }
    
    @SuppressWarnings("unchecked")
    static List<String> read(File file) throws IOException, ClassNotFoundException {
        ObjectInputStream is = new ObjectInputStream(new FileInputStream(file));
        return (List<String>) is.readObject();
    }
}
 
zur datenerhaltung bzw. wenn du die liste zu einem späteren zeitpunkt wieder auslesen willst eignet sich serialisierung natürlich deutlich besser
 
Danke. Sind schon mal 2 gute Ideen 🙂

Warum hast du, nrg, die close()-Methode eigtl nicht direkt in die ...toFile()-Methode integriert? Ich dachte, dass man sowieso jeden writer wieder closen sollte?

zur datenerhaltung bzw. wenn du die liste zu einem späteren zeitpunkt wieder auslesen willst eignet sich serialisierung natürlich deutlich besser

Von Serialisierung weiß ich noch gar nichts. Werde mich da mal reinlesen. Kurze Frage schon vorher: warum ist es besser? Perfomance oder Einfachheit der Anwendung?

edit:
Moment. Das was faetzminator macht ist im Prinzip schon Serialisierung, oder?
 
Zuletzt bearbeitet:
Warum hast du, nrg, die close()-Methode eigtl nicht direkt in die ...toFile()-Methode integriert? Ich dachte, dass man sowieso jeden writer wieder closen sollte?

wenn du die klasse von aussen verwendest, wäre es sinnvoll auch selbst entscheiden zu können, wann der stream geöffnet bzw geschlossen wird. ein bufferedreader wird doch auch nicht mit new BufferedReader() instanziiert und dann in der write(String filename, String input) geöffnet und direkt wieder geschlossen. das wäre zudem absolut unperformant.

Von Serialisierung weiß ich noch gar nichts. Werde mich da mal reinlesen. Kurze Frage schon vorher: warum ist es besser? Perfomance oder Einfachheit der Anwendung?

du packst halt dein komplettes object in einen stream und schreibst es in eine datei. dann brauchst du dir überhaupt keine gedanken darüber zu machen, wie du das speicherst bzw wie du es passend wieder ausliest. das macht alles die api für dich. würde dir hier aber xml empfehlen. voraussetzung dafür ist aber eine bean konforme klasse

edit:
Moment. Das was faetzminator macht ist im Prinzip schon Serialisierung, oder?
ja
 
ja, ne kombination aus generics und serialisierung sollte der beste mittelweg sein. ich denke aus den codes von faetzminator und nrg wirst du dir was zusammen bauen können 🙂
 
Also, ich seh da in nrg's Code nicht viel an Generics 😀 Ich würde höchstens diese zwei Methoden in eine Klasse Auslagern, dort ggf. [c]file[/c] intern verwalten und den Typen von [c]read()[/c] per Generics festlegen.
 
kleines beispiel:
Java:
	public void mapToFile( Map<?, ?> input, String delimiter ) throws IOException {

Ich habe es bisher einfach hingenommen, weil es so toll funktionierte, aber was genau macht das Fragezeichen als Datentyp eigentlich? Wäre es dasselbe, als wenn ich Object schreiben würde? Sah es jetzt das reste mal in der Anwendung...
 
Wie wärs so?
Java:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;
import java.util.List;

public class Test<T> {

    public static void main(String[] args) throws IOException, ClassNotFoundException {

        Test<List<String>> test = new Test<List<String>>("test");
        test.write(Arrays.asList("foo", "bar", "baz"));

        List<String> list = test.read();

        for (String s : list) {
            System.out.println(s);
        }
    }

    private File file;

    public Test(String name) throws IOException {
        file = File.createTempFile(name, null);
        file.deleteOnExit();
    }

    public void write(T obj) throws IOException {
        ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream(file));
        os.writeObject(obj);
        os.close();
    }

    @SuppressWarnings("unchecked")
    public T read() throws IOException, ClassNotFoundException {
        ObjectInputStream is = new ObjectInputStream(new FileInputStream(file));
        T t = (T) is.readObject();
        is.close();
        return t;
    }
}
[c]Test[/c] kann man allenfalls noch umbenennen 🙂
 
Danke für eine weitere Lösung. Das Serialisieren gefällt mir an sich sehr.
Ich wäre trotzdem noch an einer Antwort auf die Frage, was genau das "?" in zum Beispiel Map<?, ?> bewirkt. Ist es wie Map<Object, Object> oder noch was anderes?
 
Danke für eine weitere Lösung. Das Serialisieren gefällt mir an sich sehr.
Ich wäre trotzdem noch an einer Antwort auf die Frage, was genau das "?" in zum Beispiel Map<?, ?> bewirkt. Ist es wie Map<Object, Object> oder noch was anderes?

Ja, das heisst, es ist unklar, von welchem Typ die Daten sind. Problem ist dabei, dass dann die Map gecastet werden muss. Bei meinem Code schert sich der Programmierer nicht mehr drum, einfach ein Mal eine Instanz mit Generics anlegen, danach schreiben und lesen wie man will.
 
Ja, das heisst, es ist unklar, von welchem Typ die Daten sind. Problem ist dabei, dass dann die Map gecastet werden muss. Bei meinem Code schert sich der Programmierer nicht mehr drum, einfach ein Mal eine Instanz mit Generics anlegen, danach schreiben und lesen wie man will.

und wo muss man bei meinem explizit casten? dadurch, dass jede klasse eine toString() (im zweifelsfall von object geerbt) hat ist mir das doch grad egal, von welchem typ das ist. @to: falls es dir noch unklar ist, google mal wildcards java

edit: aber gut hast schon recht. die klasse gleich generisch zu instanziieren, ist schon ein stück eleganter.. war ja nur ein vorschlag 🙂
 

Neue Themen


Zurück
Oben