c# - 将不同值类型的数组转换为字节数组

标签 c# arrays byte value-type

这是我到目前为止的想法,但它似乎不是很理想,有没有关于更好方法的想法?

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;
    }
}

最佳答案

好吧,你可以有这样一张 map :

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;
    }
}

您仍然为每种类型指定转换器,但它比 if/else 形式紧凑得多。

顺便说一句,还有其他各种构建字典的方法。你可以这样做:

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));
}

我看到另一个答案建议二进制序列化。我个人并不热衷于那种“不透明”的序列化方案。我想确切地知道数据中将包含什么,这意味着我可以将其移植到其他平台。

但是,我要指出的是,您当前的方案没有提供任何类型的定界符 - 例如,如果您有两个字符串,您将不知道一个字符串在哪里停止,另一个字符串在哪里开始。您也不存储类型信息——这可能没问题,但也可能不是。可变长度问题通常更为重要。您可能会考虑使用长度前缀方案,例如 BinaryWriter 中的方案。事实上,BinaryWriter 可能是一个更简单的解决方案。您可能仍希望拥有代表的 map ,但让他们采取 BinaryWriter 和值的操作。然后,您可以通过反射构建映射,或者只是一个硬编码的调用列表。

然后你只需初始化一个 BinaryWriter 包装一个 MemoryStream,将每个值适本地写入它,然后在 上调用 ToArray >MemoryStream 获取结果。

关于c# - 将不同值类型的数组转换为字节数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1385829/

相关文章:

go - 为什么golang对 byte slice 使用括号,对字符串片使用括号?

python - 如何将字节字符串拆分为单独的部分

c# - 如何在 ASP.NET MVC 4 页面中显示 HTML 编辑器

c# - 如何在启用分区的情况下接收来自主题的消息

c# - 从 aspx 中的 javascript 调用代码隐藏函数

javascript - 如何在不循环的情况下确定元素是否包含在数组中?

java - 如何在 Java 中打印出数组的偶数索引?

c# - 在c#中多线程处理大量的web请求

php - 使用 PHP 和 jQuery 预加载图像 - 逗号分隔数组?

java - 处理字节数组产生奇怪结果的字符串构造函数