编写一个二进制文件到c#结构体

本文关键字:二进制文件 结构体 一个 | 更新日期: 2023-09-27 18:07:21

所以,我读了很多相同的主题,但我无法找到解决方案。我做了一个进口商(二进制结构)代码使用c++,现在我想使闪亮的形式和转移我的代码正确。在这种情况下,c#与c++有很大的不同,所以我不得不重做很多东西,而且还有更多的东西要做。下面是我的c++代码:

#include "stdafx.h"
#include "half.h"
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;
using half_float::half;
#pragma pack(push, 1)
struct Group {
    uint8_t Name[32];
};
struct WeaponBonesData {
    uint8_t WeaponBoneName[32];
    uint8_t Unknown5[48];
    uint32_t WeaponBoneID;
};
struct TexturesData {
    uint32_t TextureType;
    uint8_t TextureName[256];
};
struct Shader {
    float DetailTileU;
    uint32_t Unknown7;
    float DetailTileV;
    uint32_t Unknown8;
    uint32_t DirtTileU;
    uint32_t Unknown9;
    uint32_t DirtTileV;
    uint32_t Unknown10;
};
struct VertexData {
    half X;
    half Y;
    half Z;
    half Sep1;
    bool bone0;
    bool bone1;
    bool weight;
    bool Sep2;
    bool normX;
    bool normY;
    bool normZ;
    bool Sep3;
    half U;
    half V;
    uint32_t Unknown11[2];
};
struct IndexData {
    uint16_t ind1;
    uint16_t ind2;
    uint16_t ind3;
};
struct Geometry {
    vector<VertexData> Vertices;
    vector<IndexData> Indices;
};
struct rigid_model {
    uint32_t rigid_material_ID;
    vector<uint32_t> LodSize;
    vector<uint32_t> LodVerticesOffset;
    vector<uint32_t> VerticesCount;
    vector<uint32_t> LodIndicesOffset;
    vector<uint32_t> IndicesCount;
    vector<float> GroupMinX;
    vector<float> GroupMinY;
    vector<float> GroupMinZ;
    vector<float> GroupMaxX;
    vector<float> GroupMaxY;
    vector<float> GroupMaxZ;
    uint8_t ShaderMaterial[12];
    uint8_t Unknown1[20];
    uint16_t Unknown2;
    vector<Group> GroupName;
    uint8_t TexturesDir[256];
    uint8_t Unknown3[422];
    uint32_t WeaponBonesCount;
    uint32_t TexturesCount;
    uint8_t Unknown4[140];
    WeaponBonesData WeaponBones[5];
    vector<TexturesData> TexData;
    uint32_t NullMask;
    Shader ShaderParams;
    uint32_t AlphaMode;
    vector<Geometry>  Mesh;
};
struct RMV2 {
    uint8_t Signature[4];
    uint32_t ModelType;
    uint32_t LodsCount;
    uint8_t SkeletonName[128];
    vector<uint32_t> GroupsCount;
    vector<uint32_t> VDCount;
    vector<uint32_t> IDCount;
    vector<uint32_t> StartOffset;
    vector<float> ZoomFactor;
    vector<rigid_model> lod;
};
#pragma pack(pop)
ostream& operator<<(ostream& os, const WeaponBonesData& WBD) {
    return os << WBD.WeaponBoneName << WBD.Unknown5 << WBD.WeaponBoneID;
}
ostream& operator<<(ostream& os, const Group& g) {
    return os << g.Name;
}
void read(RMV2 &rmv2, char filename[128]) {
    ifstream model(filename, ios::in | ios::binary);
    if (model.fail()) {
        cout << "ERROR! Invalid file name" << endl;
        system("pause");
        exit(0);
    }
    model.read((char*)&rmv2, 140);
    rigid_model data;
    uint32_t temp;
    float temp2;
    TexturesData TD;
    VertexData vertex;
    IndexData index;
    Geometry geometry;
    Group group;
    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.GroupsCount.push_back(temp);
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.VDCount.push_back(temp);
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.IDCount.push_back(temp);
        model.read((char*)&temp, sizeof(uint32_t));
        rmv2.StartOffset.push_back(temp);
        model.read((char*)&temp2, sizeof(float));
        rmv2.ZoomFactor.push_back(temp2);
    }
    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        for (size_t j = 0; j < rmv2.GroupsCount[i]; j++) {
            model.read((char*)&data.rigid_material_ID, sizeof(data.rigid_material_ID));
            model.read((char*)&temp, sizeof(uint32_t));
            data.LodSize.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.LodVerticesOffset.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.VerticesCount.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.LodIndicesOffset.push_back(temp);
            model.read((char*)&temp, sizeof(uint32_t));
            data.IndicesCount.push_back(temp);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMinX.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMinY.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMinZ.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMaxX.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMaxY.push_back(temp2);
            model.read((char*)&temp2, sizeof(float));
            data.GroupMaxZ.push_back(temp2);
            model.read((char*)&data.ShaderMaterial, sizeof(data.ShaderMaterial));
            model.read((char*)&data.Unknown1, sizeof(data.Unknown1));
            model.read((char*)&data.Unknown2, sizeof(data.Unknown2));
            model.read((char*)&group, sizeof(group));
            data.GroupName.push_back(group);
            model.read((char*)&data.TexturesDir, sizeof(data.TexturesDir));
            model.read((char*)&data.Unknown3, sizeof(data.Unknown3));
            model.read((char*)&data.WeaponBonesCount, sizeof(data.WeaponBonesCount));
            model.read((char*)&data.TexturesCount, sizeof(data.TexturesCount));
            model.read((char*)&data.Unknown4, sizeof(data.Unknown4));
            for (size_t k = 0; k < data.WeaponBonesCount; k++) {
                model.read((char*)&data.WeaponBones[k].WeaponBoneName, sizeof(data.WeaponBones[k].WeaponBoneName));
                model.read((char*)&data.WeaponBones[k].Unknown5, sizeof(data.WeaponBones[k].Unknown5));
                model.read((char*)&data.WeaponBones[k].WeaponBoneID, sizeof(data.WeaponBones[k].WeaponBoneID));
            }
            for (size_t k = 0; k < data.TexturesCount; k++) {
                model.read((char*)&TD, sizeof(TD));
                data.TexData.push_back(TD);
            }
            model.read((char*)&data.NullMask, sizeof(data.NullMask));
            if (data.rigid_material_ID == 79) {
                model.read((char*)&data.ShaderParams.DetailTileU, sizeof(data.ShaderParams.DetailTileU));
                model.read((char*)&data.ShaderParams.Unknown7, sizeof(data.ShaderParams.Unknown7));
                model.read((char*)&data.ShaderParams.DetailTileV, sizeof(data.ShaderParams.DetailTileV));
                model.read((char*)&data.ShaderParams.Unknown8, sizeof(data.ShaderParams.Unknown8));
                model.read((char*)&data.ShaderParams.DirtTileU, sizeof(data.ShaderParams.DirtTileU));
                model.read((char*)&data.ShaderParams.Unknown9, sizeof(data.ShaderParams.Unknown9));
                model.read((char*)&data.ShaderParams.DirtTileV, sizeof(data.ShaderParams.DirtTileV));
                model.read((char*)&data.ShaderParams.Unknown10, sizeof(data.ShaderParams.Unknown10));
            }
            model.read((char*)&data.AlphaMode, sizeof(data.AlphaMode));
            for (size_t k = 0; k < data.VerticesCount[j]; k++) {
                model.read((char*)&vertex, sizeof(vertex));
                geometry.Vertices.push_back(vertex);
            }
            for (size_t k = 0; k < data.IndicesCount[j] / 3; k++) {
                model.read((char*)&index, sizeof(index));
                geometry.Indices.push_back(index);
            }
            data.Mesh.push_back(geometry);
            geometry = {};
        }
        rmv2.lod.push_back(data);
        data = {};
    }
    model.close();
}
void to_rmv2(RMV2 &rmv2, char filename[128]) {
    ofstream model(filename, ios::out | ios::binary);
    model.write((char*)&rmv2, 140);
    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        model.write((char*)&rmv2.GroupsCount[i], sizeof(uint32_t));
        model.write((char*)&rmv2.VDCount[i], sizeof(uint32_t));
        model.write((char*)&rmv2.IDCount[i], sizeof(uint32_t));
        model.write((char*)&rmv2.StartOffset[i], sizeof(uint32_t));
        model.write((char*)&rmv2.ZoomFactor[i], sizeof(float));
    }
    for (size_t i = 0; i < rmv2.LodsCount; i++) {
        for (size_t j = 0; j < rmv2.GroupsCount[i]; j++) {
            model.write((char*)&rmv2.lod[i].rigid_material_ID, sizeof(rmv2.lod[i].rigid_material_ID));
            model.write((char*)&rmv2.lod[i].LodSize[j], sizeof(rmv2.lod[i].LodSize[j]));
            model.write((char*)&rmv2.lod[i].LodVerticesOffset[j], sizeof(rmv2.lod[i].LodVerticesOffset[j]));
            model.write((char*)&rmv2.lod[i].VerticesCount[j], sizeof(rmv2.lod[i].VerticesCount[j]));
            model.write((char*)&rmv2.lod[i].LodIndicesOffset[j], sizeof(rmv2.lod[i].LodIndicesOffset[j]));
            model.write((char*)&rmv2.lod[i].IndicesCount[j], sizeof(rmv2.lod[i].IndicesCount[j]));
            model.write((char*)&rmv2.lod[i].GroupMinX[j], sizeof(rmv2.lod[i].GroupMinX[j]));
            model.write((char*)&rmv2.lod[i].GroupMinY[j], sizeof(rmv2.lod[i].GroupMinY[j]));
            model.write((char*)&rmv2.lod[i].GroupMinZ[j], sizeof(rmv2.lod[i].GroupMinZ[j]));
            model.write((char*)&rmv2.lod[i].GroupMaxX[j], sizeof(rmv2.lod[i].GroupMaxX[j]));
            model.write((char*)&rmv2.lod[i].GroupMaxY[j], sizeof(rmv2.lod[i].GroupMaxY[j]));
            model.write((char*)&rmv2.lod[i].GroupMaxZ[j], sizeof(rmv2.lod[i].GroupMaxZ[j]));
            model.write((char*)&rmv2.lod[i].ShaderMaterial, sizeof(rmv2.lod[i].ShaderMaterial));
            model.write((char*)&rmv2.lod[i].Unknown1, sizeof(rmv2.lod[i].Unknown1));
            model.write((char*)&rmv2.lod[i].Unknown2, sizeof(rmv2.lod[i].Unknown2));
            model.write((char*)&rmv2.lod[i].GroupName[j], sizeof(rmv2.lod[i].GroupName[j]));
            model.write((char*)&rmv2.lod[i].TexturesDir, sizeof(rmv2.lod[i].TexturesDir));
            model.write((char*)&rmv2.lod[i].Unknown3, sizeof(rmv2.lod[i].Unknown3));
            model.write((char*)&rmv2.lod[i].WeaponBonesCount, sizeof(rmv2.lod[i].WeaponBonesCount));
            model.write((char*)&rmv2.lod[i].TexturesCount, sizeof(rmv2.lod[i].TexturesCount));
            model.write((char*)&rmv2.lod[i].Unknown4, sizeof(rmv2.lod[i].Unknown4));
            for (size_t k = 0; k < rmv2.lod[i].WeaponBonesCount; k++) {
                model.write((char*)&rmv2.lod[i].WeaponBones[k], sizeof(rmv2.lod[i].WeaponBones[k]));
            }
            for (size_t k = 0; k < rmv2.lod[i].TexturesCount; k++) {
                model.write((char*)&rmv2.lod[i].TexData[k], sizeof(rmv2.lod[i].TexData[k]));
            }
            model.write((char*)&rmv2.lod[i].NullMask, sizeof(rmv2.lod[i].NullMask));
            if (rmv2.lod[i].rigid_material_ID == 79) {
                model.write((char*)&rmv2.lod[i].ShaderParams.DetailTileU, sizeof(rmv2.lod[i].ShaderParams.DetailTileU));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown7, sizeof(rmv2.lod[i].ShaderParams.Unknown7));
                model.write((char*)&rmv2.lod[i].ShaderParams.DetailTileV, sizeof(rmv2.lod[i].ShaderParams.DetailTileV));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown8, sizeof(rmv2.lod[i].ShaderParams.Unknown8));
                model.write((char*)&rmv2.lod[i].ShaderParams.DirtTileU, sizeof(rmv2.lod[i].ShaderParams.DirtTileU));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown9, sizeof(rmv2.lod[i].ShaderParams.Unknown9));
                model.write((char*)&rmv2.lod[i].ShaderParams.DirtTileV, sizeof(rmv2.lod[i].ShaderParams.DirtTileV));
                model.write((char*)&rmv2.lod[i].ShaderParams.Unknown10, sizeof(rmv2.lod[i].ShaderParams.Unknown10));
            }
            model.write((char*)&rmv2.lod[i].AlphaMode, sizeof(rmv2.lod[i].AlphaMode));
            for (size_t k = 0; k < rmv2.lod[i].VerticesCount[j]; k++) {
                model.write((char*)&rmv2.lod[i].Mesh[j].Vertices[k], sizeof(rmv2.lod[i].Mesh[j].Vertices[k]));
            }
            for (size_t k = 0; k < rmv2.lod[i].IndicesCount[j] / 3; k++) {
                model.write((char*)&rmv2.lod[i].Mesh[j].Indices[k], sizeof(rmv2.lod[i].Mesh[j].Indices[k]));
            }
        }
    }
    model.close();
}
struct DAE {
    vector<char> Signature;
};
void convert(RMV2 &rmv2, DAE &dae) {
//  dae.Signature[0] = "<?xml version='1.0' encoding='utf - 8'?>";
}
void to_dae(DAE &dae, char filename[128]) {
    ofstream model(filename, ios::out | ios::binary);
    model.write((char*)&dae, 140);
    model.close();
}
int main(int argc, char *argv[])
{
    RMV2 rmv2;
    DAE dae;
    char filename[128], daeFilename[128];
    cout << "Filename: ";
    gets_s(filename, sizeof(filename));
    strcpy_s(daeFilename, filename);
    strcat_s(filename, ".rigid_model_v2");
    strcat_s(daeFilename, ".dae");
    read(rmv2,  filename);
    convert(rmv2, dae);
    to_dae(dae, daeFilename);
//  to_rmv2(rmv2, daeFilename);
//  cout << rmv2.lod[0].Mesh[0].Vertices[0].X << endl;
    cout << "Successfully converted to .dae" << endl;
    system("pause");
    return 0;
}

这是我的c#尝试:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace RMV2Convertor
{
    public partial class ConvertorForm : Form
    {
        public ConvertorForm()
        {
            InitializeComponent();
        }
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct Group
        {
            public Group(int size = 32)
            {
                sbyte[] Name = new sbyte[size];
            }
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct WeaponBonesData
        {
            sbyte[] WeaponBoneName;
            sbyte[] Unknown5;
            uint WeaponBoneID;
            public WeaponBonesData(int size = 32)
            {
                WeaponBoneName = new sbyte[size];
                Unknown5 = new sbyte[48];
                WeaponBoneID = new uint();
            }
        }
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct TexturesData
        {
            uint TextureType;
            sbyte[] TextureName;
            public TexturesData(int size = 256)
            {
                TextureType = new uint();
                TextureName = new sbyte[size];
            }
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct Shader
        {
            float DetailTileU;
            uint Unknown7;
            float DetailTileV;
            uint Unknown8;
            uint DirtTileU;
            uint Unknown9;
            uint DirtTileV;
            uint Unknown10;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct VertexData
        {
            Half X;
            Half Y;
            Half Z;
            Half Sep1;
            bool bone0;
            bool bone1;
            bool weight;
            bool Sep2;
            bool normX;
            bool normY;
            bool normZ;
            bool Sep3;
            Half U;
            Half V;
            ulong Unknown11;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct IndexData
        {
            ushort ind1;
            ushort ind2;
            ushort ind3;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct Geometry
        {
            List<VertexData> Vertices;
            List<IndexData> Indices;
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct rigid_model
        {
            uint rigid_material_ID;
            List<uint> LodSize;
            List<uint> LodVerticesOffset;
            List<uint> VerticesCount;
            List<uint> LodIndicesOffset;
            List<uint> IndicesCount;
            List<float> GroupMinX;
            List<float> GroupMinY;
            List<float> GroupMinZ;
            List<float> GroupMaxX;
            List<float> GroupMaxY;
            List<float> GroupMaxZ;
            sbyte[] ShaderMaterial;
            sbyte[] Unknown1;
            ushort Unknown2;
            List<Group> GroupName;
            sbyte[] TexturesDir;
            sbyte[] Unknown3;
            uint WeaponBonesCount;
            uint TexturesCount;
            sbyte[] Unknown4;
            WeaponBonesData[] WeaponBones;
            List<TexturesData> TexData;
            uint NullMask;
            Shader ShaderParams;
            uint AlphaMode;
            List<Geometry> Mesh;
            public rigid_model(int size = 12)
            {
                rigid_material_ID = new uint();
                LodSize = new List<uint>();
                LodVerticesOffset = new List<uint>();
                VerticesCount = new List<uint>();
                LodIndicesOffset = new List<uint>();
                IndicesCount = new List<uint>();
                GroupMinX = new List<float>();
                GroupMinY = new List<float>();
                GroupMinZ = new List<float>();
                GroupMaxX = new List<float>();
                GroupMaxY = new List<float>();
                GroupMaxZ = new List<float>();
                ShaderMaterial = new sbyte[size];
                Unknown1 = new sbyte[20];
                Unknown2 = new ushort();
                GroupName = new List<Group>();
                TexturesDir = new sbyte[256];
                Unknown3 = new sbyte[422];
                WeaponBonesCount = new uint();
                TexturesCount = new uint();
                Unknown4 = new sbyte[140];
                WeaponBones = new WeaponBonesData[5];
                TexData = new List<TexturesData>();
                NullMask = new uint();
                ShaderParams = new Shader();
                AlphaMode = new uint();
                Mesh = new List<Geometry>();
            }
        };
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct RMV2
        {
            public char[] Signature;
            public uint ModelType;
            public uint LodsCount;
            public char[] SkeletonName;
            public List<uint> GroupsCount;
            public List<uint> VDCount;
            public List<uint> IDCount;
            public List<uint> StartOffset;
            public List<float> ZoomFactor;
            public List<rigid_model> lod;
            public RMV2(int size = 4)
            {
                Signature = new char[size];
                ModelType = new uint();
                LodsCount = new uint();
                SkeletonName = new char[128];
                GroupsCount = new List<uint>();
                VDCount = new List<uint>();
                IDCount = new List<uint>();
                StartOffset = new List<uint>();
                ZoomFactor = new List<float>();
                lod = new List<rigid_model>();
            }
        };
        void read(RMV2 rmv2, string filename)
        {
            using (BinaryReader model = new BinaryReader(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read), Encoding.ASCII))
            {
                rmv2.Signature = model.ReadChars(4);
            }
            MessageBox.Show(rmv2.Signature.ToString());
        }
        private void bOpenFileDialog_Click(object sender, EventArgs e)
        {
            Stream myStream = null;
            OpenFileDialog openFileDialog1 = new OpenFileDialog();
            openFileDialog1.InitialDirectory = "c:''";
            openFileDialog1.Filter = "rigid_model_v2 files (*.rigid_model_v2)|*.rigid_model_v2|All files (*.*)|*.*";
            openFileDialog1.FilterIndex = 1;
            openFileDialog1.RestoreDirectory = true;

            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    if ((myStream = openFileDialog1.OpenFile()) != null)
                    {
                        using (myStream)
                        {
                            RMV2 rmv2 = new RMV2();
                            string filename = openFileDialog1.FileName;
                            read(rmv2, filename);
                        }
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message);
                }
            }
        }
    }
}

所以最重要的问题我需要一个解决方案:如何读取二进制文件结构?

编写一个二进制文件到c#结构体

读取文件只需调用ReadAllBytes:

byte[] array = File.ReadAllBytes("file path");