Java mehrere Array (object/Int) in File speichern (Minecraft)

pitman-87

Cadet 3rd Year
Registriert
Feb. 2010
Beiträge
60
Hey Leute,

hab für Minecraft einen Mod geschrieben der Teile der Map kopiert und woanders wieder einfügen kann: http://www.minecraftforum.net/topic/334760-15-01-magicbox/

Das kopierte Gelände geht jedoch verloren, sobald Minecraft geschlossen wird, da die Daten als Static in einer Klasse gespeichert werden.

Das soll nun geändert werden.

Dazu würde ich gern eine Datei anlegen die folgende Daten speichert:

- zwei 3-dimensionale Arrays aus int-Zahlen
- ein 3-dim. Array aus Objekten

Was das für ne Datei wird (.txt .dat .bin) ist mir relativ egal.
Am besten sollten alle Daten in nur einer Datei gespeichert werden, um diese handlicher für den User zu machen, somit sollte es möglich sein die Dateien mit anderen Leuten zu tauschen.

Ich programmiere erst seit 2Jahren Java (oder überhaupt) und würde gern wissen wie ich das am besten anstellen kann.

Wie man ein Array aus Zahlen in ne txt speichert weis ich, aber keine Ahnung wie ich das mit den Objekten anstelle, bzw alles in einer Datei.
 
Arrays sind Objekte.
Ein schnelle und einfache Möglichkeit wäre es die Klassen ObjectOutputStream und ObjectInputStream zu verwenden. Sie machen genau das, was man vermuten würde.
 
Das hört sich schonmal gut an danke.

Ich könnte ja jetzt alle 3 Arrays hintereinander reinschreiben, aber wie siehts denn mit auslesen aus, wann weis ich wann welches Array beginnt?
 
Das weiß Java selber.
 
Pff das ja einfacher als ich dachte ^^

Thx
 
Naja, so ganz weiß Java das nicht, man muss schon wissen, wann man was in welcher Reihenfolge geschrieben hat.

Wenn du 3 einzelne Arrays A, B, C hast und die in den ObjectOutputstrem in dieser Reihenfolge schreibst, dann kommen die nachher beim Einlesen auch in genau dieser Reihenfolge wieder raus.

Umgehen kannst du das, indem du ganz einfach eine neue Klasse erzeugst, welche du als "Hülle" verwendest, z.b.

PHP:
public class MeinSpeicherFormat {

  private int[]  a;
  private int[]  b;
  private int[]  c;

  public MeinSpeicherFormat(int[] a, int[] b, int[] c )
  {
     ..........
  }

  // getter

}


Nach dem erzeugen der Hülle mit deinen Daten kannst du dann ganz einfach genau dieses eine Objekt in den ObjectOutputStream schreiben und bekommst später beim Einlesen genau dieses eine Objekt wieder raus und zwar mit allen Unterobjekten, die darin gespeichert sind, das übernimmt Java in der Tat vollautomatisch für dich.
 
Banthor schrieb:
Wenn du 3 einzelne Arrays A, B, C hast und die in den ObjectOutputstrem in dieser Reihenfolge schreibst, dann kommen die nachher beim Einlesen auch in genau dieser Reihenfolge wieder raus.

Das konnt ich mir auch schon denken ^^

Da es sich nur um eine Klasse handelt, wo das angewendet werden muss, reciht es auch wenn ich 2 Methoden zum lesen/schreiben implementiere.

Trotzdem danke :)
 
Iwie klappt das beim 3. Array aus Objekten nicht ganz.

Hab import Serializable drin usw.

Jedoch schreibt er mir nicht die Objecte rein, kann es daran liegen dass manche Objekte null sind oder das in dem Objekt noch andere Objekte drin sind?


Edit: Da sind noch soviele Objekte drin das kann ich knicken -.-

Dann müsste ich zu tief in Minecraft herumpfuschen.

Noch jemand eine andere Idee wie ich das anstellen könnte?
 
Zuletzt bearbeitet:
Ohne die Struktur und den Inhalt des Arrays zu kennen, können wir nur die Glaskugel befragen. Da muss schon mehr Input deinerseits kommen.
 
Ist zwar schon etwas her aber hab noch ne Verständnisfrage.

Ich hab ein neues Objekt erzeuge und in einer Datei gespeichert, nun möchte ich die Datei später wieder auslesen, hab aber die Objekt-Klasse etwas abgeändert, zB zusätzliche Methoden/ Variablen (zusätzlich, die alten sind alle noch vorhanden) wird man dann das, im File gespeicherte Objekt, trotzdem korrekt auslesen oder wird dann alles verhauen?
 
Normalerweise sollte jede Klasse, die serialisierbar ist (also Serializable implementiert), auch eine UID haben.

class A implements Serializable {
private static final long serialVersionUID = 123L;
...
}

Diese sollte man ändern, sobald man die Variablen in der Klasse ändert (deren Reihenfolge, eine dazu, eine weg, usw.). Neue Methoden sind egal, die haben keinen Einfluss auf die Daten. Wenn man dann versucht ein Objekt mit Hilfe der falschen Klassenversion zu laden, wird eine Exception (InvalidClassException) geschmissen. Das Verwalten der UID kann soweit ich weiß auch Eclipse übernehmen.

Was passiert, wenn man die UID nicht drin hat bzw. hochzählt und sich die Datenstruktur der Klasse trotzdem ändert, weiß ich leider auch nicht.
 
Du schreibst, Eclipse kann die UID automatisch verwalten. Wo schaltet man das ein?
Dass er auf Knopfdruck eine Standard UID oder eine automatisch generierte hinzufügt, weiß ich. Aber da gibt's auch eine Automatik?
 
War anscheinend doch nur Halbwissen. Ich hatte das aus ner Folie zu einer Vorlesung für Verteilte Systeme und habs einfach mal geglaubt :)
Eclipse übernimmt auf Wunsch das automatische Ändern der Versionsnummer bei geänderter Klassendefinition.
Scheint aber so nicht zu stimmen, damit sie nach einer Änderung angepasst wird, muss man die alte UID löschen und sie nochmals generieren lassen.

Dafür hab ich jetzt die Antwort für den OP:
pitman-87 schrieb:
Ich hab ein neues Objekt erzeuge und in einer Datei gespeichert, nun möchte ich die Datei später wieder auslesen, hab aber die Objekt-Klasse etwas abgeändert, zB zusätzliche Methoden/ Variablen (zusätzlich, die alten sind alle noch vorhanden) wird man dann das, im File gespeicherte Objekt, trotzdem korrekt auslesen oder wird dann alles verhauen?

Wenn ein Variablentyp geändert wurde, dann gibt es immer eine InvalidClassException.

Ist nur eine neue Methoden/Variable dazugekommen, oder eine alte gelöscht worden, dann funktioniert es weiterhin. Allerdings nur, wenn man noch die selbe UID nutzt.

Da die von Eclipse generierte UID sich bei allen Änderung mit ändert, muss man die UID von Hand setzen. UID weglassen geht auch nicht, denn die dann automatisch generierte UID ändert sich ebenfalls, siehe Post unten von Banthor.
 
Zuletzt bearbeitet: (Link an die richtige Stelle gepackt & Blödsinn korrigiert.)
Die "serialVersionUID" wird beim Kompilieren durch den Java-Compiler erzeugt, sofern du keine eigene vorgegeben hast.

Wenn du nun zwingend alte Daten mit einer neuen Klassendefinition lesen musst, dann bleibt dir nichts anderes übrig als in Deiner neuen Klassendefinition die aktuelle ID des alten Compilats zu verwenden. Im JDK gibt es im bin Order ein Tool, welches dir für eine kompilierte Klasse die ID anzeigt, diese also in der neuen Klassendefinition eintragen.

Wichtig:
Die neuen Felder sollten am besten mit einen gültigen Defaultwert vorinitialisiert sein, ansonsten kann es Probleme geben, da diese Felder ja durch die alten Daten keinen Wert haben.
 
Also nochmal auf klar deutsch, sobald ich eine einheitliche ID nutze, kann ich in der Klasse beliebig viele Variablen hinzufügen.

Danke für die Antworten ^^
 
Zuletzt bearbeitet:
Zurück
Oben