I have an android client that communicates with .net web service.
objToFormat is a List of my custom type.
public static byte[] ToByteArray(object objToFormat)
{
try
{
if (objToFormat == null) return null;
MemoryStream stream = new MemoryStream();
GZipStream zipped = new GZipStream(stream, CompressionMode.Compress, true);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(zipped, objToFormat);
zipped.Close();
zipped.Dispose();
return (stream.GetBuffer());
}
}
In my Android client i use the ksoap2 library and i receive the serialized string from the web service.
this is my android code :
byte[] decoded = Base64.decode(response, Base64.DEFAULT);
Object res = deserializeObject(decoded);
how do i deserialize the object ?
Thank you
You need to use a file stream to deserialize the object. The example below uses a Hashtable to save the deserialized content:
// Declare the hashtable reference.
Hashtable responseFromWebService = null;
// Open the file containing the data that you want to deserialize.
FileStream fs = new FileStream("DataFile.dat", FileMode.Open);
try
{
BinaryFormatter formatter = new BinaryFormatter();
// Deserialize the hashtable from the file and
// assign the reference to the local variable.
responseFromWebService = (Hashtable) formatter.Deserialize(fs);
}
catch (SerializationException e)
{
Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
throw;
}
finally
{
fs.Close();
}
You can find the MSDN documentation on Deserialization here:
https://msdn.microsoft.com/en-us/library/system.runtime.serialization.iformatter.deserialize(v=vs.110).aspx
EDIT in response to new information about it needing to be in Java
Your class needs has to have implements Serializable unless you're using an ArrayList object (or similar) which already implements this.
You also need to cast it back to what the object was (for example, the above hashtable)
Usage:
Hashtable deserializedData = (Hashtable) deserializeObject(someBytes)
public static Hashtable deserializeObject(byte[] b)
{
try
{
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(b));
Hashtable htable = in.readObject();
in.close();
return htable;
}
catch(ClassNotFoundException cnfe)
{
Log.e("deserializeObject", "class not found error", cnfe);
return null;
}
catch(IOException ioe)
{
Log.e("deserializeObject", "io error", ioe);
return null;
}
}
Related
I want to run a program that saves object by serializing it to a bin file.
The problem is, when I serialize one object to a new file, I can't add to the same file same object without erasing it.
Is there any method to serialize objects with the same type one by one, and then deserialized a list of the object?
this is the object saving:
static void Main(string[] args)
{
UserHandler.saveUser("or kandabi", "2133", "board 1");
UserHandler.saveUser("dana waizer", "21343", "board 2");
UserHandler.saveUser("elad", "4353", "board 3");
}
this is the methods for saving the object
public static void saveUser(String userName,String password,String boardId)
{
DalUser u = new DalUser(userName, password, boardId);
if (!File.Exists("userData.bin"))
{
Stream myFileStream = File.Create("userData.bin");
BinaryFormatter serializes = new BinaryFormatter();
serializes.Serialize(myFileStream, u);
myFileStream.Close();
}
else
{
Stream myFileStream = File.OpenRead("userData.bin");
BinaryFormatter serializes = new BinaryFormatter();
serializes.Serialize(myFileStream, u);
myFileStream.Close();
}
}
I expected that the data whould saved in the same "userData.bin" file, but there was an exception that the stream could not be opened for writing.
Use FileStream and FileMode.Append. Then you are able to add any object to your file and later you can read them as a list. Change your code to the following:
public static void saveUser(String userName, String password, String boardId)
{
DalUser u = new DalUser(userName, password, boardId);
using (var fileStream = new FileStream("userData.bin", FileMode.Append))
{
var bFormatter = new BinaryFormatter();
bFormatter.Serialize(fileStream, u);
}
}
public static List<DalUser> readUsers()
{
if (!File.Exists("userData.bin"))
return null;
var list = new List<DalUser>();
using (var fileStream = new FileStream("userData.bin", FileMode.Open))
{
var bFormatter = new BinaryFormatter();
while (fileStream.Position != fileStream.Length)
{
list.Add((DalUser)bFormatter.Deserialize(fileStream));
}
}
return list;
}
I want to deserialize encrypted objects (multiple instances of the same object type) from a file, that were added during execution of a program. The objects were encrypted using CryptoStream.
However, when deserializing i cannot loop through cryptoStream as I intended.
I can serialize and encrypt the objects and the file grows with every object added.
I can also deserialize the first encrypted object. However, following objects cannot be restored.
I have tried different approaches to loop though the stream. Also I tried other cryptostreams and working around that problem.
Serializing:
private void EncryptObjectToFile(TraceMessage pMessage, FileInfo pFileInfo)
{
if (pFileInfo == null) { pFileInfo = m_LogFile; }
m_Formatter.Serialize(m_SerializedStream, pMessage);
m_SerializedStream.Position = 0;
using (FileStream logfile = new FileStream(m_LogFile.FullName, FileMode.Append))
{
using (CryptoStream cryptoStream = new CryptoStream(logfile, m_Algorythm.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
cryptoStream.Write(m_SerializedStream.ToArray(), 0, (int)m_SerializedStream.Length);
cryptoStream.FlushFinalBlock();
}
}
}
Deserializing:
private List<TraceMessage> DecryptObjectsFromFile(FileInfo pFileInfo)
{
List<TraceMessage> tmp = new List<TraceMessage>();
try
{
READWRITELOCK.AcquireReaderLock(READERTIMEOUTS);
Interlocked.Increment(ref READS);
try
{
if (pFileInfo == null) { pFileInfo = m_LogFile; }
m_SerializedStream.Position = 0;
using (FileStream logfile = new FileStream(m_LogFile.FullName, FileMode.Open))
{
using (var cryptoStream = new CryptoStream(logfile, m_Algorythm.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
if (cryptoStream.CanRead)
{
while (cryptoStream.Position < cryptoStream.Length)
{
tmp.Add((TraceMessage)m_Formatter.Deserialize(cryptoStream));
}
}
}
}
}
catch(Exception exp) { }
finally
{
READWRITELOCK.ReleaseReaderLock();
Interlocked.Decrement(ref READS);
}
}
catch (Exception) { }
return tmp;
}
In the end what i am trying to achieve is, to encrypt objects (multiple instances of the same object type) and add them to a file. As files can be added any time and cannot be collected in a list and then written to file, I want to add those objects to an already existing file.
Later I want to recreate each object that was encrypted and serialized to the file.
I have a class that serializes and deserializes objects for a given type. I am trying to serialize a Custom file object containing the file name, the data in the file and a few other details like created time, modified time etc associated with the file. Additionally the custome class includes some properties or flags I would need at my receiver end (where I deserialize).
When I try to serialize around 30K of such file objects, it does the serialization successfully for a large majority, but throws back an outofmemoryexception for some files.
Below is my serialization class code:
public static string SerializeToByteArray(Type T, object request)
{
DataContractSerializer serializer = new DataContractSerializer(T);
using (MemoryStream memStream = new MemoryStream())
{
using (StreamReader reader = new StreamReader(memStream))
{
serializer.WriteObject(memStream, request);
memStream.Position = 0;
return reader.ReadToEnd();
}
}
}
public static T DeserializeFromByteArray<T>(string xml)
{
DataContractSerializer deserializer = new DataContractSerializer(typeof(T));
using (MemoryStream memStream = new MemoryStream())
{
byte[] data = System.Text.Encoding.UTF8.GetBytes(xml);
memStream.Write(data, 0, data.Length);
memStream.Position = 0;
var newobj = (T)deserializer.ReadObject(memStream);
return newobj;
}
}
I have a Streaming WCF service. It receives a stream of a serialized class called ContentObjectData. The bytes I receive in from the stream I have temporarily placed in an ArrayList as I don't know how big the Stream is and to be honest I don't know what to do with them anyway.
The ContentObjectData Class:
[Serializable]
public class ContentObjectData
{
string Hash { get; set; }
string Data { get; set; }
string FileName { get; set; }
string DisplayImage { get; set; }
}
This is the Service's Method that receives the stream from the client.
[OperationContract]
public void SendContentObject(Stream data)
{
ArrayList alBytes = new ArrayList();
Console.WriteLine("Client connected");
int count;
byte[] buffer = new byte[4096];
while ((count = data.Read(buffer, 0, buffer.Length)) > 0)
{
alBytes.AddRange(buffer);
}
long i = alBytes.Count;
data.Close();
}
At this moment in time I am sending an Image for testing using the following methods:
private void btnLoadImage_Click(object sender, EventArgs e)
{
DialogResult dr = OFD.ShowDialog();
if (dr == DialogResult.OK)
{
foreach (string filename in OFD.FileNames)
{
try
{
ContentObject co = new ContentObject();
co.Data = LoadFile(filename);
co.Hash = Hashing.HashString(co.Data);
co.DisplayImage = co.Data;
co.FileName = co.Hash;
Stream stream = SerializeToStream(co);
SendContentObject(stream);
}
catch (Exception ex)
{
throw ex;
}
}
}
}
private void SendContentObject(Stream stream)
{
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None, false);
// TimeSpan.MaxValue is interpreted with a rounding error, so use 24 days instead
binding.SendTimeout = TimeSpan.FromDays(24);
binding.TransferMode = TransferMode.Streamed;
ChannelFactory<RaptorStreamingHost> factory = new ChannelFactory<RaptorStreamingHost>(
binding, new EndpointAddress("net.tcp://ccs-labs.com:804/"));
RaptorStreamingHost service = factory.CreateChannel();
service.SendContentObject(stream);
((IClientChannel)service).Close();
}
private string LoadFile(string filename)
{
return Hashing.BytesToString(File.ReadAllBytes(filename));
}
public static Stream SerializeToStream(object objectType)
{
MemoryStream stream = new MemoryStream();
IFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, objectType);
stream.Position = 0L; // REMEMBER to reset stream or WCF will just send the stream from the end resulting in an empty stream!
return (Stream)stream;
}
I have this to DeSerialize but it doesn't make much sense to me:
public static object DeserializeFromStream(MemoryStream stream)
{
IFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
object objectType = formatter.Deserialize(stream);
return objectType;
}
How do I convert the ArrayList of Bytes (I guess DeSerialize them) into a New ContentObject?
Update One
Ah So close!
Ok in this method
public static ContentObjectData DeserializeFromStream(MemoryStream stream)
{
IFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
ContentObjectData objectType = (ContentObjectData)formatter.Deserialize(stream);
return objectType;
}
I have a problem. The Deserializer can not find the ContentObjectData because it is looking in the client's Namespace for ContentObjectData and not this Host's namespace.
Firstly, don't use an ArrayList to store your bytes. Since ArrayList is non-generic each individual byte will be boxed and a pointer to the byte saved in the array, which will use 5 (32 bit) or 9 (64 bit) times more memory than necessary.
Instead, you can copy the Stream to a local MemoryStream, then save the underlying byte [] array:
public static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[32768];
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, read);
}
}
[OperationContract]
public void SendContentObject(Stream data)
{
Console.WriteLine("Client connected");
var memoryStream = new MemoryStream();
using (data)
CopyStream(data, memoryStream);
byte [] alBytes = memoryStream.ToArray();
}
Then later you can turn the byte [] array back to a MemoryStream for deserialization:
public static object DeserializeFromStream(byte [] allBytes)
{
using (var stream = new MemoryStream(allBytes))
return DeserializeFromStream(stream);
}
public static object DeserializeFromStream(MemoryStream stream)
{
IFormatter formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
object objectType = formatter.Deserialize(stream);
return objectType;
}
(Or, just keep the original MemoryStream and pass it around.)
Update
BinaryFormatter serializes full .Net type information (i.e. the fully qualified type name) to and from the serialization stream. If the receiving system doesn't have a type with exactly the same name, in exactly the same namespace, in exactly the same assembly, then deserialization fails.
If this is your situation, you have the following workarounds:
Extract a shared DLL containing the type in question and link it into both client and server; problem solved.
Write a SerializationBinder to map the type assemblies and names. See here and also here or here for instructions how to do it.
Consider a different, more contract-oriented binary format. Bson is one option. protobuf-net is another, albeit one I have not used. More here.
I am new to stocks in C#, I wish to send a Object in C#. Have been using BinaryWriter to send data (works fine for string), but it doesn't seem to have a method like
writer.Writer(new SerliaizedObject());
How do we achieve this using BinaryReader/BinaryWriter
UPDATE:
I used the following functions to convert by object to byte and send it across to the client
public static byte[] SerializeToBytes<T>(T item)
{
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, item);
stream.Seek(0, SeekOrigin.Begin);
return stream.ToArray();
}
}
public static object DeserializeFromBytes(byte[] bytes)
{
var formatter = new BinaryFormatter();
using (var stream = new MemoryStream(bytes))
{
return formatter.Deserialize(stream);
}
}
To send the data is used:
formatter = new BinaryFormatter();
MessageBox.Show(SerializeToBytes<mydata>(new mydata()).Length+"");
writer.Write(SerializeToBytes<mydata>(new mydata()));
ChatBox.AppendText("Client Says :" + UserMessage.Text + "\r\n");
And to read the data I used:
while (true)
{
byte[] bytes = reader.ReadBytes(120);
mydata temp = DeserializeFromBytes(bytes) as mydata;
ChatBox.AppendText("Server Says " + temp + "\r\n");
}
But the reader doesn't seem to work, Any Ideas?
Use BinaryFormatter to write serializable objects to streams in binary format:
FileStream fs = new FileStream("DataFile.dat", FileMode.Create);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(fs, mySerializable);
You should use the first 4 bytes as length header, and in the receive loop you add a variable bytesReadSoFar. Then you know when everything is received.