【问题标题】:XMLSerializer - issue with UTF-8 vs UTF-16 CodeXMLSerializer - UTF-8 与 UTF-16 代码的问题
【发布时间】:2019-02-02 15:33:06
【问题描述】:

我正在尝试将一个简单对象(5 个字符串属性)序列化为 XML 以保存到数据库图像字段。然后我需要稍后在程序中将其反序列化回字符串。
但是,我遇到了一些错误——由于 XML 被保存认为它是 UTF-16 导致的——但是,当我将它从数据库加载回字符串时——它认为它是一个 UTF 8 字符串。

我得到的错误是

  • InnerException {“没有 Unicode 字节顺序标记。无法切换到 Unicode。”} System.Exception {System.Xml.XmlException} -- 消息“XML 文档 (0, 0) 中存在错误。”字符串

发生这种情况是因为我将字符串保存到数据库或从数据库加载字符串的两种不同方式吗?在保存时我使用的是 StringBuilder - 但在从数据库加载时我只使用了一个字符串。

想法?

序列化并保存到数据库

        // Now Save the OBject XML to the Query Tables
        var serializer = new XmlSerializer(ExportConfig.GetType());
        StringBuilder StringResult = new StringBuilder();
        using (var writer = XmlWriter.Create(StringResult))
        {
           serializer.Serialize(writer, ExportConfig);
        }
        //MessageBox.Show("XML :  " + StringResult);
        // Now Save to the Query

    try
    {
        string UpdateSQL = "Update ZQryRpt "
                     + "  Set ExportConfig = " + TAGlobal.QuotedStr(StringResult.ToString())
                     + "  where QryId = " + TAGlobal.QuotedStr(((DataRowView)bindingSource_zQryRpt.Current).Row["QryID"].ToString())
                     ;
        ExecNonSelectSQL(UpdateSQL, uniConnection_Config);
    }
    catch (Exception Error)
    {
        MessageBox.Show("Error Setting ExportConfig: " + Error.Message);
    }

从数据库加载并反序列化

    byte[] binaryData = (byte[])((DataRowView)bindingSource_zQryRpt.Current).Row["ExportConfig"];
    string XMLStored = System.Text.Encoding.UTF8.GetString(binaryData, 0, binaryData.Length);

    if (XMLStored.Length > 0)
    {
        IIDExportObject ExportConfig = new IIDExportObject();
        var serializer = new XmlSerializer(ExportConfig.GetType());
        //StringBuilder StringResult = new StringBuilder(XMLStored);
        // Load the XML from the Query into the StringBuilder

        // Now we need to build a Stream from the String to use in the XMLReader
        byte[] byteArray = Encoding.UTF8.GetBytes(XMLStored);
        MemoryStream stream = new MemoryStream(byteArray);
        using (var reader = XmlReader.Create(stream))
        {
            ExportConfig = (IIDExportObject)serializer.Deserialize(reader);
        }
    }

【问题讨论】:

  • 我发现解决问题的唯一方法是在阅读时跳过 xml ident 行。所以我通常使用 StreamReader 作为我的流。打开流后,我做了一个 reader.ReadLine();然后输入 XmlReader.Create(reader)。

标签: c# xml utf-8


【解决方案1】:

约翰 - 非常感谢您的评论!它使我能够完成代码并找到解决方案。

正如您所说 - 使用流阅读器是解决方案 - 但我无法阅读第一行,因为我的字符串中只有一个“行”。但是,我可以使用这条线

            using (StreamReader sr = new StreamReader(stream, false))

这允许我读取流并忽略设置为 false 的“字节顺序标记检测”。

    string XMLStored = MainFormRef.GetExportConfigForCurrentQuery();
    if (XMLStored.Length > 0)
    {
        IIDExportObject ExportConfig = new IIDExportObject();
        try
        {
            var serializer = new XmlSerializer(ExportConfig.GetType());
            // Now we need to build a Stream from the String to use in the XMLReader
            byte[] byteArray = Encoding.UTF8.GetBytes(XMLStored);
            MemoryStream stream = new MemoryStream(byteArray);
            // Now we need to use a StreamReader to get around UTF8 vs UTF16 issues
            //   A little cumbersome - but it works
            using (StreamReader sr = new StreamReader(stream, false))
            {
                using (var reader = XmlReader.Create(sr))
                {
                    ExportConfig = (IIDExportObject)serializer.Deserialize(reader);
                }
            }
        }
        catch
        {

        }

我不确定这是最好的解决方案 - 但它确实有效。我很想知道是否有其他人有更好的方法来处理这个问题。

【讨论】:

    【解决方案2】:

    感谢 G Bradley,我接受了他的回答并对其进行了概括,以便更容易打电话。

        public static string SerializeToXmlString<T>(T objectToSerialize)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(T));
    
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = false;
            settings.Encoding = Encoding.UTF8;
            StringBuilder builder = new StringBuilder();
    
            using (XmlWriter writer = XmlWriter.Create(builder, settings))
            {
                serializer.Serialize(writer, objectToSerialize);
            }
    
            return builder.ToString();
        }
    
        public static T DeserializeFromXmlString<T>(string xmlString)
        {
            if (string.IsNullOrWhiteSpace(xmlString))
                return default;
    
            var serializer = new XmlSerializer(typeof(T));
            byte[] byteArray = Encoding.UTF8.GetBytes(xmlString);
            MemoryStream stream = new MemoryStream(byteArray);
            using (StreamReader sr = new StreamReader(stream, false))
            {
                using (var reader = XmlReader.Create(sr))
                {
                    return (T)serializer.Deserialize(reader);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2011-01-11
      • 1970-01-01
      • 2014-08-21
      • 2013-02-25
      • 2023-03-06
      • 2015-12-06
      • 2017-01-20
      • 1970-01-01
      • 2015-01-28
      相关资源
      最近更新 更多