叶帆工作室

嵌入式开发爱好者(十年开发经验,精通C/C++/VC/VB/C#...)

用户操作
[即时聊天] [发私信] [加为好友]
叶帆ID:yefanqiu
536439次访问,排名80好友0人,关注者224
微软MVP / CSDN 2008十大MVB/MSDN中文技术论坛版主
yefanqiu的文章
原创 218 篇
翻译 0 篇
转载 3 篇
评论 1099 篇
叶帆的公告
本博客原创文章,作者保留一切权利,需经作者同意后方可转载,转载时 请注明[叶帆工作室]及文章链接。yefan@vip.sina.com
【简介】叶帆[微软MVP]
【文章】叶帆文章列表
【软件】叶帆共享软件列表
最近评论
BinYu:我用的是vista home basic sp1,但vs2005强行装不上去,请帮忙分析一下,qq:811344767,先谢谢了
wjh6877:算法想好了吗?

没有就是空话
一生好人:其实我也想来正版,但生活逼人,没办法啊
fox23:something like java card;-)
wwqqha:不错不错
文章分类
收藏
    相册
    叶帆照片
    【叶帆软件】
    [01]VB源码之友(V2.1.548)
    [02]API浏览器.net(V5.0)
    [03]叶帆成语词典(V2.0.8)
    [04]叶帆密码库(V1.2.8)
    【叶帆资源】
    DAO 2.0引擎
    叶帆快速通道
    MSDN-MVP
    Windows Embedded 专题
    中文MSDN
    叶帆圈子--工业自动化
    叶帆工作室(博客园)
    叶帆工控--工业自动化
    叶帆群组--工业应用开发
    微软中文技术论坛
    微软硬件创新中心(HIC)
    瑞康社区论坛
    叶帆友情链接
    张欣
    枕善居
    莫依
    葛涵涛
    郑建
    陈辉
    马宁
    马骐
    魏涛序
    黎波
    存档
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 C#文件方式读写结构体探析收藏

    新一篇: .Net Micro Framework研究—Tinyfnt字体研究 | 旧一篇: .Net Micro Framework 2007技术论坛(提供PPT下载)

        最近一直在研究.Net Micro Framework字体文件(tinyfnt),由于tinyfnt文件头部有一段描述数据,所以很想定义一个结构体,像VC一样直接从文件中读出来,省得用流一个个解析很是麻烦。

    没有想到在C#中竟没有直接的指令,想必C#设计者认为提供了流和序列化技术,一切问题都可以迎刃而解了。

    C#中结构体是一个比较复杂的东西,在此之上有很多需要设置的参数,否则用起来就很容易出错。下面是msdn上一段描述,看看也许有助于理解C#语言中的结构体。

    -------------------------

    通过使用属性可以自定义结构在内存中的布局方式。例如,可以使用 StructLayout(LayoutKind.Explicit) FieldOffset 属性创建在 C/C++ 中称为联合的布局。

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

    struct TestUnion

    {

        [System.Runtime.InteropServices.FieldOffset(0)]

        public int i;

        [System.Runtime.InteropServices.FieldOffset(0)]

        public double d;

        [System.Runtime.InteropServices.FieldOffset(0)]

        public char c;

        [System.Runtime.InteropServices.FieldOffset(0)]

        public byte b;

    }

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

    以下是字段从其他显式设置的位置开始的另一个示例。

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

    struct TestExplicit

    {

        [System.Runtime.InteropServices.FieldOffset(0)]

        public long lg;

        [System.Runtime.InteropServices.FieldOffset(0)]

        public int i1;

        [System.Runtime.InteropServices.FieldOffset(4)]

        public int i2;

        [System.Runtime.InteropServices.FieldOffset(8)]

        public double d;

        [System.Runtime.InteropServices.FieldOffset(12)]

        public char c;

        [System.Runtime.InteropServices.FieldOffset(14)]

        public byte b;

    }

    i1 i2 这两个 int 字段共享与 lg 相同的内存位置。使用平台调用时,这种结构布局控制很有用。

    -------------------------

    我做了一个简单的测试程序,基本达成预定需求,不过程序该方式要求比较苛刻,如果要解析的数据与转换的结构体不匹配就会引发一系列莫名其妙的异常(如内存不可读等等之类),下面是测试程序的源代码,有兴趣的朋友可以看一看,也希望网友能提出更好的方案。

     

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.IO;

    using System.Runtime.InteropServices;

     

    namespace RWFile

    {

        public partial class Form1 : Form

        {

            public Form1()

            {

                InitializeComponent();

            }

            //从文件中读结构体

            private void button1_Click(object sender, EventArgs e)

            {

                string strFile = Application.StartupPath + "\\test.dat";

                if (!File.Exists(strFile))

                {

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

                    return;

                }

                FileStream fs = new FileStream(strFile, FileMode.Open, FileAccess.ReadWrite);

                TestStruct ts = new TestStruct();

                byte[] bytData = new byte[Marshal.SizeOf(ts)];

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

                fs.Close();

                ts = rawDeserialize(bytData);

                textBox1.Text = ts.dTest.ToString();

                textBox2.Text = ts.uTest.ToString();

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

            }

            //向文件中写结构体

            private void button2_Click(object sender, EventArgs e)

            {

                string strFile = Application.StartupPath + "\\test.dat";

                FileStream fs = new FileStream(strFile, FileMode.Create , FileAccess.Write);

                TestStruct ts = new TestStruct();

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

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

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

                byte[] 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)] //,FieldOffset(0)] 

                public double dTest;

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

                public UInt16 uTest;

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

                public byte[] bTest;

            }

            //序列化

            public static byte[] rawSerialize(object obj)

            {

                int rawsize = Marshal.SizeOf(obj);

                IntPtr buffer = Marshal.AllocHGlobal(rawsize);

                Marshal.StructureToPtr(obj, buffer, false);

                byte[] rawdatas = new byte[rawsize];

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

                Marshal.FreeHGlobal(buffer);

                return rawdatas;

            }

            //反序列化

            public static TestStruct rawDeserialize(byte[] rawdatas)

            {

                Type anytype = typeof(TestStruct);

                int rawsize = Marshal.SizeOf(anytype);

                if (rawsize > rawdatas.Length) return new TestStruct();

                IntPtr buffer = Marshal.AllocHGlobal(rawsize);

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

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

                Marshal.FreeHGlobal(buffer);

                return (TestStruct)retobj;

            }      

          }

    }

    发表于 @ 2007年12月22日 22:03:00|评论(loading...)|编辑

    新一篇: .Net Micro Framework研究—Tinyfnt字体研究 | 旧一篇: .Net Micro Framework 2007技术论坛(提供PPT下载)

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 叶帆