Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Stream Binär speichern
KRambo
myCSharp.de - Member



Dabei seit:
Beiträge: 355

Themenstarter:

Stream Binär speichern

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
VizOne
myCSharp.de - Member

Avatar #avatar-1563.gif


Dabei seit:
Beiträge: 1.373

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
KRambo
myCSharp.de - Member



Dabei seit:
Beiträge: 355

Themenstarter:

beantworten | zitieren | melden

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

Hier der Exception-Text:
Zitat
************** 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...
private Nachricht | Beiträge des Benutzers
KRambo
myCSharp.de - Member



Dabei seit:
Beiträge: 355

Themenstarter:

beantworten | zitieren | melden

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...
private Nachricht | Beiträge des Benutzers
NoOneKnows
myCSharp.de - Member

Avatar #avatar-1526.gif


Dabei seit:
Beiträge: 333
Herkunft: Hannover

beantworten | zitieren | melden

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})
private Nachricht | Beiträge des Benutzers
KRambo
myCSharp.de - Member



Dabei seit:
Beiträge: 355

Themenstarter:

beantworten | zitieren | melden

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;
}
private Nachricht | Beiträge des Benutzers
Fabse
myCSharp.de - Member



Dabei seit:
Beiträge: 124

beantworten | zitieren | melden

Zitat
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)
private Nachricht | Beiträge des Benutzers
VizOne
myCSharp.de - Member

Avatar #avatar-1563.gif


Dabei seit:
Beiträge: 1.373

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
KRambo
myCSharp.de - Member



Dabei seit:
Beiträge: 355

Themenstarter:

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers