# Objekte aus Datei auslesen und in ArrayList schreiben!



## Bonz (5. Jun 2006)

Hallo!

Hab ein kleines Problem mit ArrayList.
Arbeite an einem Programm in dem auch ein "Adressbuch" eingebettet wird.
Nun hat eigentlich alles schon sehr gut funktioniert. Die Objekte konnte ich schon in eine Datei schreiben bzw. auch jederzeit wieder auslesen. Jedoch war meine erste Lösung sehr unsauber, da ich immer zuerst ein Adressbuch-Array mit 1000 Objekten erstellte. Effektiver wäre es aber, wenn sich die Größe dynamisch ändern würde.

Ich hoffe, dass ich euch anhand eines Code-Ausschnitts das Problem verdeutlichen kann. Als Beispiel habe ich den Code-Bereich gewählt, bei dem man einen Eintrag löschen kann.

Hier noch die alte Version:


```
if (e.getActionCommand().equalsIgnoreCase("del")) {

            if (address.getSelectedItem().equals("broadcast")) {
                JOptionPane.showMessageDialog(null,"broadcast kann nicht gelöscht werden!");
            }
            else {
                int ret;
                ret = JOptionPane.showConfirmDialog(null, address.getSelectedItem() + " wirklich löschen?","Nachricht",JOptionPane.OK_CANCEL_OPTION);
                System.out.println(ret);
                if (ret == 0) {
                    Addressbook buch = new Addressbook(1000);
                    int i, size;
                    ObjectLoader ol = new ObjectLoader();
                    buch.setUser(ol.load());
                    address.getSelectedItem();
                    size = buch.getSize();
                    for (i = 0; i < size; i++) {
                        if (address.getSelectedItem().equals(buch.getUser(i).
                                getName())) {
                            buch.remove(i);
                            i = size;
                        }
                    }
                    ObjectSaver os = new ObjectSaver(buch.getInhalt());
                    os.save();
                }
            }
            refreshComboBox();

        }
```

Und hier der Versuch es mit einer ArrayList zu lösen (es fehlt der "remove"-Teil):


```
if (e.getActionCommand().equalsIgnoreCase("del")) {

            if (address.getSelectedItem().equals("broadcast")) {
                JOptionPane.showMessageDialog(null,"broadcast kann nicht gelöscht werden!");
            }
            else {
                int ret;
                ret = JOptionPane.showConfirmDialog(null, address.getSelectedItem() + " wirklich löschen?","Nachricht",JOptionPane.OK_CANCEL_OPTION);
                System.out.println(ret);
                if (ret == 0) {
                    ArrayList list1 = new ArrayList();
                    
                     int i = 0, size;
                    ObjectLoader ol = new ObjectLoader();
                    
                  //  list1.add(ol.load());
            //        list1.toArray(ol.load());
                    list1.add(0, ol.load());
               //     list1.add(1, ol.load());
               //     list1.add(ol.load());
                    
                    size = list1.size();
                    System.out.println(size);
                    System.out.print(list1);
                    System.out.print(list1.toString());
                    System.out.print(list1.toArray());
                    System.out.print(list1.get(0));
                }
            }
            refreshComboBox();

        }
```

Die ganzen System.Out's dienen mir dazu zu sehen, was ich da eigentlich rausbekomme. Ich weiß natürlich auch, dass hier der eigentliche "Remove"-Teil fehlt, aber ich möchte es vorher mal schaffen, dass ich die Objekte richtig einlese. Dann sollte das löschen eh kein Problem mehr darstellen.
Wenn ich es so ausführe bekomme ich keine schöne Ausgabe sondern nur "[[LAddressbook.User;@1fcc0a2][[LAddressbook.User;@1fcc0a2][Ljava.lang.Object;@caf6c1[LAddressbook.User;@1fcc0a2" und so.

Hier noch der ObjectLoader:

```
public class ObjectLoader {

    private User[] userObject;
    private String file;

    public ObjectLoader() {
    }

    public User[] load()
    {
        file = "addressbook.txt";
        FileInputStream fis = null;
        ObjectInputStream is = null;
        try
        {
          fis = new FileInputStream(file);
          is = new ObjectInputStream(fis);
          userObject = (User[])is.readObject();
          is.close();
        }
        catch(Exception e)
        {
             JOptionPane.showMessageDialog(null,"Fehler beim Laden!");
        }

        return userObject;
     }
```

Und hier noch die User-Klasse:

```
public class User implements Serializable{

    private String name;
    private String ipadress;

    public User(String name) {
        this.name = name;
    }

    public void setIpadress (String ipadress) {
        this.ipadress = ipadress;
    }

    public String getIpadress() {
        return ipadress;
    }

    public String getName() {
          return name;
    }

    public String toString() {
        return (name + " " + ipadress);
    }

}
```

Vielleicht könnt ihr mir ja weiterhelfen. Hab auch schon in einem ähnlichen Thread was darüber gelesen, aber das konnte mir leider bei meinem Kernproblem auch nicht weiterhelfen.

Bonz


----------



## cowabunga1984 (6. Jun 2006)

Hi,

ich glaube deine Objekte werden schon richtig in die Arraylist geschrieben. Du liest sie nur falsch aus.
Was gibt denn _System.out.print(list1.get(0)); _ aus?

_[LAddressbook.User;@1fcc0a2]_ -> @1fcc0a2 könnte für eine Referenz auf dein Objekt stehen.

Ich bin auch noch nicht so der Java-Crack, aber da die seit gestern niemand geantwortet hat, hab ich gedacht ich versuchs einfach mal ^^

Gruß
cowabunga[/i]


----------



## Bonz (7. Jun 2006)

cowabunga1984 hat gesagt.:
			
		

> Hi,
> 
> ich glaube deine Objekte werden schon richtig in die Arraylist geschrieben. Du liest sie nur falsch aus.
> Was gibt denn _System.out.print(list1.get(0)); _ aus?
> ...



Erstmal Danke für deine Antwort!

Als Ausgabe bei _System.out.print(list1.get(0)); _ bekomme ich _[LAddressbook.User;@1fcc0a2_!

Ich verstehe das nicht!
Entweder schreibe ich es schon falsch rein und lese es dann "richtig" aus oder umgekehrt...

Bonz


----------



## cowabunga1984 (7. Jun 2006)

_list1.get(0)_ gibt dir das Objekt zurück, welches sich in deiner ArrayList an stelle 0 befindet. Hast du in deinem Objekt Methoden welche dir eines String zurückgeben?
z.B.

```
myObject objHolla = list1.get(0);
System.out.println(objHolla.getName());
```

oder so ähnlich...
Du kannst kein Objekt ausgeben, nur die Attribute vom Objekt oder halt Methoden welche einen String zurückgeben.

Ich hoffe mal du weist was ich meine


----------



## SamHotte (7. Jun 2006)

mit "list.get(0)" bekommst du ein Objekt; dessen "toString()"-Methode gibt immer einen komischen Zahlenwert zurück.

Wenn du aus der ArrayList Objekte vom Typ "User" haben möchtest, lautet der Befehl "(User)list.get(0)". Und wenn nun auch noch dein Typ "User" die "toString()"-Methode sinnvoll implementiert, dann kannst du auch mit der Ausgabe etwas anfangen.


----------



## André Uhres (7. Jun 2006)

Wenn ich richtig verstehe, dann willst du den Array "ol.load()" als Liste haben  :?: 

```
List list1 = Arrays.asList(ol.load());
```


----------



## Bonz (7. Jun 2006)

SamHotte hat gesagt.:
			
		

> mit "list.get(0)" bekommst du ein Objekt; dessen "toString()"-Methode gibt immer einen komischen Zahlenwert zurück.
> 
> Wenn du aus der ArrayList Objekte vom Typ "User" haben möchtest, lautet der Befehl "(User)list.get(0)". Und wenn nun auch noch dein Typ "User" die "toString()"-Methode sinnvoll implementiert, dann kannst du auch mit der Ausgabe etwas anfangen.



Obwohl ich ja eine "toString()"-Methode in der "User" implementiert habe (siehe ersten Beitrag) funktioniert das leider nicht und ich bekomme folgende Fehlermeldung:
_Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [LAddressbook.User;_

Bonz


----------



## Murray (7. Jun 2006)

ObjectLoader#load liefert ja ein Array von User-Objekten zurück, nicht etwa einen einzelnen User, der in seiner toString-Methode möglicherweise eine "schöne" Ausgabe implementiert.
Insofern liefert natürlich auch list.get(0) wieder ein ganzes Array, und die VM macht aus Arrays beim toString eben immer "L" + Name des Elementyps + ";" + "@" + HexWert.
Du kannst Dich jetzt entweder selbst darum kümmern, das Array elementweise auszugeben, oder Du verwendest java.util.Arrays#toString:

```
System.out.println( Arrays.toString( (Object[])(list.get( 0)) ));
```

@SamHotte: Selbst wenn die Liste User-Objekte enthalten würde, würde der cast von Object auf User nichts ändern; es wird immer die toString-Methode der terminalen Klassen aufgerufen, unabhängig davon, welchen Typ die Referenz hat, in der das Objekt gehalten wird.


----------



## Bonz (7. Jun 2006)

André Uhres hat gesagt.:
			
		

> Wenn ich richtig verstehe, dann willst du den Array "ol.load()" als Liste haben  :?:
> 
> ```
> List list1 = Arrays.asList(ol.load());
> ```



Also, ich hätte mir das so gedacht:

ol.load() gibt ein userObject vom Typ User[] zurück und dieses "User"-Array möchte ich in eine ArrayList schreiben.
Das müsste doch gehen, oder habe ich da einen Denkfehler bzw. verstehe ich da etwas Grundlegendes falsch?

Bonz


----------



## Bonz (7. Jun 2006)

Murray hat gesagt.:
			
		

> ObjectLoader#load liefert ja ein Array von User-Objekten zurück, nicht etwa einen einzelnen User, der in seiner toString-Methode möglicherweise eine "schöne" Ausgabe implementiert.
> Insofern liefert natürlich auch list.get(0) wieder ein ganzes Array, und die VM macht aus Arrays beim toString eben immer "L" + Name des Elementyps + ";" + "@" + HexWert.
> Du kannst Dich jetzt entweder selbst darum kümmern, das Array elementweise auszugeben, oder Du verwendest java.util.Arrays#toString:
> 
> ...



Ok, danke mal für den TIPP!
Du hast natürlich recht. Das muss ich gleich mal testen!

Bonz


----------



## Murray (7. Jun 2006)

Bonz hat gesagt.:
			
		

> ol.load() gibt ein userObject vom Typ User[] zurück und dieses "User"-Array möchte ich in eine ArrayList schreiben.
> Das müsste doch gehen, oder habe ich da einen Denkfehler bzw. verstehe ich da etwas Grundlegendes falsch?


Das geht schon, Du musst eben nur berücksichtigen, dass die toString-Methode des Elementtyps nicht automatisch verwendet wird, wenn Du das Array mit toString in einen String umwandelst; dafür braucht man Arrays#toString.


----------



## André Uhres (7. Jun 2006)

Bonz hat gesagt.:
			
		

> ol.load() gibt ein userObject vom Typ User[] zurück und dieses "User"-Array möchte ich in eine ArrayList schreiben.




```
ArrayList list1 = new ArrayList(Arrays.asList(ol.load()));
```


----------



## Bonz (7. Jun 2006)

Murray hat gesagt.:
			
		

> Bonz hat gesagt.:
> 
> 
> 
> ...



Ok, also mit _System.out.println( Arrays.toString( (Object[])(list1.get( 0)) ));_ bekomme ich jetzt zwar schon "lesbaren Text" raus, aber jetzt gibt es mir ja auf einen Schlag alle User (+ IP-Adressen) aus.
Kann ich jetzt irgendwie auf zB. den Namen des zweiten Users zugreifen bzw. ihn ausgeben lassen?
In der User-Klasse hätte ich ja die zwei Methoden "getIpAddress" und "getName" angelegt. Nur weiss ich nicht, wie umständlich ich jetzt auf diese zugreifen muss.

Bonz


----------



## André Uhres (7. Jun 2006)

Bonz hat gesagt.:
			
		

> ..Kann ich jetzt irgendwie auf zB. den Namen des zweiten Users zugreifen bzw. ihn ausgeben lassen?..




```
ArrayList list1 = new ArrayList(Arrays.asList(ol.load()));
System.out.println(list1.get(1).getName());
```


----------



## Bonz (7. Jun 2006)

André Uhres hat gesagt.:
			
		

> Bonz hat gesagt.:
> 
> 
> 
> ...



Ok, danke, das hilft mir jetzt auch weiter. Denn jetzt bekomme ich mit _System.out.println(list1.get(0));_ wirklich die toString()-Methode des ersten Objekts geliefert. Nur hier wird mir leider auch wieder beides (Name und IP-Adresse) geliefert, da ich das auch so in der toString()-Methode geschrieben habe. Aber ich muss doch auch noch irgendwie zB. auf getName zugreifen können, oder nicht?

Bonz


----------



## Bonz (7. Jun 2006)

André Uhres hat gesagt.:
			
		

> Bonz hat gesagt.:
> 
> 
> 
> ...



Ja, das hätte ich auch schon versucht, aber leider funktioniert das nicht.  

Bonz


----------



## André Uhres (7. Jun 2006)

Bonz hat gesagt.:
			
		

> ..ich muss doch auch noch irgendwie zB. auf getName zugreifen können..




```
System.out.println((User)list1.get(1)).getName());
```


----------



## Bonz (7. Jun 2006)

André Uhres hat gesagt.:
			
		

> Bonz hat gesagt.:
> 
> 
> 
> ...



JA!
Danke, so funktioniert's!
Vielen Dank!

Bonz


----------



## André Uhres (7. Jun 2006)

Bonz hat gesagt.:
			
		

> Danke, so funktioniert's!


Es geht aber noch besser. Das Casten lässt sich nämlich auch vermeiden:

```
ArrayList<User> list1 = new ArrayList<User>(Arrays.asList(ol.load())); 
        System.out.println(list1.get(1).getName());
```


----------



## Bonz (14. Jun 2006)

Da ich jetzt ein weiteres Problem habe, dass mit meinem vorherigen zusammenhängt, wußte ich nicht so recht, ob ich nun einen neuen Thread anfangen hätte sollen oder nicht, da ja das erste Problem eigentlich gelöst wurde.
Sorry, falls ich da jetzt etwas falsch mache.

Nun zum Problem:
Also, das Laden funktioniert ja jetzt einwandfrei, aber nun habe ich Probleme mit dem Speichern. Wie schreibe ich jetzt, dass er die aktuelle ArrayList wieder speichern soll?
Es soll natürlich so geschehen, dass ich die Daten genauso wieder hereinladen kann, wie es weiter oben ja gelöst wurde.
Ich habe es schon unter anderem damit versucht:

```
ObjectSaver os = new ObjectSaver(list1);
os.save();
```
oder auch:

```
ObjectSaver os = new ObjectSaver((User[])list1);
os.save();
```
Mir ist auch halbwegs klar, warum die zwei Möglichkeiten nicht funktioniern, aber ich finde keine Lösung. Man muss irgendwie die ArrayList list1 als User-Array übergeben, oder?

Hier der ObjectLoader:

```
public class ObjectSaver {
        private User[] userObject;
        private String filename;

        public ObjectSaver(User[] userObject)
        {
                this.userObject = userObject;
        }

        public void save()
        {
                   FileOutputStream fos = null;
                   ObjectOutputStream out = null;
                    try
                    {
                        fos = new FileOutputStream("addressbook.txt", false);
                        out = new ObjectOutputStream(fos);
                        out.writeObject(userObject);
                        out.close();
                   }
                    catch(IOException e)
                    {
                        JOptionPane.showMessageDialog(null,"Fehler beim Speichern!");
                    }

        }
}
```

Vielleicht kann mir ja jemand weiterhelfen.
Danke!

EDIT: Ich habe jetzt den Thread wieder als "ungelöst" markiert, da zwar das Hauptproblem (Laden) gelöst wurde, aber das Folgeproblem (Speichern) leider noch nicht. Ich hoffe, dass das so passt.

Bonz


----------



## André Uhres (15. Jun 2006)

```
ObjectSaver os = new ObjectSaver((User[])list1.toArray());
```


----------



## Bonz (15. Jun 2006)

André Uhres hat gesagt.:
			
		

> ```
> ObjectSaver os = new ObjectSaver((User[])list1.toArray());
> ```



Danke, aber das führt leider zu einer Fehlermeldung:

Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [Ljava.lang.Object;
	at Core.SendGUI.actionPerformed(SendGUI.java:276)

Bonz


----------



## André Uhres (15. Jun 2006)

```
User[] u2 = new User[list1.size()];
        int i = 0;
        for (User user : list1) {
            u2[i] = user;
            i++;
        }
        ObjectSaver os = new ObjectSaver(u2);
```


----------



## Murray (15. Jun 2006)

```
ObjectSaver os = new ObjectSaver((User[])list1.toArray( new User[list1.size()]));
```


----------



## Bonz (15. Jun 2006)

André Uhres hat gesagt.:
			
		

> ```
> User[] u2 = new User[list1.size()];
> int i = 0;
> for (User user : list1) {
> ...



"list1" in der for-Schleife nimmt er nicht, da er mir schreibt, dass es sich hierbei um einen inkompatiblen Typ handelt. Wenn ich das vom Programm vorgeschlagene Typecast mache "(User)" bleibt es allerdings auch bei der Fehlermeldung.

Bonz


----------



## Bonz (15. Jun 2006)

Murray hat gesagt.:
			
		

> ```
> ObjectSaver os = new ObjectSaver((User[])list1.toArray( new User[list1.size()]));
> ```



Das funktioniert!
DANKE!

Muss das jetzt noch weiter testen...

Bonz


----------

