您现在的位置是:首页 > 编程 > 

C# Unicode 编码代理项错误处理

2025-07-28 20:09:40
C# Unicode 编码代理项错误处理 问题描述​在一个 XML 序列化与文件保存的业务中,出现了一个异常:“代理项对无效,缺少低代理项字符。”直接原因:业务提供的字符串中,有非法编码的字符。具体而言,就是如果出现了需要用代理项表示的字符,则必须成对出现(代理项对),前一个为高代理项,后一个为低代理项。 关于 Unicode 的代理项,可以参看:Unicode | 代理项(Surrogate)

C# Unicode 编码代理项错误处理

问题描述

在一个 XML 序列化与文件保存的业务中,出现了一个异常:“代理项对无效,缺少低代理项字符。”

直接原因:业务提供的字符串中,有非法编码的字符。具体而言,就是如果出现了需要用代理项表示的字符,则必须成对出现(代理项对),前一个为高代理项,后一个为低代理项。

关于 Unicode 的代理项,可以参看:Unicode | 代理项(Surrogate) - 云+社区 - 腾讯云

本质原因:业务层提供的字符串有问题,需要调查为什么会出现非法的代理项编码。

业务方可能的问题原因:

对于需要使用代理项字符来说,就自然含义来看,它是一个字符,但编码上由高代理+低代理组合成一个代理对来表示。在 C# 的代码下,如 string surrogateContent = “\ud85\udc01”,此时的 surrogateContent.Length 为 2。

所以就可能出现,在某些场景下,将其分开成两个“字符”了,但这两个“字符”都是非法的,因为其编码是在代理项区域,必须成对出现,合起来表示一个字符。

解决:

1 修复业务,不再产生非法字符。

2 存储层对于非法字符过滤掉,之后再进行 XML 序列化或者保存(先正常处理,出现异常,再检查是否有非法字符,处理之后再重试)。这种方式会造成数据的丢失,需要根据实际业务场景来决定是否可以这样处理。

场景复现

这里使用的 C# 代码

代码语言:javascript代码运行次数:0运行复制
public static string Test2(){    // 示例字符:高代理项 \ud85 低代理项 \udc01    char invalidChar = '\ud85';    string invalidStr = "\ud85";
    string surrogateContent = "\ud85"; // 代理项对无效,缺少低代理项字符。    string surrogateContent = "\udc01"; // 无效的高代理项字符(0x{0})。高代理项字符必须具有范围(0xD800 - 0xDBFF)内的值。    string surrogateContent = "\ud85\ud85"; // 代理项对 (0x{0}, 0x{1}) 无效。高代理项字符(0xD800 - 0xDBFF) 必须始终与低代理项字符(0xDC00 - 0xDFFF)成对。
    Cole.WriteLine(Char.IsSurrogate(invalidChar));    Cole.WriteLine(Char.IsSurrogatePair(invalidStr, 0));    Cole.WriteLine(Char.IsHighSurrogate(invalidChar));    Cole.WriteLine(Char.IsLowSurrogate(invalidChar));
    XElement element = new XElement("node")    {        Value = surrogateContent    };
    var document = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), element);
    using (var stringWriter = new StringWriter(CultureInfo.InvariantCulture))    {        var settings = new XmlWriterSettings        {            OmitXmlDeclaration = true,            Indent = true,            ewLineHandling = ewLineHandling.Entitize,        };        using (var writer = System.Xml.XmlWriter.Create(stringWriter, settings))        {            document.WriteTo(writer);        }        return stringWriter.ToString();    }}

因为代理项需要成对出现,前高后低,所以这里的错误一共有三种。

代码语言:javascript代码运行次数:0运行复制
1 Xml_InvalidSurrogatePairWithArgs  The surrogate pair (0x{0}, 0x{1}) is invalid. A high surrogate character (0xD800 - 0xDBFF) must always be paired with a low surrogate character (0xDC00 - 0xDFFF).  代理项对 (0x{0}, 0x{1}) 无效。高代理项字符(0xD800 - 0xDBFF) 必须始终与低代理项字符(0xDC00 - 0xDFFF)成对。
2 Xml_InvalidSurrogateMissingLowChar  The surrogate pair is invalid. Missing a low surrogate character.  代理项对无效,缺少低代理项字符。
 Xml_InvalidSurrogateHighChar  Invalid high surrogate character (0x{0}). A high surrogate character must have a value from range (0xD800 - 0xDBFF).  无效的高代理项字符(0x{0})。高代理项字符必须具有范围(0xD800 - 0xDBFF)内的值。

相关的源码:

代码语言:javascript代码运行次数:0运行复制
private static unsafe char* EncodeSurrogate( char* pSrc, char* pSrcEnd, char* pDst ) {    Debug.Assert( XmlCharType.IsSurrogate( *pSrc ) );
    int ch = *pSrc;    if ( ch <= XmlCharType.SurHighEnd ) {        if ( pSrc + 1 < pSrcEnd ) {            int lowChar = pSrc[1];            if ( lowChar >= XmlCharType.SurLowStart &&                (LocalAppContextSwitches.DontThrowOnInvalidSurrogatePairs || lowChar <= XmlCharType.SurLowEnd)) {
                pDst[0] = (char)ch;                pDst[1] = (char)lowChar;                pDst += 2;
                return pDst;            }            throw XmlConvert.CreateInvalidSurrogatePairException( (char)lowChar, (char)ch );        }        throw new ArgumentException( Res.GetString( Res.Xml_InvalidSurrogateMissingLowChar ) );    }    throw XmlConvert.CreateInvalidHighSurrogateCharException( (char)ch );}

由于都是 ArgumentException,所以不是很好区分,不严谨的处理方式是,根据 Message 来判断。

代码语言:javascript代码运行次数:0运行复制
/// <summary>/// 是否字符代理项相关的异常/// </summary>/// <param name="ex"></param>/// <returns></returns>public static bool IsSurrogateException(ArgumentException ex){    if (ex.Message.Contains("代理项字符") ||        ex.Message.ToLower().Contains("surrogate"))    {        return true;    }    else    {        return false;    }}
相关内容

C# 的 char 类型是 UTF-16 编码的字符。

char type - C# reference | Microsoft Docs

C# Char 下有多个方法可以进行代理项相关的判断。

Char.IsSurrogate 方法 (System) | Microsoft Docs

.ET 中的字符编码

.ET 中的 character 编码简介 | Microsoft Docs

Unicode | 代理项(Surrogate)

Unicode | 代理项(Surrogate) - 云+社区 - 腾讯云

字符编码查询工具

汉字字符集编码查询;中文字符集编码:GB212、BIG5、GBK、GB1800、Unicode

原文链接:

本作品采用 「署名 4.0 国际」 许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2022年月11日 ,如有侵权请联系 cloudcommunity@tencent 删除c#unicode编码代理字符编码

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1222166.html

相关标签:无
上传时间: 2025-07-25 18:15:26
留言与评论(共有 9 条评论)
本站网友 布雷诺
15分钟前 发表
出现了一个异常:“代理项对无效
本站网友 生死有命富贵在天
22分钟前 发表
前一个为高代理项
本站网友 健脾养胃粥
17分钟前 发表
在某些场景下
本站网友 本地导航
2分钟前 发表
需要调查为什么会出现非法的代理项编码
本站网友 伊犁美食
26分钟前 发表
2 Xml_InvalidSurrogateMissingLowChar The surrogate pair is invalid. Missing a low surrogate character. 代理项对无效
本站网友 superoneclick
6分钟前 发表
Cole.WriteLine(Char.IsSurrogate(invalidChar)); Cole.WriteLine(Char.IsSurrogatePair(invalidStr
本站网友 t行动
23分钟前 发表
原始发表:2022年月11日
本站网友 米兰理工大学
1分钟前 发表
Char.IsSurrogate 方法 (System) | Microsoft Docs.ET 中的字符编码 .ET 中的 character 编码简介 | Microsoft DocsUnicode | 代理项(Surrogate) Unicode | 代理项(Surrogate) - 云+社区 - 腾讯云字符编码查询工具 汉字字符集编码查询;中文字符集编码:GB212