Десериализация двоичных файлов с использованием PtrToStructure в C # - PullRequest
3 голосов
/ 23 ноября 2011

Я пытаюсь реконструировать кучу устаревших двоичных данных в моей компании, чтобы я мог перевести их в более надежный формат. Приложение, которое мы использовали для создания этих данных, больше не поддерживается.

Я выяснил, что я могу описать данные в серии структур, и я смог их перенести в управляемую среду с помощью Marshal.PtrToStructure, за исключением одного файла.

Ниже я привел образец структуры, которую я пытаюсь проанализировать. Все необработанные данные являются последовательными, и я пытаюсь десериализовать за один шаг.

[StructLayout(LayoutKind.Sequential, Pack = 1)]
struct DrillTPD
{
    public short Header;
    public short Header2;
    public short Header3;
    public short RecordCount;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 999)]
    public TPDHeader[] Templates;
} 
[StructLayout(LayoutKind.Sequential, Pack = 1, Size=18)]
struct TPDHeader
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string TemplateName;
    public int TPDIndex;
}

TPDIndex - это смещение в байтах от начала файла. Как я могу добавить свойство для правильной десериализации этих данных?

[StructLayout(LayoutKind.Sequential, Pack = 1, Size = 76)]
struct TPDParent
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
    public string TemplateName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 25)]
    public string Description;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string Field;
    public double Width;
    public double Length;
    public double Thickness;
    public short WL;
    public short XY;
    public short Origin;
    public short Features;
    [MarshalAs(UnmanagedType.ByValArray)]
    public TPDDetail[] Details;
}
[StructLayout(LayoutKind.Sequential, Pack=1, Size=350)]
struct TPDDetail
{
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 350)]
    public string Text;
}

Массив TPDDetail в TPDParent определяется компонентами в структуре. Если функции отсутствуют, данные TPDDetail отсутствуют после TPDParent.

Как динамически сообщить десериализатору размер массива TPDDetail?

Псевдо XML Структура этих данных в идеале будет выглядеть так:

<DrillTPD>
    <TPDHeader>
        <TPDParent>
            <TPDDetail/>
            <TPDDetail/>
            <TPDDetail/>
        </TPDParent>
    </TPDHeader>
    <TPDHeader>
        .....
    </TPDHeader>
</DrillTPD>

Последний комментарий: я когда-либо работал только на языках .NET, но я пытаюсь понять неуправляемую сторону вещей. Спасибо, что нашли ответы на свои вопросы. :)

Ответы [ 2 ]

0 голосов
/ 23 ноября 2011

Из моего pov лучше всего, если у вас есть два класса - один входной класс с неуправляемыми данными и второй класс только с управляемыми данными, у которого есть конструктор, принимающий входной класс в качестве параметра и помеченный соответствующим образом для сериализации - если вседанные управляются, тогда размер массива будет управляться фреймворком внутри.

0 голосов
/ 23 ноября 2011

Попробуйте создать простой экземпляр вашей структурной иерархии, а затем сохранить его в файле в виде байтов.Затем вы можете использовать шестнадцатеричный редактор, чтобы сравнить то, что у вас получилось, с тем, что, как вы думали, получится.Разница в том, что она не работает так, как вы ожидаете.

В противном случае вы пытаетесь создать идеальное определение ваших структур, и он откажется работать до тех пор, пока не станет идеальным, и этого будет довольно трудно достичьсложная настройка, как у вас.

...