开发C#怎么判断字符串包含中文 C#如何识别字符编码区间干货|Duuu笔记
深入理解前端原理,本文探讨
最可靠方法是遍历字符串并用char.IsSurrogate()配合char.ConvertToUtf32()检测Unicode码点,覆盖\u4e00-\u9fff、\u3400-\u4dbf及U+20000-U+2EBEF等全部中日韩汉字区块,避免漏字或误判。
用
char.IsSurrogate
和 Unicode 区间判断是否含中文最可靠
直接看字符的 Unicode 码点范围,比依赖编码或正则更稳。C# 的
string
是 UTF-16 编码,但中文字符分散在多个区块(基本汉字、扩展 A/B/C/D/E/F/G、兼容汉字等),不能只查
\u4e00-\u9fff
。
常见错误是只匹配
\u4e00-\u9fff
,漏掉「?」「㐂」「㐀」这类扩展区汉字,甚至把日文平假名(如
\u3040-\u309f
)误判为中文;还有人用
Encoding.GetEncoding("GB2312").GetBytes()
反推,结果遇到含 emoji 或生僻字就抛
EncoderFallbackException
。
\u4e00-\u9fff
:仅覆盖常用汉字,约 2 万字,缺大量人名、地名用字
必须补上
\u3400-\u4dbf
(扩展 A)、
U+20000-U+2A6DF
(扩展 B)、
U+2A700-U+2B73F
(扩展 C)等——这些需用
char.IsSurrogate()
配合
char.ConvertToUtf32()
检测
避免用
Regex.IsMatch(s, @"[\u4e00-\u9fff]")
单独判断,性能差且覆盖不全
推荐函数:遍历 +
char.IsSurrogate
+
char.ConvertToUtf32
这是 .NET 5+ 最轻量、最准的方式,不依赖外部库,也不触发编码转换开销。
示例逻辑:
白瓜AI
白瓜AI,一个免费图文AI创作工具,支持 AI 仿写,图文生成,敏感词检测,图片去水印等等。
下载
public static bool ContainsChinese(string s)
{
if (string.IsNullOrEmpty(s)) return false;
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (char.IsHighSurrogate(c) && i + 1 < s.Length && char.IsLowSurrogate(s[i + 1]))
{
int utf32 = char.ConvertToUtf32(c, s[i + 1]);
if ((utf32 >= 0x3400 && utf32 <= 0x4DBF) || // 扩展 A
(utf32 >= 0x20000 && utf32 <= 0x2A6DF) || // 扩展 B
(utf32 >= 0x2A700 && utf32 <= 0x2B73F) || // 扩展 C
(utf32 >= 0x2B740 && utf32 <= 0x2B81F) || // 扩展 D
(utf32 >= 0x2B820 && utf32 <= 0x2CEAF)) // 扩展 E/F/G
return true;
i++; // 跳过低代理项
continue;
}
if (c >= '\u4e00' && c <= '\u9fff') return true; // 基本区
if (c >= '\u3400' && c <= '\u4dbf') return true; // 扩展 A(BMP 内部分)
if (c >= '\u3000' && c <= '\u303f') return true; // 中文标点
}
return false;
}
注意:扩展 B 及之后的码点无法用单个
char
表示,必须检测代理对(surrogate pair)
别忘了中文全角标点(
\u3000-\u303f
),否则「,。!?;:」「『』「」」会被漏掉
如果只要判断「是否有任意一个中文字符」,找到即
return true
,别遍历到底
为什么不用
Encoding.UTF8.GetBytes()
或
Encoding.Default
判断?
编码方式不是字符属性,而是字节表示方式。同一个中文字符串,在 UTF-8、GBK、UTF-16 下字节完全不同,但字符本身没变——你真正想问的是“这个
char
或
string
里有没有中文字符”,不是“它当前以什么编码存的”。
用
Encoding.Default
(通常是 GBK)会受系统区域设置影响,在英文 Windows 上可能返回
Encoding.ASCII
,导致所有中文都变成
?
或乱码
用
Encoding.UTF8.GetBytes(s)
后扫描字节,会把 UTF-8 多字节序列当普通字节处理,比如「中」是
0xe4 0xb8 0xad
,但单独扫
0xe4
完全无意义
调用
Encoding.GetEncoding("GBK")
在 .NET Core/.NET 5+ 默认不启用,需手动注册,还可能抛
NotSupportedException
边界情况:Emoji、生僻字、古籍用字容易被忽略
像「?」(U+30000,扩展 B 起始)、「?」(U+20BB6,扩展 B)这种字,既不在 BMP,也不在常用区间,很多“中文检测”工具直接返回
false
。
它们在 C# 中占两个
char
(高代理 + 低代理),必须用
char.IsSurrogate()
捕获,再转成
int
码点判断
古籍用字(如《康熙字典》增补字)大量落在扩展 E/F/G(U+2B820–U+2CEAF),目前只有少数字体支持显示,但 Unicode 已收录
Emoji 如 ?(U+1F30F)虽在扩展区,但不属于中文——别把整个扩展区都当中文,要按具体码点范围筛
真要覆盖全,就得把 Unicode 官方《CJK Unified Ideographs》各扩展块都列进去,但实际项目里,至少得包含扩展 A+B+C,不然用户输入「䶮」「犇」「燚」就判定失败——这些字在身份证、企业名里很常见。
