Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Tuesday, June 21, 2011 8:58 AM
Hello
im trying to serialize and deserialize c# class into a string.
i read a lot of posts, but still im unable to solve my problem and would apprciate any input.
im using
/serialize
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, data); /// data is the class i wanna serialize.
ms.Seek(0, 0);
StreamReader rdr = new StreamReader(ms);
string str = rdr.ReadToEnd();
byte[] byteArray = Encoding.ASCII.GetBytes(str);
//deserialize
MemoryStream stream = new MemoryStream(byteArray);
stream.Seek(0, 0);
BinaryFormatter bf = new BinaryFormatter();
object d = bf.Deserialize(stream);
when im using this code on simple classes it works just fine, but i when i try to use on the actual class i need to serialize i get runtime error
-> Object of type 'chronoswars.MasterUnit' cannot be converted to type 'chronoswars.UnitBoardData'.
im not sure why the compiler is trying to convert this classes it doesnt make any sense to me.
when im serializing and deserializing the very same class from a file it works just fine. so it is possible for example to get the string from the file, however using a file just to do so is not a solution for me.
i have no idea why im getting this error and or how solve it, or go around it.
Thanks
All replies (19)
Wednesday, June 22, 2011 4:52 AM ✅Answered
Found the problem, you are writing the string to a new stream and encoding it. instead of just returning the buffer. Here is an example for you that i cleaned up a bit with using-blocks to closed the streams. and here you can specify the types to use in the methods:
class Program
{
static void Main(string[] args)
{
var sc = new Someclass();
var b = ToString(sc);
try
{
var o = FromString<Someclass>(b);
Console.WriteLine(o.listi.Count);
}
catch (SerializationException e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
[Serializable]
public class Someclass
{
public List<int?> listi;
public Someclass()
{
listi = new List<int?>();
for (int x = 0; x < 100; x++)
listi.Add(x);
}
}
public static TType FromString<TType>(byte[] byteArray)
{
using (var stream = new MemoryStream(byteArray))
{
var bf = new BinaryFormatter();
return (TType)bf.Deserialize(stream);
}
}
public static byte[] ToString<TType>(TType data)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, data);
return ms.GetBuffer();
}
}
}
Wednesday, June 22, 2011 7:16 AM ✅Answered
I think if you use these two methods instead you are using the ASCII encoding on both the serialize AND deserialize methods it should work
public static TType FromString<TType>(string input)
{
var byteArray = Encoding.ASCII.GetBytes(input);
using (var stream = new MemoryStream(byteArray))
{
var bf = new BinaryFormatter();
return (TType)bf.Deserialize(stream);
}
}
public static string ToString<TType>(TType data)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, data);
return Encoding.ASCII.GetString(ms.GetBuffer());
}
}
Wednesday, June 22, 2011 7:38 AM ✅Answered
Yes!!!! i cant belive this, its actually working!!!
one thing thouogh right before u wrote this last post i was trying to do about the same.
anyway final result - if u use ASCII encoding, for some reason some of the list items get trunced out.
if i changed from ascii to unicode (ovcourse on both ends) it works just fine!
Thank you very much for your help, u did my day!!!
Tuesday, June 21, 2011 9:04 AM
How do you call these methods? You need to cast, so how do you do that?
Tuesday, June 21, 2011 9:07 AM
lets say i have a class MytypeClass ;
MytypeClass newdata = (MytypeClass )bf.Deserialize(stream);
thats how i cast, regardless i get the runtime error before that when im trying to deserialize.
thanks again!
Tuesday, June 21, 2011 9:13 AM
And the stream you pass into the method, where does that come from? A file? could it be an old serialized file of some other class?
Tuesday, June 21, 2011 9:22 AM
no, im wanna build the stream from the string, but for time being im buliding the memory stream from byte array (byte[]),
which is built from the string
str - is the string im wanna deserialize
byte[] byteArray = Encoding.ASCII.GetBytes(str);
MemoryStream stream = new MemoryStream(byteArray);
Tuesday, June 21, 2011 9:24 AM
Wait, what does the string contain?
You know that the string must contain a serialized object of exactly the same typ as the one you are trying to cast to right?
Tuesday, June 21, 2011 9:30 AM
this is to code to serialize and then deserialzie, like i said it works fine on simle clases, but i get the runtime error on a much more complex class.
same class can and is being serialized into a file. i waana do the smae only without using the file
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, data); /// data is the class i wanna serialize.
ms.Seek(0, 0);
StreamReader rdr = new StreamReader(ms);
string str = rdr.ReadToEnd();
byte[] byteArray = Encoding.ASCII.GetBytes(str);
//deserialize
MemoryStream stream = new MemoryStream(byteArray);
stream.Seek(0, 0);
BinaryFormatter bf = new BinaryFormatter();
object d = bf.Deserialize(stream);
thx again
Tuesday, June 21, 2011 9:35 AM
Its impossible to say without seeing more code.
When you deserialize a string, that does not contain the same type as you are trying to cast to.
If you are running this in visual studio you could debug and what what the object that comes out of the Deserialize method really contains. If it is the type you think it is.
Tuesday, June 21, 2011 9:42 AM
yes i understand that, the class im trying to serialize is a very complex class and its impossible to share it here.
i get the runtime error on this
object d = bf.Deserialize(stream); when trying to deserialize.
is there a diffrent approch on how to serialize an object into a string?
Again thanks for your help
Tuesday, June 21, 2011 10:56 AM
ok, i started to try to seralize class by class of the main class im trying to serialize and i found the problem.
some class contains a list of element of a class. when i add more then 16~ objects to that class the deserializations fails.
further more when i created just some class with an int list with in, when i load to that list more than 90~ ints im
getting the exact same error!
any ideas?
the entire code:
// to unserialize an object from byte array
public object FromString(byte[] byteArray)
{
MemoryStream stream = new MemoryStream(byteArray);
BinaryFormatter bf = new BinaryFormatter();
object d = null;
try
{
d = bf.Deserialize(stream);
}
catch (Exception e)
{
}
return d;
}
// to seriazlie an object into byte array
public byte[] tostring(object data)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, data);
ms.Seek(0, 0);
StreamReader rdr = new StreamReader(ms);
string str = rdr.ReadToEnd();
byte[] byteArray = Encoding.ASCII.GetBytes(str);
return byteArray ;
}
//just some class to serialize
public class MasterunitCollectiondemo
{
public List<int> listi;
public MasterunitCollectiondemo()
{
listi = new List<int>();
for (int y=0;y<100;y++){
listi.Add(y);}
}
}
// code that generate runtime error
MasterunitCollectiondemo md = new MasterunitCollectiondemo();
byte[] b = tostring(md);
object o = FromString(b) ; -> here i get an error if the list in md is bigger than about 90!!!
thanks for your help
Wednesday, June 22, 2011 12:44 AM
Exacly what errormessage do you get there?
Wednesday, June 22, 2011 3:48 AM
when i insert for example 100 ints, i get SerializationException
Binary stream '63' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.
Wednesday, June 22, 2011 4:14 AM
You are not sending the same code now right? That example wont even work since the Masterdemo class dont have the Serializable attribute
Wednesday, June 22, 2011 4:22 AM
thank you very much for your help, i appreciate it very much!
you are most right, i only created this code to show an example(and i wrote in this post), and yes its missing serialize and initialize of the list.
i created a new project and tested it and im getting the same error .
this is the real complied code:(so u can test it yourself)
[Serializable]
public class Someclass
{
private List<int> listi;
public Someclass()
{
listi = new List<int>();
for (int x = 0; x < 100; x++)
listi.Add(x);
}
}
public object FromString(byte[] byteArray)
{
MemoryStream stream = new MemoryStream(byteArray);
// stream.Seek(0, 0);
BinaryFormatter bf = new BinaryFormatter();
object d = null;
try
{
d = bf.Deserialize(stream);
}
catch (ArgumentException e)
{
}
return d;
}
public byte[] tostring(object data)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, data);
ms.Seek(0, 0);
StreamReader rdr = new StreamReader(ms);
string str = rdr.ReadToEnd();
byte[] byteArray = Encoding.ASCII.GetBytes(str);
return byteArray ;
}
public void checkserialize ()
{
Someclass sc = new Someclass();
byte[] b = tostring(sc);
try
{
object o = FromString(b);// <=====error here!!!
}
catch (SerializationException e)
{
}
}
Wednesday, June 22, 2011 7:12 AM
Thank you very much help!
i spent hrs trying to solve this, i tried so many things u wouldnt belive it....
anyway one last question thouogh, the entire purpess of this is to be able to save SomeClass (from the above example) into a string,
so that i will be able to save it a sql database table.
your code works great, but im not sure how to cast the bytearray into a string without losing chars and vice verca.
Again many thanks for your help! you were truly helpfull!
Wednesday, June 22, 2011 7:52 AM
Great, glad i could help :)
Monday, July 11, 2011 2:15 AM
Hi,
I don't mean to hijack the post but I am encountered with a somewhat related problem and I was hoping you could help me figure out where I made an error.
I have a serializable class called Measurement. I also used your code to help me with the customized serialization/deserialization. I am using RabbitMQ to write and read messages (of Measurement objects). I am getting the following error on the command line to the left. It looks the error originates from the deserialize method?
Unhandled Exception: System.InvalidCastException: Unable to cast object of 'Measurement' to type 'Measurement' .
I have also included the entire code for reference.
Thanks in advance,
//MB1.cs
using System;
using System.IO;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
//start alternate serialization
public static class AltSerialization
{
public static byte[] AltSerialize(Measurement m)
{
using (var ms = new MemoryStream())
{
var bf = new BinaryFormatter();
bf.Serialize(ms, m);
return ms.GetBuffer();
}
}
public static Measurement AltDeSerialize(byte[] seriM)
{
using (var stream = new MemoryStream( seriM ))
{
BinaryFormatter bf = new BinaryFormatter();
return (Measurement)bf.Deserialize(stream);
}
}
}
//end alternte serialization
[Serializable()] //This attribute sets class to be serialized
public class Measurement : ISerializable
{
[NonSerialized] public int id;
public int time; //timestamp
public double value;
public Measurement()
{
id = 1;
time = 12;
value = 0.01;
}
public Measurement(int _id, int _time, double _value)
{
id = _id;
time = _time;
value = _value;
}
//Deserialization constructor
public Measurement(SerializationInfo info, StreamingContext ctxt)
{
//Assign the values from info to the approporiate properties
//time = (int)info.GetValue("MeasurementTime", typeof(int));
//value = (double)info.GetValue("MeasurementValue", typeof(double));
}
//Serialization function
public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
{
// Custom name-value pair
// Values must be read with the same name they're written
//info.AddValue("MeasurementTime", time);
//info.AddValue("MeasurementValue", value);
}
}
public interface IMessageBus
{
string MsgSys // Property 1
{
get;
set;
}
void write (Measurement m1);
Measurement read();
void publish(string queue);
void subscribe(string queue);
}
public class Rabbit : IMessageBus
{
// Implementation of methods for Rabbit class go here
private List<string> publishQ = new List<string>();
private List<string> subscribeQ = new List<string>();
public void write ( Measurement m1 )
{
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "localhost";
using (IConnection connection = factory.CreateConnection())
using (IModel channel = connection.CreateModel()) {
channel.ExchangeDeclare("myExchange", "direct");
byte[] body = AltSerialization.AltSerialize( m1 );
foreach (string queue in publishQ)
{
channel.BasicPublish("myExchange", queue, null, body);
Console.WriteLine("\n [x] Message sent to queue {0}.", queue );
}
}
}
public void publish(string queueName)
{
publishQ.Add(queueName);
}
public Measurement read()
{
ConnectionFactory factory = new ConnectionFactory();
factory.HostName = "localhost";
using (IConnection connection = factory.CreateConnection())
using (IModel channel = connection.CreateModel()) {
channel.ExchangeDeclare("myExchange", "direct");
string queue_name = channel.QueueDeclare();
foreach (string severity in subscribeQ) {
channel.QueueBind(queue_name, "myExchange", severity);
}
Console.WriteLine(" [*] Waiting for messages. " +
"To exit press CTRL+C");
QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel);
channel.BasicConsume(queue_name, true, consumer);
while(true) {
BasicDeliverEventArgs ea =
(BasicDeliverEventArgs)consumer.Queue.Dequeue();
Console.WriteLine(" [x] Received ");
return AltSerialization.AltDeSerialize( ea.Body );
}
}
}
public void subscribe(string queueName)
{
subscribeQ.Add(queueName);
}
public static string MsgSysName;
public string MsgSys
{
get
{
return MsgSysName;
}
set
{
MsgSysName = value;
}
}
public Rabbit(string _msgSys) //Constructor
{
System.Console.WriteLine("\nMsgSys: RabbitMQ");
MsgSys = _msgSys;
}
}
public class Zmq : IMessageBus
{
public void write ( Measurement m1 )
{
//
}
public Measurement read()
{
//
return null;
}
public void publish(string queue)
{
//
}
public void subscribe(string queue)
{
//
}
public static string MsgSysName;
public string MsgSys
{
get
{
return MsgSysName;
}
set
{
MsgSysName = value;
}
}
// Implementation of methods for Zmq class go here
public Zmq(string _msgSys) //Constructor
{
System.Console.WriteLine("ZMQ");
MsgSys = _msgSys;
}
}
public class MessageBusFactory
{
public static IMessageBus GetMessageBus(string MsgSysName)
{
switch ( MsgSysName )
{
case "Zmq":
return new Zmq(MsgSysName);
case "Rabbit":
return new Rabbit(MsgSysName);
default:
throw new ArgumentException("Messaging type " +
MsgSysName + " not supported." );
}
}
}
public class MainClass
{
public static void Main()
{
//Asks for the message system
System.Console.WriteLine("Enter name of messageing system: ");
System.Console.WriteLine("Usage: [Rabbit] [Zmq]");
string MsgSysName = (System.Console.ReadLine()).ToString();
//Create a new Measurement message
Measurement m1 = new Measurement(2, 2345, 23.456);
//Declare an IMessageBus instance:
//Here, an object of the corresponding Message System
// (ex. Rabbit, Zmq, etc) is instantiated
IMessageBus obj1 = MessageBusFactory.GetMessageBus(MsgSysName);
System.Console.WriteLine("\nA {0} object is now created.", MsgSysName);
//System.Console.WriteLine("Test message:\nID: {0}", m1.id);
//System.Console.WriteLine("Time: {0}", m1.time);
//System.Console.WriteLine("Value: {0}", m1.value);
// Ask queue name and store it
//System.Console.WriteLine("Enter a queue name: ");
//string QueueName = (System.Console.ReadLine()).ToString();
//obj1.publish( QueueName );
//System.Console.WriteLine("Enter another queue name: ");
//QueueName = (System.Console.ReadLine()).ToString();
//obj1.publish( QueueName );
// Write message to the queue
//obj1.write( m1 );
System.Console.WriteLine("Enter a queue to subscribe to: ");
string QueueName = (System.Console.ReadLine()).ToString();
obj1.subscribe( QueueName );
// Read message from the queue
Measurement m2 = new Measurement();
m2 = obj1.read();
}
}