Laden...

Stream Binär speichern

Erstellt von KRambo vor 19 Jahren Letzter Beitrag vor 19 Jahren 8.709 Views
K
KRambo Themenstarter:in
355 Beiträge seit 2004
vor 19 Jahren
Stream Binär speichern

Hallo Leute

Hab ein kleines Problem und zwar hab ich folgende Funktionen (1te zum laden der Config, 2te zum Speichern derselben).


public static ArrayList LoadConfig()
{
	if(File.Exists(PROFILE_FILE_NAME))
	{
		XmlSerializer serializer = new XmlSerializer(typeof(ConfigWrapper));
		StreamReader reader = new StreamReader(PROFILE_FILE_NAME);
		ConfigWrapper wrapper = (ConfigWrapper)serializer.Deserialize(reader.BaseStream);
		reader.Close();

		return wrapper.Profiles;
	}
	else
		return new ArrayList();

}
		
public static void SaveConfig(ArrayList profiles, string language)
{
	XmlSerializer serializer = new XmlSerializer(typeof(ConfigWrapper));
	StreamWriter writer = new StreamWriter( PROFILE_FILE_NAME,false);				
	try
	{
		ConfigWrapper wrapper = new ConfigWrapper();
		wrapper.Profiles = profiles;
		wrapper.Language = language;
				
		serializer.Serialize(writer.BaseStream,wrapper);
	}
	catch(Exception x)
	{
		System.Diagnostics.Debug.WriteLine(x.Message);
	}

	writer.Close();
}

Jetzt möchte ich das ganze aber binär abspeichern (also mit dem BinaryFormatter). Ok hab ich mir gedacht, tausch ich einfach den XmlSerializer gegen den BinaryFormatter aus, das ganze sieht dann so aus:


public static ArrayList LoadConfig()
{
	if(File.Exists(PROFILE_FILE_NAME))
	{
		//XmlSerializer serializer = new XmlSerializer(typeof(ConfigWrapper));
		BinaryFormatter formatter = new BinaryFormatter();

		StreamReader reader = new StreamReader(PROFILE_FILE_NAME);
		//ConfigWrapper wrapper = (ConfigWrapper)serializer.Deserialize(reader.BaseStream);
		ConfigWrapper wrapper = (ConfigWrapper)formatter.Deserialize(reader.BaseStream);
		reader.Close();

		return wrapper.Profiles;
	}
	else
		return new ArrayList();

}
		
public static void SaveConfig(ArrayList profiles, string language)
{
	//XmlSerializer serializer = new XmlSerializer(typeof(ConfigWrapper));
	BinaryFormatter formatter = new BinaryFormatter();
	StreamWriter writer = new StreamWriter( PROFILE_FILE_NAME,false);				
	try
	{
		ConfigWrapper wrapper = new ConfigWrapper();
		wrapper.Profiles = profiles;
		wrapper.Language = language;
				
		formatter.Serialize(writer.BaseStream,wrapper);
		//serializer.Serialize(writer.BaseStream,wrapper);
	}
	catch(Exception x)
	{
		System.Diagnostics.Debug.WriteLine(x.Message);
	}

	writer.Close();
}

Das ganze funktioniert aber noch nicht ganz. Wenn ich SaveConfig aufrufe, dann speichert er das ganze auch, wenn ich das ganze aber wieder laden möchte, bekomme ich ne Exception und zwar "Das Streamende wurde erreicht, bevor die Verarbeitung abgeschlossen wurde."

Mache ich da irgendwas falsch?? Help 🙂

1.373 Beiträge seit 2004
vor 19 Jahren

Also, bei mir funktioniert der Code soweit. Was für eine Exception ist das eigentlich, die du kriegst (welcher Typ)?

Die einzigen Dinge, die ich verbessern würde, wären, direkt einen FileStream statt StreamReader/Writer zu benutzen, die Streams mit dem using-statement automatisch schließen zu lassen und nicht direkt "Exception" zu fangen sondern nur diejenigen Ausnahmen, die ich erwarte.

MfG VizOne

K
KRambo Themenstarter:in
355 Beiträge seit 2004
vor 19 Jahren

Hab ich mir auch gedacht, dass es soweit funktionieren müsste...

Hier der Exception-Text:

************** Ausnametext **************
System.Runtime.Serialization.SerializationException: Das Streamende wurde erreicht, bevor die Verarbeitung abgeschlossen wurde.
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at SwitchNet.Config.LoadConfig() in e:\visual studio projects\switchnetwork binaryconfig\config.cs:line 35
at SwitchNet.MainForm.loadProfiles() in E:\Visual Studio Projects\SwitchNetwork BinaryConfig\MainForm.cs:line 489
at SwitchNet.MainForm.loadApp() in E:\Visual Studio Projects\SwitchNetwork BinaryConfig\MainForm.cs:line 599
at SwitchNet.MainForm.MainForm_Load(Object sender, EventArgs e) in E:\Visual Studio Projects\SwitchNetwork BinaryConfig\MainForm.cs:line 622
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Was ich komisch finde, dass er immer gleich viel in die Datei reinschreibt, obwohl das Objekt ja eine ArrayListe ist. Steht aber immer das gleiche in der Datei, als ob er nicht alles schreiben würde...

K
KRambo Themenstarter:in
355 Beiträge seit 2004
vor 19 Jahren

Weiss niemand woran das liegen könnte? Ich schreib das ganze mal wie du gesagt hast auf nen FileStream um mit using, wobei ich nicht glaube dass es daran liegt...

333 Beiträge seit 2004
vor 19 Jahren

Ich denke mal es ist kein Problem des Deserialisierens, sondern des Serailisierens. Du sagst selbst die Datei ist immer gleich groß. Also wenn sich die Inhalte der ArrayList verändern, kann das nicht sein. Die EndOfStream-Exception deutet auch deutlich darauf hin, das die gespeicherte Datei unvollständig ist.

Öhm, aber was mir grad so einfällt. Ruf mal writer.Flush() vor dem writer.Close() auf. Vielelicht nützt das was. Bin der Meinung ich hatte damit auch schonmal ein Problem.

([bb]|[^b]{2})

K
KRambo Themenstarter:in
355 Beiträge seit 2004
vor 19 Jahren

Hab ich schon. Hab grad gemerkt dass er gar nicht soweit kommt. Es gibt ne Exception beim Serialisieren und zwar ne System.Runtime.Serialization.SerializationException: "Der Typ ConfigWrapper in Assembly Switch, Version=1.0.1836.1297, Culture=neutral, PublicKeyToken=null ist nicht als serialisierbar markiert."

Nur was heisst jetzt das für mich?
Die Klasse ConfigWrapper sieht so aus:


[XmlInclude(typeof(Profile))]
public class ConfigWrapper
{
	[XmlArrayAttribute("Profiles")]
	public ArrayList Profiles;
}

F
124 Beiträge seit 2004
vor 19 Jahren

Original von KRambo

  
[XmlInclude(typeof(Profile)), Serializable()]  
public class ConfigWrapper  
{  
[XmlArrayAttribute("Profiles")]  
public ArrayList Profiles;  
}  
  

alle klassen, die serialisierbar sein sollen, müssen als serialisierbar markiert werden und das macht man mit nem anttribut. klassenfelder, die nicht serialisiert werden sollen, werden folgendermaßen markiert:

	public class PaintManager
{
private Image img;

[field: NonSerialized()] public event EventHandler LastImageChanged;
[field: NonSerialized()] public event EventHandler PaintPartsChanged;
}

events dürfen übrigens nicht serialisiert werden, weshalb ich auch das bsp genommen habe. dann versucht der formatter auch noch die form usw mit zu serialisieren (wenn die sich für das event registriert hat natürlich nur)

1.373 Beiträge seit 2004
vor 19 Jahren

Das Attribut muss auch bei allen Typen gesetzt sein, die in der ArrayList eingefügt werden, sprich: alle Typen im Objektgraphen müssen serialisierbar sein.

MfG VizOne

K
KRambo Themenstarter:in
355 Beiträge seit 2004
vor 19 Jahren

Hey super dank eurer Hilfe hab ichs jetzt geschafft. Musste an 2 Stellen beim XmlInclude das Serializable() einfügen und dann noch bei ner Klasse und jetzt läufts problemlos 🙂

Das freut mich jetzt richtig danke vielmals 😁