转换不同的值类型的数组为一个字节数组 [英] Convert an array of different value types to a byte array

查看:166
本文介绍了转换不同的值类型的数组为一个字节数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是什么我已经出来了,到目前为止,但它似乎并不十分理想,任何想法更好的方法?

 公共无效ToBytes(对象[]数据字节[]缓冲区)
{
    字节[] obytes;
    INT偏移= 0;    的foreach(数据obj对象)
    {
        如果(obj是字符串)
            obytes = System.Text.Encoding.UTF8.GetBytes(((字符串)OBJ));
        否则,如果(obj是布尔)
            obytes = BitConverter.GetBytes((布尔)OBJ);
        否则,如果(obj是字符)
            obytes = BitConverter.GetBytes((char)的OBJ);
        //等等每个值类型        Buffer.BlockCopy(obytes,0,缓冲,抵消,obytes.Length);
        胶印+ = obytes.Length;
    }
}


解决方案

好了,你可以有一个图是这样的:

 私有静态readonlyDictionary<类型,函数功能与LT;对象,字节[]>>转换器=
    新字典<类型,函数功能与LT;对象,字节[]>>()
{
    {typeof运算(字符串),O => Encoding.UTF8.GetBytes((串)O)},
    {typeof运算(布尔),O => BitConverter.GetBytes((布尔)O)},
    {typeof运算(炭),O => BitConverter.GetBytes((炭)O)},
    ...
};公共静态无效ToBytes(对象[]数据字节[]缓冲区)
{
    INT偏移= 0;    的foreach(数据obj对象)
    {
        如果(OBJ == NULL)
        {
            //或做你想做的
            抛出新的ArgumentException(无法转换空值);
        }
        FUNC<对象,字节[]>转换器;
        如果(!Converters.TryGetValue(obj.GetType(),从转换器))
        {
            抛出新的ArgumentException(无转换​​器+ obj.GetType());
        }        字节[] = obytes转换器(OBJ);
        Buffer.BlockCopy(obytes,0,缓冲,抵消,obytes.Length);
        胶印+ = obytes.Length;
    }
}

您还在指定每种类型的转换器,但它是一个很多比的if / else形式更加紧凑。

有构造字典,顺便说一句的各种方式。你可以做这样的:

 私有静态只读字典<类型,函数功能与LT;对象,字节[]>>转换器=
        新字典<类型,函数功能与LT;对象,字节[]>>();静态WhateverYourTypeIsCalled()
{
    AddConverter<串GT;(Encoding.UTF8.GetBytes);
    AddConverter<布尔>(BitConverter.GetBytes);
    AddConverter<焦炭>(BitConverter.GetBytes);
}静态无效AddConverter< T>(Func键< T,字节[]>转换器)
{
    Converters.Add(typeof运算(T),X =>转换器((T)x));
}


我看到另一个答案已经建议二进制序列化。我个人并不热衷于不透明的序列化机制这样。我想知道到底发生了什么是在数据中,这意味着我可以移植到其他平台的方式。

我想指出,不过,您的现行计划并没有给任何形式的分隔符 - 如果你有两个字符串,你根本不知道其中一个停止,并开始其他,例如。您还没有存储类型信息 - 这可能是好的,但也未必。可变长度问题通常更重要。你可能会考虑使用长度 - preFIX方案,像在的BinaryWriter 。事实上,的BinaryWriter 可能是一般简单的解决方案。你可能会想还有一个地图的代表,而且使他们采取的BinaryWriter 和值的行动。然后,您可以建立反射地图,或只是一个硬codeD话费清单。

然后你只初始化的BinaryWriter 包装在的MemoryStream ,适当地写每个值给它,然后调用的ToArray 的MemoryStream 来获得满意的结果。

This is what I've come up with so far, but it doesn't seem very optimal, any ideas on better approaches?

public void ToBytes(object[] data, byte[] buffer)
{
    byte[] obytes;
    int offset = 0;

    foreach (object obj in data)
    {
        if (obj is string)
            obytes = System.Text.Encoding.UTF8.GetBytes(((string)obj));
        else if (obj is bool)
            obytes = BitConverter.GetBytes((bool)obj);
        else if (obj is char)
            obytes = BitConverter.GetBytes((char)obj);
        // And so on for each valuetype

        Buffer.BlockCopy(obytes, 0, buffer, offset, obytes.Length);
        offset += obytes.Length;
    }
}

解决方案

Well, you could have a map like this:

private static readonlyDictionary<Type, Func<object, byte[]>> Converters = 
    new Dictionary<Type, Func<object, byte[]>>()
{
    { typeof(string), o => Encoding.UTF8.GetBytes((string) o) },
    { typeof(bool), o => BitConverter.GetBytes((bool) o) },
    { typeof(char), o => BitConverter.GetBytes((char) o) },
    ...
};

public static void ToBytes(object[] data, byte[] buffer)
{
    int offset = 0;

    foreach (object obj in data)
    {
        if (obj == null)
        {
            // Or do whatever you want
            throw new ArgumentException("Unable to convert null values");
        }
        Func<object, byte[]> converter;
        if (!Converters.TryGetValue(obj.GetType(), out converter))
        {
            throw new ArgumentException("No converter for " + obj.GetType());
        }

        byte[] obytes = converter(obj);
        Buffer.BlockCopy(obytes, 0, buffer, offset, obytes.Length);
        offset += obytes.Length;
    }
}

You're still specifying the converter for each type, but it's a lot more compact than the if/else form.

There are various other ways of constructing the dictionary, btw. You could do it like this:

private static readonly Dictionary<Type, Func<object, byte[]>> Converters = 
        new Dictionary<Type, Func<object, byte[]>>();

static WhateverYourTypeIsCalled()
{
    AddConverter<string>(Encoding.UTF8.GetBytes);
    AddConverter<bool>(BitConverter.GetBytes);
    AddConverter<char>(BitConverter.GetBytes);
}

static void AddConverter<T>(Func<T, byte[]> converter)
{
    Converters.Add(typeof(T), x => converter((T) x));
}


I see another answer has suggested binary serialization. I'm personally not keen on "opaque" serialization schemes like that. I like to know exactly what's going to be in the data in a way that means I can port it to other platforms.

I would point out, however, that your current scheme doesn't give any sort of delimiter - if you have two strings, you'd have no idea where one stopped and the other started, for example. You also don't store the type information - that may be okay, but it may not be. The variable length issue is usually more important. You might consider using a length-prefix scheme, like the one in BinaryWriter. Indeed, BinaryWriter may well be a simpler solution in general. You'd probably want to still have a map of delegates, but make them actions taking a BinaryWriter and a value. You could then build the map by reflection, or just a hardcoded list of calls.

Then you'd just initialize a BinaryWriter wrapping a MemoryStream, write each value to it appropriately, then call ToArray on the MemoryStream to get the results.

这篇关于转换不同的值类型的数组为一个字节数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆