c#往结构体里面读数据_结构体:探析C#文件方式读写结构体

本文探讨如何在C#中使用结构体直接读取和写入文件,尤其是处理Net Micro Framework的tinyfnt文件。文章指出C#没有提供直接从文件读取结构体的指令,但可以通过自定义内存布局实现。示例代码展示了如何利用StructLayout和FieldOffset属性创建类似C/C++的联合布局,并提供了序列化和反序列化的实现,以便将结构体数据存入和从文件中读出。然而,这种方法对数据对齐和结构体匹配要求较高,不匹配可能导致异常。
摘要由CSDN通过智能技术生成

最近直在研究Net Micro Framework字体文件(tinyfnt)由于tinyfnt文件头部有段描述数据所以很想

定义个结构体像VC样直接从文件中读出来省得用流个个解析很是麻烦   没有想到在中竟没有直接指令想必设

计者认为提供了流和序列化技术切问题都可以迎刃而解了

在中结构体是个比较复杂东西在此的上有很多需要设置参数否则用起来就很容易出错下面是msdn上段描述

看看也许有助于理解C#语言中结构体

通过使用属性可以自定义结构在内存中布局方式例如可以使用 StructLayout(LayoutKind.Explicit) 和

FieldOff 属性创建在 C/C 中称为联合布局

[.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]

struct TestUnion

{

[.Runtime.InteropServices.FieldOff(0)]

public i;

[.Runtime.InteropServices.FieldOff(0)]

public double d;

[.Runtime.InteropServices.FieldOff(0)]

public char c;

[.Runtime.InteropServices.FieldOff(0)]

public b;

}  在上个代码段中TestUnion 所有字段都从内存中同位置开始

以下是字段从其他显式设置位置开始另个举例

[.Runtime.InteropServices.StructLayout(LayoutKind.Explicit)]

struct TestExplicit

{

[.Runtime.InteropServices.FieldOff(0)]

public long lg;

[.Runtime.InteropServices.FieldOff(0)]

public i1;

[.Runtime.InteropServices.FieldOff(4)]

public i2;

[.Runtime.InteropServices.FieldOff(8)]

public double d;

[.Runtime.InteropServices.FieldOff(12)]

public char c;

[.Runtime.InteropServices.FieldOff(14)]

public b;

}  i1 和 i2 这两个 字段共享和 lg 相同内存位置使用平台时这种结构布局控制很有用

我做了个简单测试基本达成预定需求不过该方式要求比较苛刻如果要解析数据和转换结构体不匹配就会

引发系列莫名其妙异常(如内存不可读等等的类)下面是测试源代码有兴趣朋友可以看看也希望网友能提出更好方

using ;

using .Collections.Generic;

using .ComponentModel;

using .Data;

using .Drawing;

using .Text;

using ..Forms;

using .IO;

using .Runtime.InteropServices;

RWFile

{

public partial Form1 : Form

{

public Form1

{

InitializeComponent;

}

//从文件中读结构体

private void button1_Click(object sender, EventArgs e)

{

strFile = Application.StartupPath + "  est.dat";

(!File.Exists(strFile))

{

MessageBox.Show("文件不存在");

;

}

FileStream fs = FileStream(strFile, FileMode.Open,

FileAccess.ReadWrite);

TestStruct ts = TestStruct;

bytData = [Marshal.SizeOf(ts)];

fs.Read(bytData, 0, bytData.Length);

fs.Close;

ts = rawDeserialize(bytData);

textBox1.Text = ts.dTest.;

textBox2.Text = ts.uTest.;

textBox3.Text = Encoding.Default.GetString(ts.bTest);

}

//向文件中写结构体

private void button2_Click(object sender, EventArgs e)

{

strFile = Application.StartupPath + "  est.dat";

FileStream fs = FileStream(strFile, FileMode.Create ,

FileAccess.Write);

TestStruct ts = TestStruct;

ts.dTest = double.Parse(textBox1.Text);

ts.uTest = UInt16.Parse(textBox2.Text);

ts.bTest = Encoding.Default.GetBytes(textBox3.Text);

bytData = rawSerialize(ts);

fs.Write(bytData, 0, bytData.Length);

fs.Close;

}

[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Ansi)] //,Size=16

public struct TestStruct

{

[MarshalAs(UnmanagedType.R8)] //,FieldOff(0)]

public double dTest;

[MarshalAs(UnmanagedType.U2)] //, FieldOff(8)]

public UInt16 uTest;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]

//, FieldOff(10)]

public bTest;

}

//序列化

public rawSerialize(object obj)

{

rawsize = Marshal.SizeOf(obj);

IntPtr buffer = Marshal.AllocHGlobal(rawsize);

Marshal.StructureToPtr(obj, buffer, false);

rawdatas = [rawsize];

Marshal.Copy(buffer, rawdatas, 0, rawsize);

Marshal.FreeHGlobal(buffer);

rawdatas;

}

//反序列化

public TestStruct rawDeserialize( rawdatas)

{

Type anytype = typeof(TestStruct);

rawsize = Marshal.SizeOf(anytype);

(rawsize > rawdatas.Length) TestStruct;

IntPtr buffer = Marshal.AllocHGlobal(rawsize);

Marshal.Copy(rawdatas, 0, buffer, rawsize);

object retobj = Marshal.PtrToStructure(buffer, anytype);

Marshal.FreeHGlobal(buffer);

(TestStruct)retobj;

}

}

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值