Input/Output Alternative zur Serialisierung/ ImageJ Objecte

Influenza

Neues Mitglied
Hallo ihr Guten!
Ich bin seit einem Jahr in der Programmierung tätig und nun an meine Grenzen gestoßen. Bisher habe ich noch jedes Problem googeln können.

Ich entwickle ein plugin für das java basierte ImageJ (ImageJ API) und brauche eine Klasse die ich speichern und Laden kann. Das Serialisieren habe ich mir natürlich angesehen und versucht anzuwenden (Quellcode weiter unten). Trotzdem gibt die konsole immer einen notserialisable exception aus.
Ist es generell nicht möglich meine Klasse zu speichern oder gibt es eventuell noch andere alternativen?

Herzlichen Dank für eure Hilfe!


Influenza

Java:
import ij.gui.Roi;

import java.awt.Color;
import java.awt.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;



public class EvaSer implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 3873721584911475388L;
	/**
	 * 
	 */
	/**
	 * 
	 */
	public int nSpec;
	public int nImages;
	public List<int[][]> types;
	
	public String evalName;
	public String[] specNames;
	public String[] typeNames;
	
	public List<String> imageNames;		
	public List<Roi[][]> rois;			
	public List<Roi> fixpoints;			
	public List<File[]> files;			
	public Roi[] ovrls;				
	public Color[] specieColors;		
	public File dir;					
	
	public EvaSer(){
		this.evalName="new Evaluation "+System.currentTimeMillis();
		initLists();
		initTypeArrs();
	}
	private void initTypeArrs() {
		typeNames=new String[]{""};
		
	}
	public void initLists() {
		this.imageNames= new ArrayList<String>();
		this.rois= new ArrayList<Roi[][]>();
		this.fixpoints= new ArrayList<Roi>();		
		this.types= new ArrayList<int[][]>();
	}
	public void save(Component parent)  {
		 System.out.println(this.nSpec);
		 System.out.println(this.nImages);
		 System.out.println(this.types.toString());
		 System.out.println(this.evalName);
		 System.out.println(this.specNames.toString());
		 System.out.println(this.typeNames.toString());
		 System.out.println(this.imageNames.toString());
		 System.out.println(this.rois.toString());
		 System.out.println(this.fixpoints.toString());
		 System.out.println(this.files.toString());
		 System.out.println(this.ovrls.toString());
		 System.out.println(this.specieColors.toString());
		 System.out.println(this.dir);
		String path;
		path=this.dir.toString();
		if(this.evalName==null){
			this.evalName=RegularFunctions.getName(parent);
		}
		path=path+this.evalName+".eva";
		
		ObjectOutputStream oos = null;
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(path);
			oos = new ObjectOutputStream(fos);

			oos.writeObject((Object)this);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (oos != null)
				try {
					oos.close();
				} catch (IOException e) {
				}
			if (fos != null)
				try {
					fos.close();
				} catch (IOException e) {
				}
		}
	}

	
	public EvaSer load(String path) {

		ObjectInputStream ois = null;
		FileInputStream fis = null;
		Object so= new Object();
		
		try {
			fis = new FileInputStream(path);
			ois = new ObjectInputStream(fis);
			Object obj = ois.readObject();
			if (obj instanceof EvaSer) {
				so = (EvaSer) obj;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (ois != null)
				try {
					ois.close();
				} catch (IOException e) {
				}
			if (fis != null)
				try {
					fis.close();
				} catch (IOException e) {
				}
		}
		return (EvaSer) so;
	}
}
 
Würde mal behaupten die Klasse
Code:
Roi
oder eines ihrer Member ist nicht serialisierbar. Alle anderen Klassen sind Standard-API und müssetn Serializable sein.
 
Ich benutzer immer folgenden Test um zu prüfen, ob eine Klasse serialisierbar ist.
Java:
public class TurtleSerial {
	public static void main(String[] args) throws IOException {
		DeineKlasse deineKlasse = new DeineKlasse("Turtle");
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
		objectOutputStream.writeObject(deineKlasse);
		System.out.println(byteArrayOutputStream);
	}

}

class DeineKlasse implements Serializable {
	private Thread turtle;
	private String isSerializable;

	public DeineKlasse(String txt) {
		this.isSerializable = txt;
		// this.turtle = new Thread(); // Thread nicht serialisierbar
	}
}
 
Ich habe mir zur Serialisierung sogar eine eigene Klasse angelegt 8
Java:
import java.io.*;

public class Serializer {
	
	// Deklarationen
	
	protected String url = "";
	
	// Konstruktoren
	
	public Serializer() { }
	
	public Serializer( String url ) { this.url = url; }
	
	// Methoden
	
    public Object load() {
		
    	ObjectInputStream input  = null;
    	Object            object = null;
    	
		if ( new File( url ).exists() ) {
			
			try {
				
				input = new ObjectInputStream( new BufferedInputStream( new FileInputStream( url ) ) );
				object = input.readObject();
				input.close();
				
			} catch (            IOException e ) { e.printStackTrace(); }
			
			  catch ( ClassNotFoundException e ) { e.printStackTrace(); }
			
			finally { if ( input != null ) { try { input.close(); } catch ( IOException e ) { e.printStackTrace(); } } }
			
			input = null;
			
		}
		
		return object;
		
	}
	
	public void save( Object object ) { // Welt speichern
		
		ObjectOutputStream output = null;
		
		try {
			
			output = new ObjectOutputStream( new BufferedOutputStream( new FileOutputStream( url ) ) );
			output.writeObject( object );
			output.close();
			
		} catch ( IOException e ) { e.printStackTrace(); }
		
		finally { if ( output != null ) { try { output.close(); } catch ( IOException e ) { e.printStackTrace(); } } }
		
		output = null;
		
	}
	
}
 
Du musst halt bedenken das alle verwendeten Klassen Serialisierbar sein müssen, zudem kannst du wie mein vorposter dazu eine Utilityklasse anlegen, allerdings würde ich dann den weg über statische Hilfsmethoden wählen 🙂

Und z.B auch die dinge wie Streams schließen in wiederrum Separate Utilityklassen auslagern .
 
denn das hier :

Java:
 catch ( IOException e ) { e.printStackTrace(); } }

ist keine Fehlerbehandlung 😉
 
Halli Hallo,
bitte entschuldigt die verzögerte Reaktion meinerseits. ich danke euch allen für eure Mühe!

Die Klasse Roi hat laut API das Serializable interface implementiert. Allerdings wurde ich darauf verwiesen, dass diese Klasse trotzdem nicht ohne weiteres als Serializable Object angesehen werden kann.
(Für Interessierte: Roi (ImageJ API)
wird mithilfe von: RoiEncoder (ImageJ API)
gespeichert, das die Rois in ein byte[] transfomiert)

Jetzt stehe ich jedoch vor dem nächsten Problem! Das Speichern funktioniert ohne Fehlermeldung, die über System.out.println geprüften Felder sind alle ungleich null, ABER beim deserializieren, sprich beim Laden des Objektes, sind die vorher geprüften Felder (auch einfache Strings) null und können nicht gefunden werden.


Fällt jemanden eine Möglichkeit ein, wie ich diesen Fehler systematisch ausmachen und beseitigen könnte?

Vielen Dank und viele Grüße!


Hier nun die neuen Felder, die save/load funktion ist wie oben unverändert:

Java:
public class EvaSer implements Serializable{
	
	private static final long serialVersionUID = 3873721584911475388L;


	public int nSpec;
	public List<EvaImage> images;
	
	public String evalName;
	public String[] specNames;
	public String[] typeNames;

	
	public byte[][] ovrls;				
	public Color[] specieColors;		
	public File dir;				
	
	public EvaSer(){
		this.evalName=("new Evaluation "+System.currentTimeMillis()).substring(0,18);
		initLists();
		initTypeArrs();
	}
	private void initTypeArrs() {
		typeNames=new String[]{""};
		
	}
	public void initLists() {
		this.images= new ArrayList<EvaImage>();
	}
	public void save(Component parent)  {
		 System.out.println(this.nSpec);
		 System.out.println(this.evalName);
		 System.out.println(this.specNames.toString());
		 System.out.println(this.typeNames.toString());
		 System.out.println(this.ovrls.toString());
		 System.out.println(this.specieColors.toString());
		 System.out.println(this.dir);
		String path;
		path=this.dir.toString();
		if(this.evalName==null){
			this.evalName=RegularFunctions.getName(parent);
		}
		path=path+this.evalName+".eva";
		
		ObjectOutputStream oos = null;
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(path);
			oos = new ObjectOutputStream(fos);

			oos.writeObject((Object)this);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (oos != null)
				try {
					oos.close();
				} catch (IOException e) {
				}
			if (fos != null)
				try {
					fos.close();
				} catch (IOException e) {
				}
		}
	}

	
	public EvaSer load(String path) {

		ObjectInputStream ois = null;
		FileInputStream fis = null;
		Object so= new Object();
		
		try {
			fis = new FileInputStream(path);
			ois = new ObjectInputStream(fis);
			Object obj = ois.readObject();
			if (obj instanceof EvaSer) {
				so = (EvaSer) obj;
			}
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (ois != null)
				try {
					ois.close();
				} catch (IOException e) {
				}
			if (fis != null)
				try {
					fis.close();
				} catch (IOException e) {
				}
		}
		return (EvaSer) so;
	}
}

Die Klasse EvaImage habe ich der übersichtlichkeit wegen neu hinzugefügt:
Java:
public class EvaImage implements Serializable {
	
	public String imageName;		
	public List<List<byte[]>> byteRois;		
	public byte[] fixpoint;			
	public File[] imageFile;			
	public List<List<Integer>> types;	
	
	public EvaImage(int nSpec, String imageName, String originPath){

		this.byteRois= new ArrayList<List<byte[]>>();		
		this.types= new ArrayList<List<Integer>>();
		for(int i=0; i<nSpec; i++){
			this.byteRois.add(new ArrayList<byte[]>());
			this.types.add(new ArrayList<Integer>());
		}
		
		this.imageFile= new File[2];
		this.imageFile[0]=new File(originPath);
		this.imageName=imageName;
	}

}
 

Zurück
Oben