在C#中将字节读入结构

Chr*_* D. 6 c# file-io struct

时间换另一个问题.我正在为我的小型3D引擎项目编写MD2加载程序.在我的旧语言(C)中,我可以定义一个结构,然后从打开的文件中直接读取()到结构中.我有一个结构来保存MD2文件中的标题信息,如下所示:

[StructLayout(LayoutKind.Sequential)]
public struct MD2_Header
{
    public int FourCC;
    public int Version;
    public int TextureWidth;
    public int TextureHeight;
    public int FrameSizeInBytes;
    public int NbrTextures;
    public int NbrVertices;
    public int NbrTextureCoords;
    public int NbrTriangles;
    public int NbrOpenGLCmds;
    public int NbrFrames;
    public int TextureOffset;
    public int TexCoordOffset;
    public int TriangleOffset;
    public int FrameOffset;
    public int OpenGLCmdOffset;
    public int EndOffset;
}
Run Code Online (Sandbox Code Playgroud)

在我的读者代码中,我想做的事情如下:

// Suck the MD2 header into a structure, it is 68 bytes long.
Classic.Util.MD2_Header md2hdr = new Classic.Util.MD2_Header();
md2hdr = reader.ReadBytes(sizeof(Classic.Util.MD2_Header));
Run Code Online (Sandbox Code Playgroud)

我意识到这是不正确的,因为它有点奇怪地打破了类型安全,但你知道我想要完成什么.我可以通过单独调用reader.ReadInt32()来做到这一点,但我很好奇是否有任何方式让我按照我希望使用普通库调用的方式工作.

我看了一下Marshal.Copy()方法,但似乎是在托管和非托管内存之间进行,这不是我在这里做的.

有什么建议?

not*_*row 5

将字节流读取到字节数组,为其命名packet,然后尝试以下操作:

GCHandle pinned = GCHandle.Alloc(packet, GCHandleType.Pinned);
MD2_Header h = (MD2_Header)Marshal.PtrToStructure(pinned.AddrOfPinnedObject(), typeof(MD2_Header));
pinned.Free();
Run Code Online (Sandbox Code Playgroud)


Guf*_*ffa 3

C 中的结构和 C# 中的结构是完全不同的两个东西。C 中的结构体可用于值类型和引用类型,而 C# 中的结构体仅用于值类型。

值类型应该表示单个值,但是您拥有大量值,因此您应该使用类。.NET 中结构的建议最大大小为 16 字节,并且您拥有的数据量是其四倍多。

具有属性和采用字节数组的构造函数的类将如下所示:

public class MD2_Header {

  public int FourCC { get; set; }
  public int Version { get; set; };
  public int TextureWidth { get; set; };
  public int TextureHeight { get; set; };
  public int FrameSizeInBytes { get; set; };
  public int NbrTextures { get; set; };
  public int NbrVertices { get; set; };
  public int NbrTextureCoords { get; set; };
  public int NbrTriangles { get; set; };
  public int NbrOpenGLCmds { get; set; };
  public int NbrFrames { get; set; };
  public int TextureOffset { get; set; };
  public int TexCoordOffset { get; set; };
  public int TriangleOffset { get; set; };
  public int FrameOffset { get; set; };
  public int OpenGLCmdOffset { get; set; };
  public int EndOffset { get; set; };

  public MD2_Header(byte[] values) {
    FourCC = BitConverter.ToInt32(values, 0);
    Version = BitConverter.ToInt32(values, 4);
    TextureWidth = BitConverter.ToInt32(values, 8);
    TextureHeight = BitConverter.ToInt32(values, 12);
    FrameSizeInBytes = BitConverter.ToInt32(values, 16);
    NbrTextures = BitConverter.ToInt32(values, 20);
    NbrVertices = BitConverter.ToInt32(values, 24);
    NbrTextureCoords = BitConverter.ToInt32(values, 28);
    NbrTriangels = BitConverter.ToInt32(values, 32);
    NbrOpenGLCmds = BitConverter.ToInt32(values, 36);
    NbrFrames = BitConverter.ToInt32(values, 40);
    TextureOffset = BitConverter.ToInt32(values, 44);
    TexCoordOffset = BitConverter.ToInt32(values, 48);
    TriangleOffset = BitConverter.ToInt32(values, 52);
    FrameOffset = BitConverter.ToInt32(values, 56);
    OpenGLCmdOffset = BitConverter.ToInt32(values, 60);
    EndOffset = BitConverter.ToInt32(values, 64);
  }

}
Run Code Online (Sandbox Code Playgroud)