C#各种数组直接的数据复制/转换

之前做Opengl程序,用的的C#的SharpGL这个库,里面有各种奇怪绑定的函数,比如原型为:

void glInterleavedArrays(uint format, int stride, void * pointer);

的函数被他绑定成:

private static extern void glInterleavedArrays(uint format, int stride, int[] pointer);

然后我就被逼着学习了各种float[] 转 int[] 的方法,比较他们的效率(其实我还是感觉c++比较快,一个指针类型转换,欧啦)

下面是我写的各种数组赋值转换的方法和结果对比。

1.Marshal.Copy,存在数组到IntPtr,IntPtr到数组的2次拷贝【当T2不是Copy支持的类型会出错,之所以引入dynamic dTo 是因为使用T2[] dTo 无法编译通过】,处理2000000*100字节1120.0018ms

public static T2[] Arr2Arr<T1, T2>(T1[] from)
    where T1: struct
    where T2 :struct
{

    int byteNum = from.Length * from[0].Sizeof();
    T2 testByte = new T2();

    dynamic dFrom = from;
    dynamic dTo = new T2[byteNum / testByte.Sizeof()];

    IntPtr ptr = Marshal.AllocHGlobal(byteNum);
    Marshal.Copy(dFrom, 0, ptr, from.Length);
    Marshal.Copy(ptr, dTo, 0, dTo.Length);
    return dTo;
}

2.unsafe的方法,通过指针获得IntPtr,减少了一次复制,速度变快【当T2不是Copy支持的类型会出错,之所以引入pFrom是因为无法fixed泛型T1[]】,处理2000000*100字节695.9993ms

public unsafe static T2[] Arr2Arr<T1, T2>(T1[] from, void * pFrom)
    where T1 : struct
    where T2 : struct
{
    int byteNum = from.Length * from[0].Sizeof();
    T2 testByte = new T2();
    dynamic dTo = new T2[byteNum / testByte.Sizeof()];

    IntPtr ptr = new IntPtr(pFrom);
    Marshal.Copy(ptr, dTo, 0, dTo.Length);
    return dTo;
}

3.通过GCHandle获得IntPtr,然后复制【当T2不是Copy支持的类型会出错】,处理2000000*100字节930.0481ms

public static T2[] Arr2Arr2<T1, T2>(T1[] from)
    where T1 : struct
    where T2 : struct
{
    var gch = GCHandle.Alloc(from,GCHandleType.Pinned);
    IntPtr ptr = gch.AddrOfPinnedObject();

    int byteNum = from.Length * from[0].Sizeof();
    T2 testByte = new T2();
    dynamic dTo = new T2[byteNum / testByte.Sizeof()];
    Marshal.Copy(ptr, dTo, 0, dTo.Length);
    gch.Free();
    return dTo;
}

4.Array.Copy的方法,原生的数组复制方法【没有了Copy,可以处理任意值类型】,处理2000000*100字节620.042ms

public static T2[] Arr2Arr3<T1, T2>(T1[] from)
    where T1 : struct
    where T2 : struct
{
    int byteNum = from.Length * from[0].Sizeof();
    T2 testByte = new T2();
    T2[] dTo = new T2[byteNum / testByte.Sizeof()];

    Array.Copy(from, dTo, dTo.Length);
    return dTo;
}

5.通过Buffer.BlockCopy拷贝数组,速度最快,感觉类似于c++的memcpy【没有了Copy,可以处理任意值类型】,处理2000000*100字节300.0329ms

public static T2[] Arr2Arr4<T1, T2>(T1[] from)
    where T1 : struct
    where T2 : struct
{
    int byteNum = from.Length * from[0].Sizeof();
    T2 testByte = new T2();
    T2[] dTo = new T2[byteNum / testByte.Sizeof()];

    Buffer.BlockCopy(from, 0, dTo, 0, byteNum);

    return dTo;
}

测试部分代码:

byte[] from = new byte[100];
from[0] = 1;
from[1] = 1;

var last = DateTime.Now;
for (int i = 0; i < 2000000; i++)
{
    。。。
}
Console.WriteLine((DateTime.Now- last).TotalMilliseconds);
//sizeof扩展方法
internal static class ExFunc
{
    public static int Sizeof(this ValueType t)
    {
        return Marshal.SizeOf(t);
    }
}

综上所述,Buffer.BlockCopy 适用场合最广泛,效率最高。

例子下载地址:http://files.cnblogs.com/files/chihirosan/Convert.zip

时间: 2024-08-04 10:56:54

C#各种数组直接的数据复制/转换的相关文章

file_get_contents(&#39;php://input&#39;) 数据如何转换成数组

前台表单页:demo01.html 后台:demo01.php 输出结果: 备注:若前台通过Ajax的post提交过来的是json数据,需要对json数据进行解析:$data = json_decode($postStr,true); file_get_contents('php://input') 的优势: 1, php://input 可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据.但是,一般GE

Delphi Byte数组与String类型的转换

string string = AnsiString = 长字符串,理论上长度不受限制,但其实受限于最大寻址范围2的32次方=4G字节: 变量Str名字是一个指针,指向位于堆内存的字符序列,字符序列起始于@Str[1],@Str[1]偏移负16个字节的空间存储着字串长度.引用计数等信息.字符序列以NULL结束. string[n] string[n] = ShortString = 短字符串,最多容纳255个字符,实际长度是字符长度+1,是Delphi的简单类型: Str[0]存储着字符的个数,

【转】java中byte数组与int类型的转换(两种方式)----不错

原文网址:http://blog.csdn.net/piaojun_pj/article/details/5903009 java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中,发送.者接收的数据都是 byte数组,但是int类型是4个byte组成的,如何把一个整形int转换成byte数组,同时如何把一个长度为4的byte数组转换为int类型.下面有两种方式. 第一种方法: public static byte[] int2byte(int

将传入结构体 pMtInfo 中包含的数据内容转换成 JSON 字符串返回

upu_struct.h封装了有关  pMtInfo结构体的内容,用到的部分如下图所示: 利用jansson库实现将传入结构体 pMtInfo 中包含的数据内容转换成 JSON 字符串返回 代码如下: #include <stdio.h> #include <string.h> #include "jansson.h" #include "upu_struct.h" #include "upu_proto_parse.h"

使用C# 将Excel1 中sheet1 的数据复制粘贴到Excel2中的sheet2

最近在项目中有这个需求, 在网上找的资料哦也有限 . 最开始想的是用openxmlsdk  只能在同一个Excel表中数据复制! 1.使用openxml sdk 复制Excel 中Sheet1 的数据到sheet2: 1 /// <summary> 2 ///使用openxmlsdk 转换数据 原理是通过CloneNode克隆 目前只完成同表之间的全部复制! 3 /// </summary> 4 /// <param name="path">Exce

JSONObject.fromObject(map)(JSON与JAVA数据的转换)

JSON与JAVA数据的转换(JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互.) 上一篇文章中有这么一句,是后台的封装数据. JSONObject jo = JSONObject.fromObject(map);常见的java代码转换成json 1. List集合转换成json代码 List list = new ArrayList(); list.add( "first" ); lis

JSON与JAVA数据的转换

原文地址:JSONObject.fromObject(map)(JSON与JAVA数据的转换)作者:田保兴 JSON与JAVA数据的转换(JSON 即 JavaScript Object Natation,它是一种轻量级的数据交换格式,非常适合于服务器与 JavaScript 的交互.)JSONObject jo = JSONObject.fromObject(map); 常见的java代码转换成json 1. List集合转换成json代码 List list = new ArrayList(

java中byte数组与int类型的转换(两种方式)

java中byte数组与int类型的转换,在网络编程中这个算法是最基本的算法,我们都知道,在socket传输中,发送.者接收的数据都是 byte数组,但是int类型是4个byte组成的,如何把一个整形int转换成byte数组,同时如何把一个长度为4的byte数组转换为int类型.下面有两种方式. 方法一 /** * int到byte[] * @param i * @return */ public static byte[] intToByteArray(int i) { byte[] resu

盘点机数据怎么转换成电脑盘点系统的数据

若是该物联宇手持终端是针动该POS系统配备的,先把盘点机生成的盘点数据文件复制到POS系统电脑上,然后在POS系统盘点界面应该有类似"数据导入"的功能,选择该数据文件导入.否则需要把盘点机生成的数据文件转换成POS系统限制格式的文件,此种情况下最佳的处理方式是让盘点机提供商修改程序,生成所需格式:若是此方式行不通,则需要一二次转换数据文件格式的软件,每次导入前都要转换一下文件格式. 原文地址:https://blog.51cto.com/14265294/2387356