Laden...

MemoryStream zu string und wieder retour...

Erstellt von norman_timo vor 18 Jahren Letzter Beitrag vor 18 Jahren 11.654 Views
norman_timo Themenstarter:in
4.506 Beiträge seit 2004
vor 18 Jahren
MemoryStream zu string und wieder retour...

Hallo C# Fans!

Ich habe ein skurilles Problem:

Zur Versendung instanziierter Objekte via WebService serialisiere ich diese und verschicke sie als string zum Client.

Das geschieht folgendermaßen:


		public static string SerializeBinary(object request) 
		{
			string theString = "";

			System.Runtime.Serialization.Formatters.Binary.BinaryFormatter serializer = 
				new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
			System.IO.MemoryStream memStream = new System.IO.MemoryStream();
			serializer.Serialize(memStream, request);

			// convert memory stream to string
			memStream.Position=0;	
			using (System.IO.StreamReader sr = new System.IO.StreamReader(memStream) ) 
			{
				theString = sr.ReadToEnd();
				// Close and clean up the StreamReader
				sr.Close();
			}

			// return xml string
			return theString;
		}

Mit dieser Methode erhalte ich von dem entsprechenden Objekt einen serialisierten String.

Problem taucht dann aber beim Client auf. Ich bekomme es nicht geregelt, diesen String wieder in ein MemoryStream zu wandeln um mit serializer.Deserialize(memStream); den deserialisierungsprozess anzuschmeissen 😦

Wie wandle ich den String um und übergebe ihn der Deserialize() Funktion? Konkretes Problem:
Wenn ich einen MemoryStream aus dem String ertstelle, dann ist er geschlossen, und es gibt einen Laufzeitfehler, oder ich schließe ihn nach der Verarbeitung, dann meldet aber Deserialize() dass ein unerwartetes Ende im Stream aufgetreten ist ???

ODER: vielleicht gibt es eine andere Art und Weise aus dem String wieder ein instanziiertes Objekt zu machen?

Für Hilfe wäre ich sehr dankbar,

Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo norman_timo,

du brauchst nichts in String umzuwandeln. Du musst nur den Stream wieder an den Anfang zurückspulen, bevor du deserialisierst. Ich denke es gibt eine Seek-Methode oder eine Position-Eigenschaft dafür - habe aber gerade die Doku nicht zur Hand.

herbivore

norman_timo Themenstarter:in
4.506 Beiträge seit 2004
vor 18 Jahren

Jo, das ist prinzipiell richtig Herbivore, danke dafür!

Mein Problem ist aber, dass ich das Objekt via WebService verschicke!

Schicke ich den MemoryStream über SOAP (das geht nämlich nicht) dann bekomme ich nur die Info, an welcher Speicheraddresse und welche Länge das Speicherabbild auf dem Server hat, und das ist auf dem Client nicht zu verwerten.

Deshalb die Umwandlung in einen String, der wird nämlich problemlos via SOAP verschickt, auch weil es sich um einen Standarsdtyp dreht.

Auf dem Client steht also nur der String zur Verfügung.

Oder geht das komfortabler?

Ich bin für jede Idee zu haben und habe vollkommene Programmierhoheit 🙂

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo norman_timo,

ok, überzeugt. Doch in einen String wandeln.

Beim Rückwandeln: MemoryStream öffnen (read/write), String reinschreiben (StreamWriter), Stream zurückspulen, deserialisieren.

HTH

herbivore

F
10.010 Beiträge seit 2004
vor 18 Jahren

Du weist schon, das ein WebService eigentlich auch in der Lage ist
jedes serialisierbare Object ohne umwandlung zu empfangen/Verschicken?

norman_timo Themenstarter:in
4.506 Beiträge seit 2004
vor 18 Jahren

Jo, auch das hab ich schon probiert:


			System.IO.MemoryStream memStream = new System.IO.MemoryStream();
			object retValue;

			// convert string to memory stream
			using (System.IO.StreamWriter sw = new System.IO.StreamWriter(memStream)) 
			{
				sw.WriteLine(theString);

				// convert memory stream to object
				System.Runtime.Serialization.Formatters.Soap.SoapFormatter deserializer = 
					new System.Runtime.Serialization.Formatters.Soap.SoapFormatter();

				memStream.Position=0;
				retValue = deserializer.Deserialize(memStream);

				// Close and clean up the StreamReader
				memStream.Close();
				sw.Close();
			}


Das resultiert in folgender Fehlermeldung:

{"An unexpected end of file parsing NAME has occurred. Line 37, position 2." }

Nu, aber es gibt bei mir in dem String kein Ding wie NAME, ich denke dass er aber irgendwo ein EOS (EndOfStream) erwartet, das er nicht bekommt, weil der Stream noch nicht geschlossen wurde 😦

Schließe ich ihn vorher meckert er, dass er geschlossen ist, und nicht verwenden kann ???

Was mache ich verkehrt?

Norman-Timo

[EDIT⚠ Sorry, nicht verwirren lassen, dass ich einmal den BinaryFormatter benutzt hab, und jetzt den SOAPFormatter, ich unterstütze BEIDES, pass aber schon auf, dass ich immer nur eine Version beim Server und Client verwende 🙂[/EDIT]

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

norman_timo Themenstarter:in
4.506 Beiträge seit 2004
vor 18 Jahren

@FZelle:

Ja, das versuche ich irgendwie, muss aber sagen, dass ich das Serialisieren selbst in die Hand nehmen möchte, da ich Objekte serialisieren will, OHNE dass Klassen, die vererbt worden sind mitserialisert werden!

Ist es dann immer noch problemlos möglich?

Und wenn wie?

Vielleicht ist das eine Lösung die mir zusagt?

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

norman_timo Themenstarter:in
4.506 Beiträge seit 2004
vor 18 Jahren

Trööööt!

Ich bin so blöd 🙂))

Naja eigentlich nicht, aber es reimt sich doch so toll 🙂

Ich habe den Fehler gefunden:

eine kleine Zeile im Code mehr:



// ...

sw.Flush();

// ...


schreibt den kompletten String in den MemoryStream und wird somit auch als komplett erkannt!

Jetzt bin ich auf eine andere Fehlermeldung gestoßen:

{"The constructor to deserialize an object of type CPM.Std.Tracking.WebControls.WebTrackingMap was not found." }

aber das ist klar, weil ich dem Objkekt noch nicht erklärt hab, wie es sich deserialisieren soll, das ist eine Kleinigkeit!

Dank allen trotzdem, vielleicht haben andere genau das gleiche Problem?

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

1.373 Beiträge seit 2004
vor 18 Jahren

Wäre es in deinem Fall nicht besser, den String als z.B. Base64 zu codieren? Sonst hast du doch die ganzen nicht-druckbaren Zeichen mit drin:


...
return Convert.ToBase64String(memStream.GetBuffer(), 0, memStream.Length);

Deserialisieren:


byte[] data = Convert.FromBase64String(theString);
MemoryStream ms = new MemoryStream(data);
....

Also nichts mit StreamReader/StreamWriter. Das ganze ist nicht nur einfacher sondern IMHO auch besser für SOAP.

MfG VizOne

norman_timo Themenstarter:in
4.506 Beiträge seit 2004
vor 18 Jahren

Yes!

Nochmal um einiges besser!

Das werd ich sofort mit einbauen, weil ich nämlich auch festgestellt hab, dass beim BinaryFormatter er das Problem mit der Übertragung hat (whrscheinlich eben Druckzeichen 🙂

Herzlichen Dank, ein wundervoller Beitrag hierzu!

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”