Problem in serializing - c#

Presently I need to serialize one of my object which contains more my own classes object.
But the problem is I dont want to save it in a file and then retrieve it into memory stream.
Is there any way to directly serialize my object into stream.
I used BinaryFormatter for seializing.
First I used a MemoryStream directly to take serialize output but it is giving error
at time of deserialization. But later when I serialize it with a file then close it and
again reopen it , it works perfectly. But I want to take it direct into stream because
in my program I need to do it frequently to pass it into network client. And using file
repeatedly might slow down my software.
Hope I clear my problem. Any Sugetion ?

If you're trying to deserialize from the same MemoryStream, have you remembered to seek back to the beginning of the stream first?
var foo = "foo";
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
// Serialize.
formatter.Serialize(stream, foo);
// Deserialize.
stream.Seek(0, SeekOrigin.Begin);
foo = formatter.Deserialize(stream) as string;
}

Here's a quick and dirty sample, of serializing back and forth a string. Is this what your trying to do?
static void Main(string[] args)
{
var str = "Hello World";
var stream = Serialize(str);
stream.Position = 0;
var str2 = DeSerialize(stream);
Console.WriteLine(str2);
Console.ReadLine();
}
public static object DeSerialize(MemoryStream stream)
{
BinaryFormatter formatter = new BinaryFormatter();
return formatter.Deserialize(stream);
}
public static MemoryStream Serialize(object data)
{
MemoryStream streamMemory = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(streamMemory, data);
return streamMemory;
}

Related

Understanding saving - do I only use Stream, or use both Formatter and Stream?

From what I understand, the Formatter converts a serializable object into a stream of bytes and the Stream (e.g. FileStream) does the actual writing of those bytes into a file. Example code:
public static void SaveData(MySerializableData data)
{
BinaryFormatter formatter = new BinaryFormatter();
FileStream stream = new FileStream(SavePath, FileMode.Create);
formatter.Serialize(stream, data);
stream.Close();
}
However at other times, I'm also seeing this type of code:
void Save()
{
string data = "Value 1";
StreamWriter writer = new StreamWriter("MySaveFile.txt", true);
writer.Write(data);
}
Why is it that in the second case, we abandon the 2-step process of saving? Why do we sometimes use only StreamWriter, but at other times use both the formatter and a stream object?
Thank you!
BinaryFormatter serializes a class into a byte array and writes it to a stream. It's useful when you want to save/load classes with it's data. Serializtion stores metadata about the class graph that is storing.
StreamWriter is a stream that has specific functions to write a string into a file.
Consider this example:
MemoryStream mstr = new MemoryStream();
string datastr = "hello!";
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(mstr, datastr);
mstr.Seek(0, SeekOrigin.Begin);
string resultString = Encoding.ASCII.GetString(mstr.ToArray());
If you inspect resultString you will find that it contains something like this:
"\0\u0001\0\0\0????\u0001\0\0\0\0\0\0\0\u0006\u0001\0\0\0\u0006hello!\v"
Well, that's not what you would want to have in a text file, right? As you see serialization is not intended to store raw data but class instances.
Now check this:
MemoryStream mstr = new MemoryStream();
StreamWriter sw = new StreamWriter(mstr);
string datastr = "hello!";
sw.Write(datastr);
mstr.Seek(0, SeekOrigin.Begin);
sw.Close();
string resultString = Encoding.ASCII.GetString(mstr.ToArray());
If you now inspect resultString it will contain:
"hello!"
As you see it's very different, that's what you would expect in a text file.
You can also store raw binary data with a stream:
byte[] data = new byte[]{ 1,2,3,4 };
var fs = File.Create("out.dat"); //this creates a new file and creates a filestream
fs.Write(data, 0, data.Length);
fs.Close();
If you now inspect the file with a binary editor you will see it contains:
0x01, 0x02, 0x03, 0x04
There are many types of streams with different purposes (per example, the MemoryStream that I used in the examples, a binary stream that stores it's data into an array in memory) and a ton of classes that use streams for many things, in this case you have mixed the concepts of serialization and data storage using streams, those are two different things.

Binary Serialization in c#

I am trying to serialize a class object using binary serialization in C#. I have tried and everywhere all I can find that the serialized data goes to a file always in all the examples I have seen.
In my case, I have to store the serialized data in SQL. The following is an example of the method I have created.
//Serializing the List
public void Serialize(Employees emps, String filename)
{
//Create the stream to add object into it.
System.IO.Stream ms = File.OpenWrite(filename);
//Format the object as Binary
BinaryFormatter formatter = new BinaryFormatter();
//It serialize the employee object
formatter.Serialize(ms, emps);
ms.Flush();
ms.Close();
ms.Dispose();
}
How can I get the serialized data directly in a string variable? I don't want to use a file.
Please help.
The easiest way to represent a byte array as a string in C# is with base64 encoding. The below example shows how this would be achieved within your code.
public void Serialize(Employees emps, String filename)
{
//Create the stream to add object into it.
MemoryStream ms = new MemoryStream();
//Format the object as Binary
BinaryFormatter formatter = new BinaryFormatter();
//It serialize the employee object
formatter.Serialize(ms, emps);
// Your employees object serialised and converted to a string.
string encodedObject = Convert.ToBase64String(ms.ToArray());
ms.Close();
}
This creates the string encodedObject. To retrieve the byte array and your serialised object back from the string you will use the below code.
BinaryFormatter bf = new BinaryFormatter();
// Decode the string back to a byte array
byte[] decodedObject = Convert.FromBase64String(encodedObject);
// Create a memory stream and pass in the decoded byte array as the parameter
MemoryStream memoryStream = new MemoryStream(decodedObject);
// Deserialise byte array back to employees object.
Employees employees = bf.Deserialize(memoryStream);
Just use MemoryStream ms = new MemoryStream() instead of your file stream.
You can extract a byte[] for Storage to SQL after serializing by calling ms.ToArray().
And don't forget to put your Stream into a using-Statement, to guarantee correct disposal of the allocated resources.

Could XmlSerializer and MemoryStream return an array of 0 value bytes?

I have a method that saves an instance of my custom class to a file. One time I noticed that my application fails to start, because this file is filled with 0-value bytes (null characters). This has never happened before, it seemed to work just fine. Does anyone see something odd with this code? Something that can cause the serializer or the memory stream to return an array of zero values? Or should I suspect it's the work of another application?
private readonly XmlSerializer _serializer = new XmlSerializer(typeof(MySettings));
public void Save(MySettings config)
{
using (var stream = new MemoryStream())
{
_serializer.Serialize(stream, config);
byte[] binaryConfig = stream.ToArray();
File.WriteAllBytes(_configFilePath, binaryConfig);
}
}
Wouldn't it be simpler to use something like this?
XmlSerializer x = new XmlSerializer(typeof(MySettings));
using (FileStream stream = new FileStream(_configFilePath, FileMode.Create, FileAccess.Write))
{
x.Serialize(stream, config);
stream.Close();
}
The XML file should not contain any 0-bytes or nul characters, as your object is translated to XML text during serialization. You can simply open the XML file using a text editor to have a look at the file contents.

How can I persist a list of object between application launches

I need to persist a list of object between application launches per user basis; how can I do it?
The object is simple: 4 strings and one int.
Serialize the object to the users appdata directory or use the IsolatedStorage when you want to persist it and deserialize it when launching.
Easiest way is to just store them as user-scoped application settings
Then you can just access them via static properties
MyApplication.Properties.Settings.Default.StringOne = "herpaderp";
MyApplication.Properties.Settings.Default.Save();
Description
One way is to use BinaryFormatter to save a list of serializable objects to a binary file. You can use the SoapFormatter if you want a readable / editable file.
Sample
Here a class that makes it possible to save a list of serializable objects.
[Serializable]
public class BinareObjectList<T> : List<T>
{
public void LoadFromFile(string fileName)
{
if (!File.Exists(fileName))
throw new FileNotFoundException("File not found", fileName);
this.Clear();
try
{
IFormatter formatter = new BinaryFormatter();
// IFormatter formatter = new SoapFormatter();
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
List<T> list = (List<T>)formatter.Deserialize(stream);
foreach (T o in list)
this.Add(o);
stream.Close();
}
catch { }
}
public void SaveToFile(string fileName)
{
if (File.Exists(fileName))
File.Delete(fileName);
IFormatter formatter = new BinaryFormatter();
// IFormatter formatter = new SoapFormatter();
Stream stream = new FileStream(fileName, FileMode.CreateNew);
formatter.Serialize(stream, this);
stream.Close();
}
}
More Information:
MSDN: BinaryFormatter Class
MSDN: SoapFormatter Class
Update
You said in a comment that you try to save application settings. Consider using Application Settings.
MSDN: Using Settings in C#
I would vote for Isolated Storage.

Serialization in .NET

My task was to serialize and deserialize an object.
I want to know:
Whether my object is serialized in the way I'm doing it
How I get to know that my object is being serialized or deserialized
Instead of passing the object in the Serialize Method, I am passing object.properties. Does this affect it in any way?
FileStream fs = new FileStream(#"D:\Rough Work\Serialization\Serialization\bin\Debug\Log.txt",FileMode.OpenOrCreate);
Laptop obj = new Laptop();
obj.Model = 2;
obj.SerialNumber = 4;
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, obj.Model);
formatter.Serialize(fs, obj.SerialNumber);
[Serializable]
class Laptop
{
public int Model;
public int SerialNumber;
}
If you can successfully deserialize an object then you serialized it correctly.
You don't need to serialize the properties individually. You can just serialize the entire object and deserialize it the same way.
using (var fs = new FileStream(#"D:\Rough Work\Serialization\Serialization\bin\Debug\Log.txt",FileMode.OpenOrCreate))
{
var formatter = new BinaryFormatter();
formatter.Serialize(fs, obj);
}
using (var fs = new FileStream(#"D:\Rough Work\Serialization\Serialization\bin\Debug\Log.txt",FileMode.OpenOrCreate))
{
var formatter = new BinaryFormatter();
obj = formatter.Deserialize(fs) as Laptop;
}
If your question is how would Laptop class know that it is being serialized then you might want to implement ISerializable interface.
See BinaryFormatter.Deserialize
You can convert to serialised method to a string and output it to the debug window
I want to know:
Whether my object is serialized in the way I'm doing it
Then you can use xml serialization, that way you can check your serialized object since it will be in human-readable form.

Categories

Resources