Wie genau funktionieren Load- und Save-Methoden in Java?
Ich habe folgende Klassen gegeben:
class Person {
private String firstname;
private String lastname;
private String sortname;
public Person() {
}
public Person(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
updateSortname();
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
updateSortname();
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
updateSortname();
}
public String getSortname() {
return sortname;
}
public void updateSortname() {
sortname = lastname + firstname;
}
@Override
public String toString() {
return firstname + " " + lastname + " (" + sortname + ")";
}
public static List<Person> load(String filename) throws IOException {
return null;
}
public static Person load(DataInputStream in) throws IOException {
return null;
}
public static void save(String filename, List<Person> list) throws IOException {
}
public static void save(DataOutputStream out, Person person) throws IOException {
}
public static List<Person> unserialize(String filename) throws IOException, ClassNotFoundException {
return null;
}
public static void serialize(String filename, List<Person> persons) throws IOException {
}
}
public class PersonTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<Person> persons = new ArrayList<>();
persons.add(new Person("Willy", "Wonka"));
persons.add(new Person("Charlie", "Bucket"));
persons.add(new Person("Grandpa", "Joe"));
System.out.println(persons);
Person.save("persons.sav", persons);
persons = Person.load("persons.sav");
System.out.println(persons);
Person.serialize("persons.ser", persons);
persons = Person.unserialize("persons.ser");
System.out.println(persons);
}
}
Mein Problem:
Ich soll für dieses Programm die Methoden load, save, unserialize und serialize definieren. Ich habe bisher nur Beispiele dazu gesehen, mit einzelnen Klassenobjekten, wie z.B. einer Klasse Domino. Wie man dabei mit Arrays arbeitet, ist mir nicht klar und ich würde mich freuen, wenn mir jemand das Thema I/O genauer erklären könnte.
1 Antwort
Bei der ersten save Methode alle Attribute mit write... schreiben:
public static void save(DataOutputStream out, Person person) throws IOException {
out.writeUTF(person.firstname);
out.writeUTF(person.lastname);
}
Bei der zweiten Methode erst die Größe der Liste einlesen, damit die load Methode später weiß, wie viele Personen gelesen werden müssen und dann jede Person mit der oberen Methode speichern:
public static void save(String filename, List<Person> list) throws IOException {
try (DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)))) {
out.writeInt(list.size());
for (int i = 0; i < list.size(); i++) {
save(out, list.get(i));
}
}
}
Die load Methoden funktionieren analog, nur dass statt write... read... verwendet wird. (Und natürlich auch ein InputStream statt eines OutputStreams).
unserialize: die Liste mit readObject() auslesen und speichern:
public static List<Person> unserialize(String filename) throws IOException, ClassNotFoundException {
List<Person> list = null;
try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(filename)))) {
list = (List<Person>) in.readObject();
}
return list;
}
serialize: wieder analog, nur mit writeObject(object) statt read
Die Größe der Liste nur einmal auslesen, also statt
for (int i = 0 ; i<in.readInt(); i++)
int size = in.readInt();
for (int i = 0 ; i<size; i++)
Habe das eigentliche Problem gefunden, in.readInt() liefert den Wert 350057 und eine java.io.EOFException, wenn ich normal mit dem Wert 3 arbeite kommt das richtige Ergebniss raus. Warum in.readInt() dieses Problem hat, ist mir nicht klar.
Zum besseren Verständnis ist hier nochmal, der gesamte Code:
import java.util.List;
import java.io.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
class Person implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private String firstname;
private String lastname;
private String sortname;
public Person() { }
public Person(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
updateSortname();
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
updateSortname();
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
updateSortname();
}
public String getSortname() {
return sortname;
}
public void updateSortname() {
sortname = lastname + firstname;
}
@Override
public String toString() {
return firstname + " " + lastname + " (" + sortname + ")";
}
public static List<Person> load(String filename) throws IOException {
List<Person> Leute = new ArrayList<>();
try (DataInputStream in = new DataInputStream (new BufferedInputStream (new FileInputStream(filename)))){
// System.out.println(in.readInt());
for (int i = 0 ; i<3; i++) {
Leute.add(i, load(in));
}
}
return Leute;
}
public static Person load(DataInputStream in) throws IOException {
Person StandIn;
String firstname = in.readUTF();
String lastname = in.readUTF();
StandIn= new Person(firstname, lastname);
return StandIn;
}
public static void save(String filename, List<Person> list) throws IOException {
try (DataOutputStream out = new DataOutputStream (new BufferedOutputStream (new FileOutputStream(filename)))){
for (int i = 0; i < list.size(); i++) {
save(out, list.get(i));
}
}
}
public static void save(DataOutputStream out, Person person) throws IOException {
out.writeUTF(person.firstname);
out.writeUTF(person.lastname);
}
@SuppressWarnings("unchecked")
public static List<Person> unserialize(String filename) throws IOException, ClassNotFoundException {
List<Person> list = null;
try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(filename)))) {
list = (List<Person>) in.readObject();
}
return list;
}
public static void serialize(String filename, List<Person> persons) throws IOException {
try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(filename)))) {
out.writeObject(persons);
}
}
}
public class PersonTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<Person> persons = new ArrayList<>();
persons.add(new Person("Willy", "Wonka"));
persons.add(new Person("Charlie", "Bucket"));
persons.add(new Person("Grandpa", "Joe"));
System.out.println(persons);
Person.save("persons.sav", persons);
persons = Person.load("persons.sav");
System.out.println(persons);
Person.serialize("persons.ser", persons);
persons = Person.unserialize("persons.ser");
System.out.println(persons);
}
}
Du hast in der save Methode
public static void save(String filename, List<Person> list) throws IOException {
try (DataOutputStream out = new DataOutputStream (new BufferedOutputStream (new FileOutputStream(filename)))){
for (int i = 0; i < list.size(); i++) {
save(out, list.get(i));
}
}
}
vergessen, zuerst die Größe der Liste mit
out.writeInt(list.size());
zu speichern
Ich habe die load Methoden definiert, bekomme aber immer eine IOException. Das Problem scheint das mehrfache aufrufen der zweiten load Methode.:
public static List<Person> load(String filename) throws IOException {
List<Person> Leute = new ArrayList<>();
try (DataInputStream in = new DataInputStream (new BufferedInputStream (new FileInputStream(filename)))){
for (int i = 0 ; i<in.readInt(); i++) {
Leute.add(i, load(in));
}
}
return Leute;
}
public static Person load(DataInputStream in) throws IOException {
Person StandIn;
String firstname = in.readUTF();
String lastname = in.readUTF();
StandIn= new Person(firstname, lastname);
return StandIn;
}
Was wäre der korrekte Weg, auf jede Person des DataInputStreams zuzugreifen?