I have an object, instance of a Serializable class. I was wondering how can you get this object as a byte stream?
I know I can use BinaryFormatter and then use the Serialize method, but this method takes a serializationStream where it writes the serialized object. I want to be able to write it in a file/stream in a specific position so I would like to do something like:
obj = new Something(); // obj is serializable
byte[] serialized = obj.serialize(); [*]
file.write(position, serialized)
Is there any way I can do the [*], to take the bytes of the serialization of an object?
MemoryStream m = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(m, new MyClass() {Name="SO"});
byte[] buf = m.ToArray(); //or File.WriteAllBytes(filename, m.ToArray())
[Serializable]
public class MyClass
{
public string Name;
}
Related
I'm trying to serialize a FormCollection object, and based on what I have researched, it inherits NameObjectCollectionBase so it also inherits GetObjectData and ISerializable. Wouldn't this mean it is serializable?
https://msdn.microsoft.com/en-us/library/system.web.mvc.formcollection(v=vs.118).aspx
Here's a snippet of what I'm trying:
BinaryFormatter formatter = new BinaryFormatter();
//Serialize
using (MemoryStream stream = new MemoryStream())
{
formatter.Serialize(stream, data);
string test = Convert.ToBase64String(stream.ToArray());
Session["test"] = test;
};
//Deserialize
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String((string)Session["test"])))
{
data = (FormCollection) formatter.Deserialize(stream);
}
I, unfortunately, got this error:
System.Runtime.Serialization.SerializationException: Type 'System.Web.Mvc.FormCollection' in Assembly 'System.Web.Mvc, Version=5.2.3.0, Culture=neutral... is not marked as serializable.
Because this is a sealed class, I cannot extend it and add the [Serializable] Attribute.
My questions is:
Why I can't serialize FormCollection like this?
And how I can serialize/deserialize a FormCollection object?
It cannot be serialized like this because it lacks [Serializable] attribute. That means developers of this class had no intention to make it serializable (with BinaryFormatter). The fact it's parent class implements ISerializable and marked with [Serializable] does not change anything - child class might have it's own internal details which will be lost during serialization if it was allowed to serialize any descendant of serializable class.
If you want to use BinaryFormatter (which might or might not be the best way) - you can do it like this:
BinaryFormatter formatter = new BinaryFormatter();
//Serialize
string serialized;
using (MemoryStream stream = new MemoryStream())
{
// pass FormCollection to constructor of new NameValueCollection
// that way we kind of convert it to NameValueCollection which is serializable
// of course we lost any FormCollection-specific details (if there were any)
formatter.Serialize(stream, new NameValueCollection(data));
serialized = Convert.ToBase64String(stream.ToArray());
};
//Deserialize
using (MemoryStream stream = new MemoryStream(Convert.FromBase64String(serialized))) {
// deserialize as NameValueCollection then create new
// FormCollection from that
data = new FormCollection((NameValueCollection) formatter.Deserialize(stream));
}
I have a class that I want to construct, by deserializing it from a network stream.
public Anfrage(byte[] dis)
{
XmlSerializer deser = new XmlSerializer(typeof(Anfrage));
Stream str = new MemoryStream();
str.Write(dis, 0, dis.Length);
this = (Anfrage)deser.Deserialize(str);
}
The intention is that I just want to pass the byte[] and have a proper object, rather than using a method in another class.
Now, I know that I obviously cannot do this =.
I've read this question and currently am reading the article mentioned in it, but I am not sure wether I'm understanding it correctly.
Is my intention clear enough?
Is there a way to do what I want to get done here?
Thank you all.
You cannot overwrite an object within the class itself by assigning to this.
You can for example create a method that returns a new instance:
public static Anfrage Create(byte[] dis)
{
XmlSerializer deser = new XmlSerializer(typeof(Anfrage));
Stream str = new MemoryStream();
str.Write(dis, 0, dis.Length);
return (Anfrage)deser.Deserialize(str);
}
Then you can instantiate one like this:
var anfrage = Anfrage.Create(bytes);
Usually with this problem is dealt with a static non-constructor function returning the Object.
public static Anfrage Create(byte[] dis)
{
XmlSerializer deser = new XmlSerializer(typeof(Anfrage));
Stream str = new MemoryStream();
str.Write(dis, 0, dis.Length);
return (Anfrage)deser.Deserialize(str);
}
if you want to have a new object and edit it, make the constructor private instead of public and acces it with you static construction function
I am experiencing difficulties successfully deserializing a byte array that had been serialized with a pre-compiled protobuff serializer class ModelSerializer. Using this, the serialization and deserialization of classes within my defined data model MyData works when I serialize to a file and deserialize from the file to MyData.
However, I have another requirement, which is to serialize MyData to a byte array, and deserialize the byte array to MyData. Below is the basic class called MyDataConverter that has 2 static methods, one to convert MyData to the byte array and the other to convert a byte array to MyData.
I could serialize MyData to a byte array successfully and write it onto a MemoryStream. However, when I deserialize the byte array, I do get a non-null instance of MyData, but all the data in it is lost (zero default, or null values for custom types).
Could I have gone wrong here? Note that I did use similar code to successfully serialize to a file and deserialize from a file, so it probably isnt something wrong with MyModel nor the pre compiled ModelSerializer. But I could paste some of that info here if necessary.
public class MyDataConverter
{
public static byte [] MyDataToBytes (MyData myData)
{
MemoryStream stream = new MemoryStream();
ModelSerializer serializer = new ModelSerializer();
serializer.Serialize (stream, myData);
byte [] bytes = stream.ToArray();
Stream.Close();
return bytes;
}
public static MyData BytesToMyData (byte [] bytes)
{
MyData myData = null;
MemoryStream stream = new MemoryStream();
stream.Write (bytes, 0, bytes.Length);
ModelSerializer serializer = new ModelSerializer();
myData = (MyData) serializer.Deserialize (stream, myData, typeof (MyData));
stream.Close();
return myData;
}
}
This is the problem:
MemoryStream stream = new MemoryStream();
stream.Write (bytes, 0, bytes.Length);
ModelSerializer serializer = new ModelSerializer();
myData = (MyData) serializer.Deserialize (stream, myData, typeof (MyData));
When you try to deserialize, you're still at the end of the stream. You could just seek to the beginning afterwards, but it would be simpler to change the code to pass the byte array to the constructor:
MemoryStream stream = new MemoryStream(bytes, false);
ModelSerializer serializer = new ModelSerializer();
myData = (MyData) serializer.Deserialize (stream, myData, typeof (MyData));
Can we pass a list of object like List as an input to serialiser.
Is it possible to save a variable from C# to disk so that you are able to use it later in another instance of your project?
For example, I have a struct with 3 fields like in the following example :
struct MyStruct
{
byte[] ByteData;
int MyInt;
double MyDouble;
};
I have an instance of this struct, let's say MyStruct S and I assign value to all my fields.
After this step, I would like to save this variable somehow in disk so that I could use those stored values later in my program.
I know, that I could copy those value on a .txt file, but I would like to save the variable as it is on my disk so that I could directly load it into memory during the next runtime of my project.
Is it possible to save it somehow on the disk so that I could load it inside my program as it is?
public void SerializeObject<T>(string filename, T obj)
{
Stream stream = File.Open(filename, FileMode.Create);
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(stream, obj);
stream.Close();
}
public T DeSerializeObject<T> (string filename)
{
T objectToBeDeSerialized;
Stream stream = File.Open(filename, FileMode.Open);
BinaryFormatter binaryFormatter = new BinaryFormatter();
objectToBeDeSerialized= (T)binaryFormatter.Deserialize(stream);
stream.Close();
return objectToBeDeSerialized;
}
[Serializable]
struct MyStruct
{
byte[] ByteData;
int MyInt;
double MyDouble;
}
Do not forget to mark your object as serializable.
You could use serialization, check this MSDN link, Serialization.
The default serialization options is binary and XML.
Serialize it: http://msdn.microsoft.com/en-us/library/et91as27.aspx
When I am deserializing my object back to it's original type my object is always null.
Here is my code:
ProjectSetup obj = new ProjectSetup();
if (System.Web.HttpContext.Current.Session["ProjectSetup"] == null)
setBookProjectSetup();
string toDeserialise = System.Web.HttpContext.Current.
Session["ProjectSetup"].ToString();
DataContractSerializer dcs = new DataContractSerializer(typeof(ProjectSetup));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(toDeserialise));
obj = (ProjectSetup) dcs.ReadObject(ms, true);
return obj;
I'm going to assume that the call to setBookProjectSetup places an instance of ProjectSetup in the HttpSessionState with a key of ProjectSetup.
The issue here starts with this:
string toDeserialise = System.Web.HttpContext.Current.
Session["ProjectSetup"].ToString();
You subsequently use the contents of the toDeserialize string as the source of the deserialization.
Unless you've overloaded ToString to return a byte stream that the DataContractSerializer would be able to deserialize (it's highly unlikely) chances are you are using the implementation of ToString on Object, which will just return the type's name.
Then, you are trying to deserialize that string into your object, which isn't going to work.
What you need to do is properly serialize your object into a byte array/MemoryStream, like so:
using (var ms = new MemoryStream())
{
// Create the serializer.
var dcs = new DataContractSerializer(typeof(ProjectSetup));
// Serialize to the stream.
dcs.WriteObject(ms, System.Web.HttpContext.Current.Session["ProjectSetup"]);
At this point, the MemoryStream will be populated with a series of bytes representing your serialized object. You can then get the object back using the same MemoryStream:
// Reset the position of the stream so the read occurs in the right place.
ms.Position = 0;
// Read the object.
var obj = (ProjectSetup) dcs.ReadObject(ms);
}