Noch mehr Serialisierungs Fragen

Der Wolf

Erfahrenes Mitglied
Hi,

folgendes Problem.
Ich habe eine Klasse in der sowohl ein nu.xom.Element als auch ein Attachment abgespeichert sind, die ich gerne serialisieren möchte. Das Problem ist, dass nu.xom.Element von sich aus nicht das Interface Serializeable implementiert und das Attachment auch nicht. (Wobei das Attachment eh ein binary attachment ist und ich mit getValue() das entsprechende binary array bekommen kann). Ich würde die ganze Sache gerne als binary abspeichern, weil im Moment in den meisten Fällen in dem Attachment ein Bild drin steht und wenn ich das als jpeg codieren kann, kann ich anscheinend bei der Speicherung auch nochmal einiges an Platz sparen, da es vorher in einem anderen Format (icewing Format) bei meiner Applikation angekommen ist. Die Frage ist nun, wie ich geschickt die einzelnen Teile serialisiere um sie dann als komplettes Objekt in eine Datei zu schreiben. Ich würde gerne am Ende wieder sowas wie das writeObject(), readObject() der ObjectInput/Output-Streams haben.

\edit: Meine jetztige Idee ist, die einzelnen Teile "per Hand" in ein byte-Array zu schreiben, die Länge der einzelnen byte arrays ebenfalls in ein bytearray schreiben und dann alle arrays aneinanderhängen und in eine Binär-Datei schreiben. Oder gibt es da eine bessere Methode?
Ich hatte auch schon die Idee gelesen die Bilder einfach einzeln ab zu speichern und die Timestamps als Dateinamen zu verwenden, aber irgendwie finde ich diese Möglichkeit ziemlich unschön. Oder ist die vielleicht performance technisch einfach sehr viel besser?

Gruß
Der Wolf
 
Zuletzt bearbeitet:
Ich hab jetzt mal eine Lösung implementiert, bei der ich glaube, dass es so gehen müsste. Keine Ahnung wie nützlich oder effizient die ist. Vielleicht kann mir ja jemand ein paar weitere Tipps geben.

Java:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.io.StringReader;
import net.sf.xcf.transport.Attachment;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.ParsingException;

/**
 * 
 */
public class DataEvent implements Serializable {

  private long timestamp;

  private transient Element data;
  
  private transient Attachment attachment;

  public DataEvent() {	
  }

  public void setTimestamp(long timestamp) {
	this.timestamp = timestamp;
  }

  public void setTimestampNow() {
	this.timestamp = System.currentTimeMillis();
  }

  public long getTimestamp() {
	return timestamp;
  }

  public void setData(Element data) {
	this.data = data;
  }

  public Element getData() {
	return data;
  }

  public void setAttachment(Attachment attachment) {
	this.attachment = attachment;
  }

  public Attachment getAttachment() {
	return attachment;
  }

  // ======================================================================
  // Encoding part.
  // ======================================================================
  
  /** Write this object to an object ouput stream. */
  private void writeObject(ObjectOutputStream stream) throws IOException {
	stream.defaultWriteObject();
	encodeData(stream);
	encodeAttachment(stream);
  }

  
  private void encodeData(ObjectOutputStream stream) throws IOException {
	String stringrep = data.toXML();	
	stream.writeUTF(stringrep);
  }

  private void encodeAttachment(ObjectOutputStream stream) throws IOException {
	byte[] bytes = attachment.getValue();	
	stream.writeUTF(String.valueOf(bytes.length));
	stream.write(attachment.getValue());
  }

  // ======================================================================
  // Decoding part.
  // ======================================================================
  
  /** Decodes a data event from a binary representation. */
  private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {	
	stream.defaultReadObject();
	decodeData(stream);
	decodeAttachment(stream);
  }

  private void decodeData(ObjectInputStream stream) throws IOException {
	String stringrep = stream.readUTF();
	StringReader reader = new StringReader(stringrep);
	Builder builder = new Builder();
	try {
	  Document doc = builder.build(reader);
	  this.data = (Element) doc.getRootElement().copy();
	} catch (ParsingException ex) {
	  // This could never happen.
	}
  }

  private void decodeAttachment(ObjectInputStream stream) throws IOException {
	// Read length of attachment.
	String length = stream.readUTF();	
	byte[] array = new byte[Integer.valueOf(length)];
	stream.readFully(array);
	this.attachment = new Attachment();
	this.attachment.setValue(array);
  }
  
}

Hier noch eine Klasse zum Testen. Falls jemand das ausprobieren will, braucht er die xom lib und die xcf lib (Ich hoffe ich hab keine vergessen).

Java:
import java.io.File;
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 net.sf.xcf.transport.Attachment;
import nu.xom.Element;

public class Main {

  public Main() {

	byte[] array1 = new byte[90];
	for (int i = 0; i < 90; i++) {
	  array1[i] = 1;
	}
	Attachment attach1 = new Attachment();
	attach1.setValue(array1);

	DataEvent event = new DataEvent();
	event.setTimestamp(123);
	event.setData(new Element("DATA1"));
	event.setAttachment(attach1);

	System.out.println("Original:");
	System.out.println("\t Timestamp: " + event.getTimestamp());
	System.out.println("\t Data: " + event.getData().toXML());
	System.out.println("\t Attachment: " + event.getAttachment().getValue().length);

	byte[] array2 = new byte[110];
	for (int i = 0; i < 110; i++) {
	  array2[i] = 0;
	}
	Attachment attach2 = new Attachment();
	attach2.setValue(array2);
	DataEvent event2 = new DataEvent();
	event2.setTimestampNow();
	event2.setData(new Element("CLAUDIA"));
	event2.setAttachment(attach2);

	System.out.println("Original:");
	System.out.println("\t Timestamp: " + event2.getTimestamp());
	System.out.println("\t Data: " + event2.getData().toXML());
	System.out.println("\t Attachment: " + event2.getAttachment().getValue().length);

	try {
	  FileOutputStream output = new FileOutputStream(new File("/homes/dschulze/Test.bin"));
	  ObjectOutputStream stream = new ObjectOutputStream(output);
	  stream.writeObject(event);
	  stream.writeObject(event2);
	  stream.close();
	} catch (FileNotFoundException ex) {
	  ex.printStackTrace();
	} catch (IOException ex) {
	  ex.printStackTrace();
	}

	Object obj1 = null, obj2 = null;
	try {
	  FileInputStream input = new FileInputStream(new File("/homes/dschulze/Test.bin"));
	  ObjectInputStream stream = new ObjectInputStream(input);
	  obj1 = stream.readObject();
	  obj2 = stream.readObject();
	  System.out.println(obj1 instanceof DataEvent);
	  System.out.println(obj2 instanceof DataEvent);
	  stream.close();
	} catch (FileNotFoundException ex) {
	  ex.printStackTrace();
	} catch (IOException ex) {
	  ex.printStackTrace();
	} catch (ClassNotFoundException ex) {
	  ex.printStackTrace();
	}

	if (obj1 != null) {
	  DataEvent event3 = (DataEvent) obj1;
	  System.out.println("Parsed1:");
	  System.out.println("\t Timestamp: " + event3.getTimestamp());
	  System.out.println("\t Data: " + event3.getData().toXML());
	  System.out.println("\t Attachment: " + event3.getAttachment().getValue().length);
	}

	if (obj2 != null) {
	  DataEvent event4 = (DataEvent) obj2;
	  System.out.println("Parsed2:");
	  System.out.println("\t Timestamp: " + event4.getTimestamp());
	  System.out.println("\t Data: " + event4.getData().toXML());
	  System.out.println("\t Attachment: " + event4.getAttachment().getValue().length);
	}

  }

  public static void main(String[] args) {
	new Main();
  }
}

Gruß
Der Wolf
 
Zurück