C# 中的数据转换

davidwee 2002-08-14 06:18:20
如何:

byte array <-> string
byte array <-> int or long

另外,我定义好一个数据结构,能不能将与之大小相等的一个数据块(byte array)赋给它从而使之中的各个变量都得到相应的值?(就像C++中使用指针赋值)
...全文
61 2 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
anamnesis 2002-08-14
  • 打赏
  • 举报
回复
发信人: ming (阿笨◇飞跃), 信区: DOTNET
标 题: [FAQ]简单struct/class属性的序列化
发信站: 虎踞龙蟠 BBS 站 (2002年04月30日17:52:41 星期二), 转信

(欢迎转贴,但请保留作者信息,作者:ming@sbbs, Email:kfkming@hotmail.com)
=========================================

琢磨了很长时间,总算是实现了。

这里所说的“简单 struct/class”是指非嵌套的,只包含简单
类型及数组的 struct/class。

1. 方法概述

中心思想是利用 System.Runtime.InteropServices 名空间中的
Marshal 类将 struct/class 转换为 IntPtr (C# 中类型安全的
指针),然后将指针所指内存拷贝到一个 byte 数组中来实现。
详细描述请参考文献[1]。这个方法只对 ValueType(在 stack 上
分配内存的类型)有效,如果 struct/class 中有 ReferenceType
(在 heap 上分配内存的类型),编译可以通过,但是运行会抛出
异常。所以我们必须对 struct/class 中的 ReferenceType 进行
必要的处理,分别表述如下:

1.1. string 类型

string 类型是一种 ReferenceType, 尽管我们在定义和使用它的
时候所使用的方法与 ValueType(如 int, byte 等)非常相似。如
果要对包含 string 类型的 struct/class 进行转换,我们必须以
如下形式定义 string.

struct demo
{
......
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string s;
}

SizeConst 是此子串的最大长度。字串长度是固定的。这一点不大
好,但是我还没有琢磨出来更好的方法,如果使用 char 数组就与
C 编程就非常类似了,可能 C 程序员处理起来更加顺手一些。如果
谁有更好的办法请也在这个版面写一下,或发给 kfkming@hotmail.com

其他的具体含义请自己查阅 MSDN。

1.2. 简单数组

简单数组是指数组元素类型为内建类型(如 int, byte 等)。
如果要对包含简单数组的 struct/class 进行转换,数组的定义形式
如下:(以 byte 数组为例)

struct demo
{
......
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
public byte[] c;
}

有一点要特别注意,在使用这个数组之前一定要对其初始化,在这里并
没有进行初始化。初始化的时候要将数组元素初始化为 Byte(注意不是
byte):

demo mydemo=new demo();
mydemo.c=new Byte[3];

数组大小应该与属性中指定的 SizeConst 相同。

上面的对 ReferenceType 添加的属性的主要作用其实是将 ReferenceType
都转换为 ValueType。比如上例中的 Byte 实际上是一个 struct, 是一个
ValueType. 这样所需内存都在堆栈上分配。

2. 转换方法

程序主要来源于参考文献[1],核心部分为 RawSerialize 函数.

using System;
using System.Runtime.InteropServices;

namespace ConsoleDemo
{
class Class1
{
[StructLayout(LayoutKind.Sequential, Pack=1, CharSet=CharSet.Ansi)]
struct demo
{
public byte a;
public int b;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=3)]
public byte[] c;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=5)]
public string s;
}

public static byte[] RawSerialize( object anything )
{
int rawsize = Marshal.SizeOf( anything );
IntPtr buffer = Marshal.AllocHGlobal( rawsize );
Marshal.StructureToPtr( anything, buffer, false );
byte[] rawdatas = new byte[ rawsize ];
Marshal.Copy( buffer, rawdatas, 0, rawsize );
Marshal.FreeHGlobal( buffer );
return rawdatas;
}


[STAThread]
static void Main(string[] args)
{
demo aa=new demo();

aa.a=10;
aa.b=10;
aa.c=new Byte[3];
aa.s="AAA";
aa.c[0]=3;
aa.c[1]=4;
aa.c[2]=5;

int rawLen=Marshal.SizeOf(aa);

//这个数组的长度必须大到能容纳整个 struct/class
byte[] c=new Byte[13];

c=RawSerialize(aa);

for (int i=0;i<c.Length;i++)
{
Console.WriteLine(c[i]);
}
}
}
}


3. 参考文献
[1] http://groups.google.com/groups?selm=%237tARJk5BHA.1656%40tkmsftngp05
[2] http://groups.google.com/groups?selm=O3eoqqJlAHA.2156%40tkmsftngp05
--

那天晚上我明白了一个道理,其实这个世界上没有什么事情是不可能的。
所以,改变自己,就应该在今天。

※ 来源:·虎踞龙蟠 BBS 站 sbbs.seu.edu.cn·[FROM: 202.119.27.47]
※ 修改:·ming 於 04月30日21:06:31 修改本文·[FROM: 202.119.15.8]
anamnesis 2002-08-14
  • 打赏
  • 举报
回复
Marshal
先structlayout你的数据结构
然后把你的结构里面的引用类型 marshalas成散列
然后用Marshal.Copy
反向的类似

111,096

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧