Convert Any Object to a Byte[]

Convert any object to a byte[]

Use the BinaryFormatter:

byte[] ObjectToByteArray(object obj)
{
if(obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj);
return ms.ToArray();
}
}

Note that obj and any properties/fields within obj (and so-on for all of their properties/fields) will all need to be tagged with the Serializable attribute to successfully be serialized with this.

How to convert any object to a byte array and keep it on memory?

I'm adding this as an actual answer since it seemed to address your needs. Your use of pickle.dump is the problem since it is designed to take the serialized object and write it to a file (though as pointed out in other answers, it doesn't necessarily have to, but that's beside the point).

The function you want to be using is pickle.dumps, which returns the serialized object directly as a byte array:

someobject = 123
someobject_bytes = pickle.dumps(someobject)

Convert class object to bytes and create object from bytes

Ok this maybe what your looking for

The assumptions gleaned from your comments and updates are as follows

  • You want a generic way to serialize your classes (messages)
  • You want to be able to use this over the wire (sockets, not wcf)
  • It conforms to a socket regime
  • You want some basic protection against corruption
  • you want it easy to use

Note : there maybe many areas here which can be improved, however this is just to give you some ideas

If your using something like webservices this entire answer is null and void, this is really only a adhock method of serialization suitable for sockets

Overview

The Package class has some methods for the following

  • Able to serialize objects to bytes
  • Able to deserialize bytes to objects
  • Can create packages with header information
  • Header contains your message type (Option)
  • The length of the entire package
  • Some basic check summing and markers, in case of corruptions you can validate a package

So given the following

Message Enum

// Some predefined messages
public enum MessageType : byte
{
MyClass,
MyOtherClass,
Message3,
Message4,

}

Some class you want to send over the wire

// a serilaizable class
// Make this as you like
[Serializable]
public class MyClass
{

public byte[] SomeArbitaryBytes { get; set; }
public string SomeArbitaryString { get; set; }
public int SomeArbitaryInt { get; set; }
public double SomeArbitaryDouble { get; set; }

public MyClass()
{

SomeArbitaryString = "hello";
SomeArbitaryInt = 7;
SomeArbitaryDouble = 98.1;
SomeArbitaryBytes = new byte[10];
for (var i = 0; i < SomeArbitaryBytes.Length; i++)
{
SomeArbitaryBytes[i] = (byte)i;
}
}
}

Package Class

public static class Package
{
// Method for basic checksum
private static byte GetBasicChecksum(this byte[] data)
{
byte sum = 0;
unchecked // Let overflow occur without exceptions
{
foreach (byte b in data)
{
sum += b;
}
}
return sum;
}

// Serialize to bytes (BinaryFormatter)
public static byte[] SerializeToBytes<T>(this T source)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, source);
return stream.ToArray();
}
}

// Deerialize from bytes (BinaryFormatter)
public static T DeserializeFromBytes<T>(this byte[] source)
{
using (var stream = new MemoryStream(source))
{
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}

// Check if we have enough data
// will throw if it detects a corruption (basic)
// return false if there isnt enough data to determine
// return true and length of the package if sucessfull
public static bool HasValidPackage(this Stream stream, out Int32 messageSize)
{
messageSize = -1;

if (stream.Length - stream.Position < sizeof(byte) * 2 + sizeof(Int32))
return false;

var stx = stream.ReadByte();

if (stx != 2)
throw new InvalidDataException("Invalid Package : STX Failed");

var packageLength = new byte[sizeof(Int32)];
stream.Read(packageLength, 0, sizeof(Int32));
messageSize = BitConverter.ToInt32(packageLength, 0) - sizeof(byte) * 3;
var checkSum = stream.ReadByte();

if (checkSum != packageLength.GetBasicChecksum())
throw new InvalidDataException("Invalid Package : CheckSum Failed");

return stream.Length >= messageSize;

}

// Pack the message
public static byte[] PackMessage<T>(this T source, MessageType messageType)
{
var buffer = source.SerializeToBytes();
var packageLength = BitConverter.GetBytes(buffer.Length + sizeof(byte) * 3);
using (var stream = new MemoryStream())
{
stream.WriteByte(2);
stream.Write(packageLength, 0, sizeof(Int32));
stream.WriteByte(packageLength.GetBasicChecksum());
stream.WriteByte((byte)messageType);
stream.Write(buffer, 0, buffer.Length);
stream.WriteByte(3);
return stream.ToArray();
}
}

// Unpack the message
public static MessageType UnPackMessage(this Stream stream, Int32 messageSize, out byte[] buffer)
{

var messageType = (MessageType)stream.ReadByte();
buffer = new byte[messageSize];
stream.Read(buffer, 0, buffer.Length);

var etx = stream.ReadByte();

if (etx != 3)
throw new InvalidDataException("Invalid Package : ETX Failed");

return messageType;
}

}

Client Side Code

// create your class 
var myClass = new MyClass();

// Create a package out of it
var bytes = myClass.PackMessage(MessageType.MyClass);

Server Side Code

// this is server side
using (var stream = new MemoryStream(bytes))
{
Int32 messageSize;

// if we have a valid package do stuff
// this loops until there isnt enough data for a package or empty
while (stream.HasValidPackage(out messageSize))
{

byte[] buffer;

switch (stream.UnPackMessage(messageSize, out buffer))
{
case MessageType.MyClass:
var myClassCopy = buffer.DeserializeFromBytes<MyClass>();
// do stuff with your class
break;
case MessageType.MyOtherClass:
break;
case MessageType.Message3:
break;
case MessageType.Message4:
break;
default:
throw new ArgumentOutOfRangeException();
}

}

// do something with the remaining bytes here, if any, i.e partial package

}

Converting from object to byte array and back in java

This should work, just cast the object to your class after receiving it from the serialize/deserialize function.

public static byte[] objToByte(TcpPacket tcpPacket) throws IOException {
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
ObjectOutputStream objStream = new ObjectOutputStream(byteStream);
objStream.writeObject(tcpPacket);

return byteStream.toByteArray();
}

public static Object byteToObj(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);
ObjectInputStream objStream = new ObjectInputStream(byteStream);

return objStream.readObject();
}

How to convert an Object into a byte array in Kotlin

The following is an object serializable class which is helpful to convert the object to bytes array and vice versa in Kotlin.

public class ObjectSerializer {
companion object {
public fun serialize(obj: Any?) : String {
if (obj == null) {
return ""
}

var baos = ByteArrayOutputStream()
var oos = ObjectOutputStream(baos)
oos.writeObject(obj)
oos.close()

return encodeBytes(baos.toByteArray())
}

public fun deserialize(str: String?) : Any? {
if (str == null || str.length() == 0) {
return null
}

var bais = ByteArrayInputStream(decodeBytes(str))
var ois = ObjectInputStream(bais)

return ois.readObject()
}

private fun encodeBytes(bytes: ByteArray) : String {
var buffer = StringBuffer()

for (byte in bytes) {
buffer.append(((byte.toInt() shr 4) and 0xF plus 'a').toChar())
buffer.append(((byte.toInt()) and 0xF plus 'a').toChar())
}

return buffer.toString()
}

private fun decodeBytes(str: String) : ByteArray {
var bytes = ByteArray(str.length() / 2)

for (i in 0..(str.length() - 1)) {
var c = str.charAt(i)
bytes.set(i / 2, ((c minus 'a').toInt() shl 4).toByte())

c = str.charAt(i + 1)
bytes.set(i / 2, (bytes.get(i / 2) + (c minus 'a')).toByte())
}

return bytes
}
}
}


Related Topics



Leave a reply



Submit