ObjectOutputStream Anzahl Objekte festhalten

ocsme

Top Contributor
Guten Tag,

Hier meine "Problem"!

Ich versuche Objekte auf die Platte zu schreiben. Natürlich verstehe ich das es so z. B. gemacht werden könnte 😀
Java:
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("rationals.ser"));
oos.writeObject(new Rational(2, 3));
oos.writeObject(new Rational(1, 4));
oos.writeObject(new Rational(7, 2));
oos.close();

Das ist nicht das Problem da hilft uns Java ja sehr viel weiter 🙂
Sondern ich würde gerne eine count Variable haben die mir vorher anzeigt viele Objekte in der Datei liegen. Denn das bräuchte ich ja als abbruchbedingung für die Schleife. z. B.

Muss ich dann 2 Schleifen machen um vorher fest zu halten wie groß der count ist? Diesen Count schreibe ich an den Anfang der Datei als Abbruchbedingung.
Oder was ich noch besser finden würde wäre so etwas in die Meta-Datei zu schreiben. Da ich das noch nie gemacht habe bräuchte ich hier bei echt Hilfe.

Ich hoffe man verstehe mein anliegen besser bekomme ich gerade nicht wirklich formuliert 🙁
Wenn nicht muss ich erst ein kleines Programm schreiben und ich zeige euch genau was ich meine 😛

"Frohe Ostern noch!"

Liebe Grüße 🙂
 
Warum packst du die Objekte nicht in eine Liste und serialisierst diese? Die Objekte werden im Programm doch sicherlich auch in einer Liste gehalten?
 
Hätte ich dann nicht das gleiche Problem und wüsste nicht wann das ende erreicht ist?
Nein derzeit habe ich nichts in einer Liste das sind auch nur so kleine Aufgaben z. B.: eine mini Matrix Programm schreiben:

Matrix(int n, int m): constructor that creates a matrix of size n x m, with all values initially set to 0;
void save(String filename): that saves the content of the matrix on the file specified by filename;
static Matrix read(String filename): that reads the data about a matrix from the file specified by filename, creates the matrix, and returns it;
Matrix sum(Matrix m): that returns the matrix that is the sum of the object and of m, if the two matrices have the same dimensions, and null otherwise;
Matrix product(Matrix m) : that returns the matrix that is the product of the object and of m, if the two matrices have compatible dimensions, and null otherwise

So gesehen kann man das ganze ja einfach Lösen mit:
Java:
    void save(String filename) throws  IOException{
        try {
            ObjectOutputStream oin = new ObjectOutputStream(new FileOutputStream(filename));
            oin.writeObject(this);
            oin.close();
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
    static Matrix read(String filename) {
        try {
            ObjectInputStream oin = new ObjectInputStream(new FileInputStream(filename));
            Object c =(oin.readObject());
            if(c.getClass()==Matrix.class){
                oin.close();
                return((Matrix)c);
            }
            oin.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

Ja das ganze ist nicht wirklich elegant und ohne try-with-resources Statement.
Ich würde aber gerne mehrere Objekte dieses Typs speichern und später wieder einlesen und dann sollen später auch gleich mehrere Objekte von einem anderen Typ gespeichert werden, doch das würde ja an der Anzahl der Objekte nichts ändern bis wohin man laufen müsste.

Wie du das genau mit der Liste meinst weiß ich nicht. Das Java-Framwork besprechen wir derzeit auch also die Array-List dürften wir nutzen aber wie soll man denn dann sowas machen? Das verstehe ich gerade nicht sry.

LG
 
Okay 🙂
erstmal Danke für die Antworten, ich versuch es mal so hin zu bekommen wie ich es mir vorstelle. Wenn es nicht Klappt Poste ich den code denke das bringt uns jetzt schneller weiter 🙂
LG
 
Also so wie ich das hier gemacht habe speichere ich 1 Objekt in 1 Datei:
Java:
void save(String filename) throws IOException {
         try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
             oos.writeObject(this);
         }
    }

    static Matrix read(String filename) throws IOException, ClassNotFoundException {
        try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))){
            Object c =(ois.readObject());
            if(c.getClass()==Matrix.class)
                return((Matrix)c);
           
            return null;
        }
    }


Sobald ich mehrere Objekte Speichern will (auf Platte schreibe), benötige ich ja eine Liste von diesen Objekten und jetzt habe ich das verstanden was Ihr gemeint habt. Doch leider habe ich immer noch die Frage die im Code steht.
Java:
void save(Matrix[] matrix, String filename) throws IOException{
            try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename))) {
              for (Matrix i : matrix)
                out.writeObject(i);
            }
    }
   
    static Matrix[] read(String filename) throws IOException, ClassNotFoundException {
        /*
         * Bei der Referenzvariable tmp möchte ich nun die größe eintragen.
         * Diese größe ist die Länge des Arrays von save. Muss diese Länge nicht zuerst in
         * die Datei geschrieben werden? Dann liest man die ersten Bit aus der Datei heraus
         * und interpretiert dies als int wert. Da es ja vorher ein int wert war.
         */
        Matrix[] tmp = new Matrix[???];
         try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) {
              for (int i = 0; i < tmp.length; i++)
                tmp[i] = (Matrix) in.readObject();
              return tmp;
         }
    }


Ich entschuldige mich auch wieder für die "doofe" Frage.

LG

und mal wieder noch eine "doofe" Frage zum Thema Exception. Müsste ich die Exception bei den Methoden catchen? NEIN oder? sollte ich an die nächst höher Instanz weiter geben und diese kümmert sich dann um die Fehlerbehandlung. Denn wenn ich es in der Methode catche läuft die Methode anschließend weiter und gibt z. B. noch etwas zurück oder sonst was 😀
 
Du kannst ein Array auch direkt serialiiseren. Die Idee ist also, dass Du keine Schleife hast, in der Du jedes Element einzeln in die Datei schreibst sondern Du schreibst gleich das ganze Array.
Und genau so kannst Du es dann auch wieder einlesen. Du erzeugst also kein Array sondern bekommst dies vom ObjectInputStream zurück.
 
Könnte mir jemand Zeigen wie so etwas aussieht wenn man es als Array oder Liste Serialisiert?
Ich komme hier echt nicht mehr weiter 🙁 denn nun bräuchte ich noch die ersten 8 Byte zu markieren das er dort nicht beginnt zu lesen. Denn ich erhalte folgenden Fehlercode:
Exception in thread "main" java.io.StreamCorruptedException: invalid stream header: 03000000
at java.i😵bjectInputStream.readStreamHeader(ObjectInputStream.java:866)
at java.i😵bjectInputStream.<init>(ObjectInputStream.java:358)
at Matrix.read(Matrix.java:32)
at Matrix.main(Matrix.java:145)

Derzeit habe ich es so gemacht:
Java:
public static void save(Matrix[] matrix, String filename) throws IOException{
            try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename));
                OutputStream os = new FileOutputStream(filename)) {
                int tmp = matrix.length;
                os.write(tmp);
               
              for (Matrix i : matrix)
                out.writeObject(i);
            }
    }
   
    static Matrix[] read(String filename) throws IOException, ClassNotFoundException {
         try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
              InputStream is = new FileInputStream(filename)) {
             Matrix[] tmp = new Matrix[is.read()];
              for (int i = 0; i < tmp.length; i++)
                tmp[i] = (Matrix) in.readObject();
              return tmp;
         }
    }



LG
 
Nicht aufgeben! Du kannst doch erst einmal Deinen Code, den Du geschrieben hast, zum laufen bringen!

Du nutzt derzeit mehrere verschiedene Streams für eine Datei. Das ist etwas, das ich so nicht kenne bisher und wodrin ich auch keinen Sinn sehe.

Wieso schreibst Du deinen Integer nicht auch über den ObjectOutputStream? writeInt ist ja dazu da. Und dann beim lesen kommt ein readInt zum Einsatz.

Und schon läuft Dein Code ohne Probleme.
 
Ja sry!
Ich drück mich echt manchmal auch super doof hier aus!
Sollte das mal öfters wieder lesen was ich schreibe 😀

Werde es später weiter versuchen bzw. evtl wird daraus erst morgen 🙁 Viel zu viel derzeit um die Ohren denke das kann man sicher verstehen 🙂

Ich gelobe Besserung 🙂
 
Okay es klappt aber ich verstehe es nicht!
Bin ich etwas bei C Programmierung 😀 so hatte ich es heute Mittag auch schon und da kam auch schon diese StreamCorruptedError 🙁

Java:
    public static void save(Matrix[] matrix, String filename) throws IOException{
        try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename))) {
            out.writeInt(matrix.length);
              for (Matrix i : matrix)
                out.writeObject(i);
        }
    }

    static Matrix[] read(String filename) throws IOException, ClassNotFoundException {
        try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename))) {
            Matrix[] tmp = new Matrix[in.readInt()];

            for (int i = 0; i < tmp.length; i++)
                tmp[i] = (Matrix) in.readObject();
            return tmp;
        }
    }


Eine Doofe Frage hätte ich aber noch. Oben hatte ich ja später 2 verschiedene Streams offen. Bekommt man es hin das wenn ich bei einem Stream anfange Bytes zu lesen das der andere Stream dann dort weiter macht wo der erste aufgehört hat?

Achso und was mir noch aufgefallen ist, wieso steht im HexEditor jetzt dort aber keine 3 drin wenn das Array die Länge drei hat? Sollten die ersten 4 Byte nicht mit 00 00 00 03 belegt sein? Die ersten 4 Byte sehen bei mir anders aus 🙁


LG
 
Bekommt man es hin das wenn ich bei einem Stream anfange Bytes zu lesen das der andere Stream dann dort weiter macht wo der erste aufgehört hat?
Im Allgemeinen nicht. Oder andersrum gesagt: das hängt von den Streams ab. Wenn Du beispielsweise einen BufferedInputStream nimmst, dann füllt dieser seinen Puffer mit den Daten aus dem darunterliegenden Stream. Folglich laufen die Streams nicht synchron.

Sollten die ersten 4 Byte nicht mit 00 00 00 03 belegt sein? Die ersten 4 Byte sehen bei mir anders aus 🙁
Die ersten vier Bytes sind der Stream Header, bestehend aus der Magic Number und der Versionsnummer (jeweils 2 Bytes). Primitive Datentypen werden als Blockdaten rausgeschrieben. Der Block hat ebenfalls einen Header, bestehend aus einem Block-Tag und der Länge. Ist die Länge kleiner als 256, besteht der Blockheader aus zwei Byte, ansonsten aus fünf. Erst dann folgen die Zahlen.

Code:
ac ed 00 05 77 08 7f ff  ff ff 00 00 00 01
<> <> <> <> <> <> <----------> <--------->
MM MM VV VV TT LL     Int1        Int2

M = Magic, V = Version, T = Tag, L = Length
 

Zurück
Oben