直接用 Random.Next() 生成汉字会出错,因汉字Unicode码点集中在0x4E00–0x9FA5,盲目取0–65535会命中控制符、代理区等非法值;应使用Next(0x4E00, 0x9FA6)生成合法BMP汉字char。

为什么直接用 Random.Next() 生成汉字会出错
因为汉字不是单字节字符,UTF-16(C# 默认字符串编码)中一个汉字通常占 2 个字节(如 '中' 的 Unicode 码点是 U+4E2D),而 Random.Next() 只能返回整数,若盲目映射到 0–65535 范围,会命中大量控制字符、标点、日文假名甚至无效码点,导致显示为方块、问号或抛出 ArgumentException。
真正可用的常用汉字集中在 Unicode 的「中日韩统一汉字」基本区:0x4E00(一)到 0x9FFF(鿿),共约 20902 个字符。但要注意:该区间内仍有少量空码位和兼容字符,实际建议收缩到更稳妥范围。
- 推荐安全范围:
0x4E00~0x9FA5(含常用字及部分扩展 A 区),共 20902 个码点 - 避免使用
0x3400~0x4DBF(扩展 A 区)——部分字体不支持,渲染异常 - 不要用
Encoding.UTF8.GetBytes()或Encoding.Default中转——中文系统下Default可能是 GB2312,会丢失生僻字
用 char + Random 直接构造汉字最简单可靠
C# 的 string 基于 UTF-16,char 是 UTF-16 code unit,而绝大多数汉字(包括全部基本区)都能用单个 char 表示(即 BMP 内)。所以无需编码转换,直接生成合法码点再转 char 即可。
var rand = new Random(); int unicode = rand.Next(0x4E00, 0x9FA6); // 注意上限是 0x9FA6(右开区间) char hanzi = (char)unicode; string result = hanzi.ToString(); // 如 "你"
- 必须用
Next(min, max)的右开区间语义,0x9FA5是最后一个有效汉字,所以上限传0x9FA6 - 不要用
(char)rand.Next(65536)—— 会高频命中0xD800–0xDFFF(代理对区域),导致ArgumentException - 如果需要多个汉字,循环调用即可;不要尝试一次性生成
char[]后new string()——没坏处但无必要
想从 GB2312 字库取字?别碰 Encoding.GetEncoding("GB2312")
虽然 GB2312 编码表里汉字是连续的(0xB0A1–0xF7FE),但用 Encoding.GetEncoding("GB2312").GetChars() 反向解码极易出错:一是 GB2312 是双字节编码,需传入正确字节数组;二是 .NET 对 GB2312 支持不完整,遇到未定义码位会返回 '';三是无法覆盖现代常用字(如「嗯」「婠」等后增字)。
- 真实场景中,没人用 GB2312 限定汉字范围——它早已被 GBK / GB18030 取代
- 若硬要兼容旧系统,应直接查 GB18030 码表(四字节变长),但复杂度远超需求
- 结论:绕过所有
Encoding类方法,坚持 Unicode 码点生成,省事且兼容性最好
生成「看起来像中文」的字符串时,注意字频偏差
纯随机选码点会导致「龘」「靁」「驫」这类生僻字和「的」「了」「在」等高频字出现概率完全一致,结果不像真实文本。若用于测试或模拟,建议预置常用字数组:
static readonly string CommonHanzi = "的一是在不了有和人就我这中与他为大来上们为要以就这中与他为大来上们为要以";
// 或读取本地文件加载 3000 常用字
var rand = new Random();
string randomWord = new string(Enumerable.Repeat(CommonHanzi, 5)
.Select(s => s[rand.Next(s.Length)])
.ToArray());
- 单纯趣味项目用全范围随机没问题;做 UI 测试、样本生成时,务必控制字频,否则会被产品质疑“这谁家用户打这么多生僻字”
- 别用
string.Concat(Enumerable.Range(...))拼接——性能差且不易调试 - 如果真要模拟输入法行为,得引入拼音映射或 NLP 分词库,那就超出「随机汉字」范畴了
真正麻烦的是需要保证生成结果可索引、可排序、可持久化——这时候就得考虑是否该用固定种子 new Random(123),以及是否要排除多音字异体字。这些细节,往往在第一次导出 Excel 报表发现「?」字排在「啊」前面时才想起来。











