Ergebnis 1 bis 11 von 11

Thema: Vector<class> laden und speichern per Java

  1. #1

    Vector<class> laden und speichern per Java

    Hej,

    Ich beschäftige mich gerade damit Java-Objekte zu sichern.

    Für die Speichermethode habe ich folgenden Code genommen:
    Code:
       FileOutputStream fos = new FileOutputStream("t.tmp");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(bands);
        oos.close();
    bands ist ein Vector<String> Objekt.

    Zum Laden benutze ich:
    Code:
         FileInputStream fis = new FileInputStream("t.tmp");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Vector bands  = (Vector) ois.readObject();
    Nun ist bands aber erstmal einfach nur ein Vector und den einfach als Vector<String> zu deklarieren resultiert nicht in einem Fehler aber einer Warnung.
    Code:
    warning: [unchecked] unchecked conversion
    found   : java.util.Vector
    required: java.util.Vector<java.lang.String>
    Für die quick and dirty solution ist das alles ok aber wie kann man das ganze eleganter machen.

    Meine erste Idee war die bands.getClass mit der Klasse eines frischen Vecor<String> zu vergleichen und wenn alles gut geht einen neuen Vector aufzubauen. Das ganze führt aber die Idee das speicherns ab adsurdum, da ich ja gerade die Iteration über die Elemente des Vektors umgehen möchte.


    Und eine Randfrage: Wenn ich später mehrere Vektoren in einer Datei speichern möchte, ist es möglich die auch so wieder auszulesen? Mir ist noch unklar wie die Identifizierung stattfindet wenn ich zum Beispiel die Vectoren bands, volunts and meinetwegen camps habe.

  2. #2
    Man kommt da nicht drumherum, die Annotation @SuppressWarnings("unchecked") zu verwenden, um den Cast ohne Warnhinweis durchzuführen.
    Allerdings sollte man sich schon vergewissern, dass im Vektor korrekte Daten stehen, bevor man den Cast ausführt. Ansonsten kann es zu einem Absturz kommen.
    Meine Lösung würde folgendermaßen aussehen:
    Code (Java):
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.StreamCorruptedException;
    import java.util.Vector;
     
     
    public class Test {
     
        private static 
        void saveData(Vector<?> data, String filename) throws IOException
                                                            , FileNotFoundException
        {
            FileOutputStream   fos = new FileOutputStream(filename);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
     
            oos.writeObject(data);
            oos.close();
        }
     
     
        private static 
        Vector<?> readData(String filename) throws IOException
                                                 , FileNotFoundException
                                                 , ClassNotFoundException
                                                 , StreamCorruptedException
        {
            FileInputStream   fis = new FileInputStream("t.tmp");
            ObjectInputStream ois = new ObjectInputStream(fis);    
     
            return (Vector<?>) ois.readObject();
        }
     
     
        private static 
        boolean hasStrings(Vector<?> vector)
        {
            return vector.get(0).getClass().toString().equals(new String().getClass().toString());
        }
     
     
        @SuppressWarnings("unchecked")
        private static 
        Vector<String> convertData(Vector<?> v1)
        {
            return (Vector<String>)v1.clone();
        }
     
     
        public static 
        void main(String[] args)
        {
            Vector<String> bands   = new Vector<String>();
            Vector<String> bands2  = new Vector<String>();
            Vector<?>     temp     = null;
            String        filename = "t.tmp";
     
            bands.add("1");
            bands.add("2");
     
            // Daten werden in die Datei gespeichert
            try 
            {
                saveData(bands, filename);
            } 
            catch (Exception e) 
            {
                System.out.println("Fehler beim Schreiben der Datei: " + e.getLocalizedMessage());
            }
     
            // Daten werden aus der Datei gelesen
            try 
            {
                temp = readData(filename);    
            } 
            catch (Exception e) 
            {
                System.out.println("Fehler beim Lesen der Datei: " + e.getLocalizedMessage());
            }    
     
            // Daten werden auf Richtigkeit geprüft
            if ((temp != null) && !temp.isEmpty() && hasStrings(temp))
            {
                // Daten werden in bands2 gespeichert
                bands2 = convertData(temp);    
            }
            else 
            {
                System.out.println("Es konnten keine Datensätze gelesen werden.");
            }
     
            System.out.println("Daten in bands2: " + bands2.toString());
        }
    }
     


    Das Fragezeichen, bei Vector<?> temp = null; ist ein Wildcard und bedeutet, dass dies ein Vector, mit einem unbekannten Typ als Element, ist.

    Geändert von Whiz-zarD (29.05.2011 um 22:39 Uhr)

  3. #3
    n1<3! Annotations höre ich nun das erste mal und die Casts.. naja, wenn man es nicht täglich braucht vergisst man es halt :)

    Danke für das sehr ausführliche Beispiel (wäre so gar nicht nötig gewesen, aber immer schön zu sehen wie es funktioniert).

    Ist die Wildcard <?> für den Vector wirklich nötig? Bei mir kompiliert es auch ohne diese Angabe - oder ist das Platform/Versionsabhängig?

    Und gibt es einen Grund die Klassen auf String-Ebene zu vergleichen? Im folgenden Beispiel habe ich die equal-Methode der Class-Klasse genutzt. (und wenn der fragliche Vector als Paramter übergeben wird, spart man sich doch auch die if != null Abfrage),

    Die Randfrage wie man mehrere Objekte in eine Datei speichert hat sich von selbst erledigt. Hier ein kleines (hard code) Beispiel für 2 Objekte.
    Code:
    import java.io.*;
    import java.util.Vector;
    
    public class Main{
    
      public static void save(Vector data, Vector data2, String filename){
        try{
          ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename));
          oos.writeObject(data);
          oos.writeObject(data2);
          oos.close();
        }catch(Exception e){System.out.println("Fehler beim Speichern der Datei "+filename);}
      }
    
      public static Vector[] load(String filename){
        try{
          ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
          Vector[] result = new Vector[2];
          result[0] = (Vector) ois.readObject();
          result[1] = (Vector) ois.readObject();
          return result;
        }catch(Exception e){
          System.out.println("Fehler beim Lesen der Datei "+filename);
          return null;
          }
      }
    
      public static boolean hasStrings(Vector data){
        return new Vector<String>().getClass().equals(data.getClass());
      }
    
      @SuppressWarnings("unchecked") public static Vector<String> convertData(Vector data){
        return (Vector<String>) data.clone();
      }
    
      public static void main(String[] args){
        String filename = "tmp";
        Vector<String> data1 = new Vector<String>();
        Vector<String> data2 = new Vector<String>();
        data1.add("foo");
        data2.add("bar");
        System.out.println(data1.get(0)+" "+data2.get(0));
        save(data1, data2, filename);
    
        Vector<String> ndata1 = new Vector<String>();
        Vector<String> ndata2 = new Vector<String>();
        Vector[] tmp = load(filename);
        
        if(hasStrings(tmp[0])) ndata1 = convertData(tmp[0]);
        if(hasStrings(tmp[1])) ndata2 = convertData(tmp[1]);
    
        System.out.println(ndata1.get(0)+" "+ndata2.get(0));
      }
    }

    Geändert von YoshiGreen (30.05.2011 um 17:14 Uhr)

  4. #4
    Zitat Zitat von YoshiGreen Beitrag anzeigen
    Ist die Wildcard <?> für den Vector wirklich nötig? Bei mir kompiliert es auch ohne diese Angabe - oder ist das Platform/Versionsabhängig?
    Theoretisch sollte es egal sein, da Vector ein Raw-Type ist und <?> einen unbekannten Typ definiert. Da alle Datentypen von der Klasse Object erben, sollten beide Möglichkeiten gleich sein. Allerdings spuckt z.B. die IDE Eclipse einen Warnhinweis, wenn man mit einem Raw-Type arbeiten möchte.


    Zitat Zitat von YoshiGreen Beitrag anzeigen
    Und gibt es einen Grund die Klassen auf String-Ebene zu vergleichen? Im folgenden Beispiel habe ich die equal-Methode der Class-Klasse genutzt. (und wenn der fragliche Vector als Paramter übergeben wird, spart man sich doch auch die if != null Abfrage),
    Man muss hier zweierlei Dinge betrachten. Einmal der Typ Vector und einmal der Typ, der im Vektor gespeichert wird.
    Du kannst ja gerne mal einen Test machen:
    Code:
    public static boolean hasStrings(Vector data){
        System.out.println((new Vector<String>().getClass()));
        System.out.println(data.getClass());
        return new Vector<String>().getClass().equals(data.getClass());
      }
    Du wirst feststellen, dass beide vom Typ Vector sind. Es spielt da keine Rolle, welcher generische Datentyp angegeben wurde. In der Klasse Vector befindet sich ja eine Liste, die den angegebenen generischen Typ speichert. Man muss dann also schauen, welchen Typ die Elemente in dieser Liste besitzen.

  5. #5
    OK, das hatte ich übersehen und nun auch eingesehen. Meine Frage richtete sich aber auf die toString()-Methode da equal() ja auch für Klassen definiert ist.
    Code:
    return vector.get(0).getClass().toString().equals(new String().getClass().toString());
    Kannst du mir dazu noch sagen wonach ich googlen soll wenn ich folgenden Code zum laufen bringen will:
    Code:
    Class cl = new String().getClass();
    Vector<cl> vec = new Vector<cl>();
    Can't find symbol ist mein Fehler aber es wäre praktisch eine Methode zum Überprüfen zu haben anstelle sie zu überlagern.

  6. #6
    Zitat Zitat von YoshiGreen Beitrag anzeigen
    OK, das hatte ich übersehen und nun auch eingesehen. Meine Frage richtete sich aber auf die toString()-Methode da equal() ja auch für Klassen definiert ist.
    Stimmt. Da hatte ich einen Gedankenfehler.

    Zitat Zitat von YoshiGreen Beitrag anzeigen
    Kannst du mir dazu noch sagen wonach ich googlen soll wenn ich folgenden Code zum laufen bringen will:
    Code:
    Class cl = new String().getClass();
    Vector<cl> vec = new Vector<cl>();
    Can't find symbol ist mein Fehler aber es wäre praktisch eine Methode zum Überprüfen zu haben anstelle sie zu überlagern.
    cl ist kein Datentyp, sondern eine Variable vom Typ Class.
    Das, was du da vorhast könnte man bei Sprachen mit schwacher Typisierung machen, die alles als Zahlen oder Zeichenketten (z.B. TorqueScript in der Torque Game Engine) behandeln, aber nicht bei einer Sprache mit starker Typisierung.
    Aber warum hast du sowas vor? Du willst doch letzendlich nur Strings in den Vektor speichern.

  7. #7
    Zitat Zitat von YoshiGreen Beitrag anzeigen
    Code:
    Class cl = new String().getClass();
    Vector<cl> vec = new Vector<cl>();
    Can't find symbol ist mein Fehler aber es wäre praktisch eine Methode zum Überprüfen zu haben anstelle sie zu überlagern.
    Also du willst auf einen variablen generischen Typ casten?
    Das macht inhärent keinen Sinn, da die Type Constraint bei generischen Klassen bloß statisch überprüft wird, bei der Programmausführung ist darüber keinerlei Information mehr vorhanden. Dynamisch einen generischen Parameter zu bestimmen ergibt daher keinen Sinn, da der im dynamischen Kontext eben nicht mehr vorhanden ist und auch nicht mehr verwendet/überprüft wird.

    Wenn der Typ erst zur Laufzeit feststeht, kannst du einfach Vector (oder Vector<Object>) verwenden, genau das wird da zur Laufzeit nämlich in jedem Fall stehen.

  8. #8
    Naja, meine Idee war einfach nur Konstruktionen wie diese hier zu vermeiden:

    Code:
      private static boolean sameClass(Vector data, Vector v){
        return new Vector().getClass().equals(data.get(0).getClass());
      }
    
      private static boolean sameClass(Vector data, String s){
        return new String().getClass().equals(data.get(0).getClass());
      }
    Und stattdessen halt sowas wie
    Code:
    public static boolean sameClass(Vector data, Class cl){
      return data.get(0).getClass().equals(cl);
    }
    oder etwas ähnliches. Die obere Lösung halte ich für so unelegant. Aber vielleicht habe ich ja auch einen total falschen Ansatz. Habe halt noch nie vorher Objekte gespeichert.

  9. #9
    Zitat Zitat von YoshiGreen Beitrag anzeigen
    Code:
    public static boolean sameClass(Vector data, Class cl){
      return data.get(0).getClass().equals(cl);
    }
    Hm, das sollte doch eigentlich eh gehen, oder? o_O Bräuchte evtl. höchstens noch etwas Code um Unterklassen zu berücksichtigen. Und du könntest ein Objekt statt der Klasse als zweiten Parameter übergeben, je nachdem, was praktischer ist.
    Oh, und du solltest auf jeden Fall sichergehen, dass data nicht leer ist, sonst gibt's unschöne Runtime Exceptions …

    Ahja, in jedem Fall kannst du im Falle von Class auch == statt equals() verwenden, da Class-Objekte Singletons sind. Aber geht natürlich so genauso.

  10. #10
    Code:
    private static boolean sameObject(Vector<?> v, Object obj) 
    {
        return !v.isEmpty()
               ? v.get(0).getClass().equals(obj.getClass())
               : false;
    }

  11. #11
    Ich kam noch net zum testen. Beim Übergeben von ner Class hatte ich irgendwelche Probleme (ich versuchs bezeiten nochmal zu rekonstruieren, Whiz Code teste ich dann auch).

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •