【问题标题】:How to serialize a collection as an alphanumeric string?如何将集合序列化为字母数字字符串?
【发布时间】:2009-07-01 08:08:51
【问题描述】:

我需要将大约 10-15 个短字符串(可能还有一些整数)的集合表达为一个相当紧凑的字母数字字符串 - 我可以将其作为 get 请求中的参数发送。

基本上,我认为我的集合将是一个哈希表,我想对其进行序列化,使其看起来有点像视图状态字符串(只是希望不要那么长!)。

例如。 testpage.aspx?code=rO0ABXNyAAlTb21lQ2xhc3PSHbLk6OgfswIAA0kAAWl

然后 testpage.aspx 可以将其反序列化回原始集合。

这可能吗?

【问题讨论】:

    标签: c# serialization hashtable


    【解决方案1】:

    这里的一个选项是选择一个分隔符,例如 ¤;加入字符串,对它们进行编码(可能是 UTF8),然后将字节打包为 base-64...

        string[] data = {"abc","123", "def"};
        string s = string.Join("¤", data);
        byte[] raw = Encoding.UTF8.GetBytes(s);
        string alphaNumeric = Convert.ToBase64String(raw); // send this
    

    (您可能需要处理 base-64 使用的少数非字母数字字符)。

    然后反转它:

        raw = Convert.FromBase64String(alphaNumeric);
        s = Encoding.UTF8.GetString(raw);
        data = s.Split('¤');
    

    如果您想发送键/值对...好吧,显而易见的选择将是查询字符串参数本身,因为它们是为此而设计的。但如果您需要将其作为字节流:

        var data = new DbConnectionStringBuilder();
        data["foo"] = "abc";
        data["bar"] = "123 + ;la";
        string s = data.ConnectionString;
    
        byte[] raw = Encoding.UTF8.GetBytes(s);
        string alphaNumeric = Convert.ToBase64String(raw); // send this
    
        raw = Convert.FromBase64String(alphaNumeric);
        s = Encoding.UTF8.GetString(raw);
        data.ConnectionString = s;
        foreach (string key in data.Keys)
        {
            Console.WriteLine(key + "=" + data[key]);
        }
    

    【讨论】:

    • 我喜欢使用 DbConnectionStringBuilder 的想法。从来没有想过以这种方式使用它:-)
    【解决方案2】:

    为什么不直接使用 protobuf-net 序列化数据并通过 Session 传递呢?或者,如果它必须是一个字符串,只需使用 XmlSerializer?

    就我个人而言,通过 URL 传递序列化数据对我来说真的很糟糕!

    【讨论】:

    • 嘿,但你是有偏见的马克 ;)
    • XmlSerializer + base64 是我的建议。
    • @Matthew Scharley,protobuf 产生更紧凑的输出。
    【解决方案3】:

    您可以将您的字典/哈希表序列化为 JSON, 然后将其更改为 base64(只是为了使其不那么明显并解决可能使用的 URL 字符等)。 或者您可以直接对其进行 URLEncode。

    【讨论】:

      【解决方案4】:

      您可以使用标准的 .Net 序列化并将您的对象序列化为 MemoryStream。然后,您可以将 MemoryStream 的内容作为字节数组读出,并在数组上使用 Convert.ToBase64String 来获取它的字符串表示形式。

      要反序列化它,你可以做相反的事情。

      如果担心序列化对象太大,可以将 MemoryStream 包裹在 System.IO.Compression.DeflateStream 中进行压缩。

      【讨论】:

      • 仅仅发送几个字符串似乎有点过头了——而且它完全不便携......?
      • @marc - 这可能有点矫枉过正,但他的问题是模糊的(......也许是几个整数),并且使用序列化(可能还有放气)是一种在大多数情况下都可以使用的通用解决方案。
      【解决方案5】:

      谢谢大家,我写了一个测试控制台应用程序。结果字符串这么长,我有点失望。

      我的示例实现了 DeflateStream,对于我的数据大小而言,这可能会引入比压缩节省更多的开销。但即使没有压缩,它仍然很大。

      我希望实现的是使一些东西更紧凑(用户的混淆是一个加号,但不是关键) - 我怀疑使用普通的旧参数化字符串实际上会更好。也许 JSON 可能没问题,但我使用的是 ASP.net 2.0,我不认为我在那里得到了现成的 json 序列化程序。

      不过,我学到了一些新的有趣的东西,所以谢谢你!

          static void Main(string[] args)
          {
              Hashtable ht1 = new Hashtable(1);
              ht1.Add("name", "bob");
              Console.WriteLine(ToCompactString(ht1));
      
              Console.WriteLine();
      
              string str = "name:bob";
              Console.WriteLine(ToCompactString(str));
              Console.ReadLine();
          }
      
          private static string ToCompactString(object obj)
          {
              var ms = new MemoryStream();
              var ds = new DeflateStream(ms, CompressionMode.Compress);
              var bf = new BinaryFormatter();
      
              bf.Serialize(ds, obj);
              byte[] bytes = ms.ToArray();
              ds.Close();
              ms.Close();
              string result = Convert.ToBase64String(bytes);
              return result;
          }
      

      【讨论】:

      • 使用我提到的第二种方式(DbConnectionStringBuilder,UTF8,base-64),这个“name”="bob" 示例是“bmFtZT1ib2I=" - 有这么大吗?顺便说一句 - 对短数据的压缩通常会增加大小......也许如果你尝试过这两个赞成的答案?
      • 我同意 Marc 的观点。这个解决方案很可能比您需要的复杂得多。
      猜你喜欢
      • 1970-01-01
      • 2020-04-14
      • 1970-01-01
      • 1970-01-01
      • 2021-01-08
      • 1970-01-01
      • 2019-12-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多