Problem mit DataOutputStream

Status
Nicht offen für weitere Antworten.

Ishildur

Bekanntes Mitglied
Hallo zusammen
Ich habe folgendes Problem mit dem DataOutputStream:

Während die DataInputStream Klasse über Methoden wie skip, mark und reset verfügt, habe ich keinerlei Äquivalente in der DataOutputStream Klasse gefunden! 🙁

Ich muss eine Datei speichern und muss hierfür in der Datei herumspringen können, weil sich viele der Headerinformationen erst mit der Zeit eruieren lassen!

Was kann man da machen?

Lg Ishildur
 
na das ist ja auch schon bisschen was anderes, im InputStream müssen nur die Daten in ihrer Gesamtheit gecacht werden,
wenn man dort herumspringt und von woanders liest ist fast nix zu ändern außer einem Index,
da kann man x-mal vor und zurück springen, die gelesenen Daten, Positionen usw. sind immer konstant

dagegen in eine bestehene Folge von 1000 Bytes 10 einfügen?
da muss man ja erstmal 500 weiter nach rechts schieben, Platz schaffen,
wenn man einmal etwas eingefügt hat ändert sich die Position aller folgenden Daten, weitere Markierungen/ Resets haben auf einmal eine andere Wirkung,
sowas ist eben anscheinend nicht vorgesehen

Tipp: verwende eine Liste, ein der du alle TeilStrings, Integer-Objekte und was du noch so hast einfügst,
die Liste stört sich nicht an Änderungen, von mark/ rest ist dort aber natürlich auch nicht die Rede,
musst dir schon selber merken, wo der Header hinkommt,

am Ende schreibst du alles aus der Liste in den Stream,
ach, könnte etwas nervig werden, da die richtigen Operationen zu finden
(wenn Integer, dann verwende writeInt() usw)

hast du denn überhaupt unterschiedliche Daten oder vielleicht gar nur Strings?
ein StringBuilder erlaubt auch append und beliebiges Insert,
vielleicht im Programm so nur einen großen Text zusammenbauen und den am Ende schreiben?
 
Hallo Slater, ich fürchte du hast mich falsch verstanden
Ich hatte natürlich vor, den Platz für den Header auszusparen und schliesslich einfach ab und zu mit dem Filezeiger in den Header zurück springen, um dort einen nun verfügbare Information zu hinterlegen. Ich speichere ganz unterschiedliche Objekte, welche auch ganz unterschiedlich grössen haben bspw. Objekte mit unterschiedlich vielen Parametern usw.
Nun will ich im Header eine Tabelle hinterlegen, in welcher die Offsets der Position jener Objekte innerhalb der Datei gespeichert ist. Die grösse des Headers kenne ich, weil ich ja natürlich die Anzahl Objekte innerhalb meiner Listen kenne und ich für jeden Offset 4 Bytes reservieren muss. Das Problem ist nun, dass ich natürlich die Grösse der einzelnen Objekte nicht kenne, solange ich diese nicht in einer Schleife durchlaufe und analysiere. Natürlich kann ich alle Objekte zweimal durchlaufen, aber es wäre natürlich einfacher, wenn ich nach jedem gesicherten Objekt die aktuelle Position des Dateizeigers an der ensprechenden Stelle im Header (im dafür reservierten Platz) zu platzieren. Das Problem ist ja auch, dass ich nicht zuverlässig berechnen kann, wieviel Platz ein writeUTF effektiv in der Datei verwendet, da dies ja nur im günstigsten Fall mit Stringlänge+2 übereinstimmt!

Ich bin gerade echt ratlos, ich hoffe du kannst mich hierbei unterstützen 🙂
 
hmm, ich versthe dich nun noch weniger,

ein DataOutputStream ist meiner Meinung nach etwas, wo man Strings, ints und sonstwas in einer bestimmten Reihenfolge reinschreibt,
und da es ist nunmal nicht möglich, nach dem Schreiben noch etwas an vorheriger Position zu schreiben

die Sache meinst du anscheinend nicht, ist aber die einzige, die ich mir vorstellen kann,
ansonsten kann man doch praktisch gar nicht mehr mit diesem Stream machen, auch theoretisch nicht wünschen 😉

was das auf einmal mit Objekten, Offsets, Platz reservieren, doppelten Schleifendurchlauf, aktuelle Position und sonstwas zu tun hat,
verstehe ich persönlich nicht
 
@Slater
ein DataOutputStream ist meiner Meinung nach etwas, wo man Strings, ints und sonstwas in einer bestimmten Reihenfolge reinschreibt,

Richtig, das ist genau das, was ich mache! Allerdings möchte ich am anfang der Datei ein Array mit den Offsets sämtlicher gespeicherter Objekte speichern, damit ich diese später sehr effizient laden kann.

Stell dir mal vor, ich habe 30 Levels mit seeeehhhr unterschiedlichen Grössen. Wenn ich nun den 25sten Level laden möchte, dann müsste ich vorher sämtliche 24 vorherigen Levels auch laden, damit ich schliesslich nach tausenden von readInts und readBytes und readUTFs usw. endlich an der Position vom 25. Level gelange.

OOOOOODDERRRR

Ich speichere im Header ein array von 25 Integers, in welchem die Offsets (Position) der einzelnen Levels innerhalb der Datei gespeichert ist, damit ich beim Ladevorgang direkt zum gewünschten Level springen kann.

Das Problem ist nun, dass ich bei 30 Levels zwar weiss, wieviel Platz ich am Anfang der Datei reservieren muss (nämlich 30*4Bytes). Ich speichere den ersten Level also nicht bei Position null sondern bei Position 30*4. Allerdings kann ich ja erst mit Sicherheit sagen, wieviel Platz denn nun ein Level in der Datei benötigt, nachdem ich ihn gespeichert habe, weil bspw. die Methode writeUTF() abhängig von den effektiven Zeichen unterschiedlich viel Speicherplatz benötigt.

Also ich schreibe das mal als Pseudocode

Array level // array of levels
offset // current offset inside the file (filepointer)

skip(30*4) // leave space for the header

// start a loop for walking each level
for i <- 0 to level.length do
write level // write the current level
offset <- tell // save the current position of the filepointer
mark // sadly only works in DataInputStream
seek(i*4) // move the filepointer to the appropriate position inside the header
write offset // write the current offset
reset // return to write the next level
end for
 
jetzt bist du wieder am Anfang:
du schreibst erst etwas in den Stream und später willst du was an den Anfang schreiben,
dass du das nur machst, weil du den Offset nicht kennst und dass du schon Platz reserviert hast sind dabei zwei wenig relevante Details

ich persönlich sehe da auf die Schnelle keine gute Lösung,
um die Datei im Nachhinein zu bearbeiten gibts noch RandomAccessFile,
aber da müsstest du schon genau wissen wohin du nun den Index schreiben musst,
quasi den Index von der Stelle für den Index kennen 😉
evtl. denkbar aber nicht gerade super

oder eine zweite Datei für die Indexe, klingt erstmal sauberer aber da ist ja überhaupt die Sache mit den Indexen, die so nicht sehr schön ist

schon mal von einer DB gehört? 😉
 
@Slater
schon mal von einer DB gehört?
Also wieviele Spiele speichern die Leveldateien in einer Datenbank? :wink:

Und wenn du das mit den Indexen nicht sauber findest, dann sind wohl sämtliche Dateisysteme "nicht sauber"... :lol:
 
Hmm ich habe festgestellt, dass die RandomAccessFile Klasse genau das kann, was ich brauche und zusätzlich sämtliche Funktionen von DataOutputStream besitzt. Da frage ich mich doch, wieso sollte man überhaupt DataOutputStream verwenden resp. was sind die Unterschiede sowie Vor- bzw. Nachteile der beiden Klassen?

Lg Ishildur
 
File klingt nach File, Stream nach Stream, der ist allgmeiner

wenn ein Stream etwas was ins Internet versendet, dann wirds nunmal nix mit nachträglicher Änderung
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben