C# Unicode 编码代理项错误处理
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组装电脑配置单推荐报价格
推荐阅读
留言与评论(共有 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 |