簡體   English   中英

如何反序列化 Python 中的序列化 C# 二進制文件?

[英]How to deserialize a serialized C# binary file in Python?

我想反序列化在 Visual Studio 2017 中的 C# 中創建的二進制文件。

一個程序(C#)序列化不同類型的arraysstructs ,另一個程序(C#)反序列化文件。 我想知道如何在 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));
    }
}

我提到了Is there a way to read C# serialized objects into Python? 並嘗試了 DirtyLittleHelper 的代碼,但出現錯誤:

    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)

當 C# 程序不共享結構的 dll 時,我遇到了相同的Assembly can't be found錯誤。 然后我剛剛制作了一個 class 庫(dll),其中包含結構並讓程序引用它,並且它們可以正常工作。

# 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)

我認為不同的是它是 C# 中的(struct_tick)bFormatter.Deserialize(fileStream)而它只是 Python 中的serializer.Deserialize(reader) 也許它需要對 dll 中的結構進行一些工作?

我想要做的實際上可以使用 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]);
    }

}

謝謝推薦protobuf的人!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM