1

I want to deserialize a binary file that's made in C# in Visual Studio 2017.

One program(C#) serializes structs of different types of arrays and the other program(C#) deserializes the file. I wonder how to do the same job in Python.

// ClassTickStruct.dll
namespace ClassTickStruct
{
    [Serializable]
    public struct struct_tick
    {
        public uint[] arr_currentIndex;
        public string[] arr_currentType;
        public DateTime[] arr_currentTime;
 
        public struct_tick(byte size_index, byte size_type, byte size_time)
        {
            arr_currentIndex = new uint[size_index];
            arr_currentType = new string[size_type];
            arr_currentTime = new DateTime[size_time];
        }
    }
}
// How one program(C#) serializes structs
using (var fileStream = new FileStream(file.bin, FileMode.Append))
{
    var bFormatter = new BinaryFormatter();

    bFormatter.Serialize(fileStream, obj_struct);
}
// How the other program(C#) deserializes the file
List<struct_tick> list_read = new List<struct_tick>();
using (var fileStream = new FileStream("file.bin", FileMode.Open))
{
    var bFormatter = new BinaryFormatter();
    //bFormatter.Binder = new AllowAllAssemblyVersionsDeserializationBinder();

    while (fileStream.Position != fileStream.Length)
    {
        list_read.Add((struct_tick)bFormatter.Deserialize(fileStream));
    }
}

I referred to Is there a way to read C# serialized objects into Python? and tried DirtyLittleHelper's code, but an error occurs that says:

    data = serializer.Deserialize(reader)
System.Runtime.Serialization.SerializationException: 'tickReceiver, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' Assembly can't be found
   location: System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
   location: System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
   location: System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
   location: System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
   location: System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
   location: System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
   location: System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   location: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
   location: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)

I had the same Assembly can't be found error when the C# programs didn't share the dll of the struct. Then I just made a class library(dll) with the structure in it and made the programs refer to it and they worked without the error.

# the whole Python code to deserialize the file
import clr
import System
#requires pythonnet installed -> pip install pythonnet 
clr.AddReference(r"C:\Users\null\Desktop\RECEIVER\ClassTickStruct.dll")

from System.Runtime.Serialization.Formatters.Binary import BinaryFormatter
from System.IO import FileStream,FileMode,FileAccess,FileShare

filepath = "file.bin"
serializer = BinaryFormatter()
reader = FileStream(filepath, FileMode.Open, FileAccess.Read)
data = serializer.Deserialize(reader)

I think what's different is that it's (struct_tick)bFormatter.Deserialize(fileStream) in C# and it's just serializer.Deserialize(reader) in Python. Maybe it needs some job with the struct in the dll?

5
  • 1
    hi @maynull, why dont you serialize with "common format" instead of relying on C# [Serializable] attribute? json, xml, or fancy protobuf might help. Commented Nov 12, 2019 at 7:18
  • 2
    I think you'll be much better off using a language/framework-agnostic serialization format like XML or JSON or something like that. Getting things right in binary is a much much more complicated job than using a XML or JSON lib for data exchange. Commented Nov 12, 2019 at 7:19
  • When working with different frameworks it's better to use common formats like XML/JSon etc... or you can implement your own binary format if performance is an issue. Using BinaryFormatter is not a very good idea because you don't have control over it. Commented Nov 12, 2019 at 7:21
  • If you want binary serialization that is easy to use between different programming languages, you should look at protobuf. Commented Nov 12, 2019 at 7:35
  • @Bagus Tesa Thank you for your recommendation. The reason I prefer this way is that it's possible to append new structs of arrays to the same one local file over and over without reading the file and it's more efficient in terms of performance(as I know of). I looked at JSON, google protobuf and etc, but I couldn't find any documents or usages that deal with those options. Commented Nov 12, 2019 at 9:00

1 Answer 1

1

What I want to do is actually possible with protobuf.

// WRITE
using (var fileStream = new FileStream("file.bin", FileMode.Append))
{
    Serializer.Serialize(fileStream, OBJ_struct);
}

// READ
using (var fileStream = new FileStream("file.bin", FileMode.Open))
{
    struct_obj str = Serializer.Deserialize<struct_obj >(fileStream);

    for (int num=0;  num < str.arr_currentIndex.Length; num++)
    {
        listBox1.Items.Add(str.arr_currentIndex[num]);
    }

}

Thank you those who recommended protobuf!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.