string 字符串
String 字符串以Unicode表示
Unicode : https://www.qqxiuzi.cn/zh/unicode-zifu.php
多字节字符
string 字符串 ,word 字符,char 对象,Byte 字节
多字节字符:1个字符占用 多个 Byte 字节
UTF-8编码中 字符 word 对象 char 字节 byte 位 bit 任意 1个 1~3个 1~ 6个 8 ~ 48个 英文和半角符号 1个 1个 1个 8个 中文和全角符号 1个 1个 3个 24 但是有一种 字符 ,把多个字符 通过 零宽度连接符 连接 表示成 1个字符,比如 👨👩👧👦 占用11个 char Byte 字节:不同的编码方式将字符转为字节时会占不同长度的字节。
编程需求: 需要字符串分隔为字符 ? 或者求字符串有几个字符?
为什么要求字符串有几个字符?
1.编程中要舍弃特定的字符,表情字符\中文字符\繁体字符
2.绘制字符在屏幕时需要知道字符个数,才能准确的计算出每个字符的坐标,和占用的屏幕像素长宽
编码求字符串 占用char与字节数量,和有几个字符.
private void button1_Click(object sender, EventArgs e) { string text = "斗a1"; int charCount = text.Length; //charCount=3,表示有3个char var characterCount = SplitToCharacters(text).ToArray().Length; //求字符串有几个字符?characterCount=3,有3个字符 char c1 = text[0]; //c1=26007'斗' 字符 byte[] bytes = System.Text.Encoding.UTF8.GetBytes(c1 + ""); int byteCount = bytes.Length; //'斗' 字符,在UTF8编码中占用3个字节 char c2 = text[1]; //c2=97'a' 字符 byte[] bytes2 = System.Text.Encoding.UTF8.GetBytes(c2.ToString()); byteCount = bytes2.Length; //'a' 字符,在UTF8编码中占用1个字节 char c3 = text[2]; //c3=49'1' 字符 byte[] bytes3 = System.Text.Encoding.UTF8.GetBytes(c3 + ""); byteCount = bytes3.Length; //'1' 字符,在UTF8编码中占用1个字节 byte[] bytes8 = System.Text.Encoding.UTF8.GetBytes(text); byteCount = bytes8.Length; //"斗a1"字符串,在UTF8编码中占用5个字节 string StrConv = "😁"; charCount = StrConv.Length; // charCount=2,,表示有2个char var characterCount3 = SplitToCharacters("😁").ToArray().Length; //求字符串有几个字符? characterCount3=1,有1个字符 char a = StrConv[0]; //a=55357'\ud83d' byte[] bytes4 = System.Text.Encoding.UTF8.GetBytes(a + ""); byteCount = bytes4.Length; //'\ud83d'字符,在UTF8编码中占用3个字节 bool isHigh1 = char.IsHighSurrogate(a); //isHigh1=true,是高字节,说明这个 char无法容纳一个字符,包含下一个char char b = StrConv[1]; //b=56833'\ude01' byte[] bytes5 = System.Text.Encoding.UTF8.GetBytes(b + ""); byteCount = bytes5.Length; //'\ude01' 字符,在UTF8编码中占用3个字节 bool isHigh2 = char.IsHighSurrogate(b); //isHigh2=false,不是高字节 byte[] bytes9 = System.Text.Encoding.UTF8.GetBytes(StrConv); byteCount = bytes9.Length; //"😁"字符串,在UTF8编码中占用4个字节 string text3 = ".1a中😁👨👩👧👦"; charCount = text3.Length; // charCount=17,表示有17个char var characterCount2 = SplitToCharacters(text3).ToArray().Length; //求字符串有几个字符? characterCount2=6,有6个字符 } /// <summary> /// 把字符串 分割 为字符,每个字符为string类型,,by :https://mp.weixin.qq.com/s/vWKqIrO9CK9PIZr7GtUv7w /// </summary> /// <param name="input"></param> /// <returns></returns> IEnumerable<string> SplitToCharacters(string input) { for (var i = 0; i < input.Length; ++i) { if (char.IsHighSurrogate(input[i])) { int length = 0; while (true) { length += 2; if (i + length < input.Length && input[i + length] == 0x200D) { length += 1; } else { break; } } yield return input.Substring(i, length); i += length - 1; } else { yield return input[i].ToString(); } } }
String.Length 是告诉 Char 对象的个数 ,而不是字符 的个数
如果一个
char
无法容纳一个字符,char.IsHighSurrogate(char a)
方法传入这个char
就会返回true
,“零宽度连接符” 值为
0x200D
。如果发现char
为该值,则说明它是一个零宽度连接符,此时后面的emoji
应该与前面的emoji
连接。
emoji 表情包 编码
emoji 编码:https://www.qqxiuzi.cn/zh/emoji.html
string 字符串 包含emoji 分割字符方法: https://mp.weixin.qq.com/s/vWKqIrO9CK9PIZr7GtUv7w
简体中文 转换 繁体中文
安装 NuGet
包 CHTCHSConv
字符清洗 不可见字符清洗
通过借鉴 Excel.CLEAN
CLEAN函数从给定文本中删除32位ASCII代码中的第一个7非打印字符(值0到31)。 在Unicode字符集中,还有其他非打印字符(值127,129,141,143,144和157)。 对于这些其他不可打印的字符,CLEAN功能不会自行删除。
C# string 字符串清洗,通过正则表达式 把字符替换为空
public static string CLEAN( string str)
{
string pattern = "[\u0000-\u0031|\u0127|\u0129|\u0141|\u0143|\u0144|\u0147|\u0157]";
str = Regex.Replace(str, pattern, "");
return str;
}
字符常识总结
在 windows 系统下的 Unicode 是UTF-16编码;linux则使用UTF-8或UTF-32。
在 windows 系统 上汉字的编码是(Gb2312)
GB2312 (GBK): 英文使用16位二进制(即二个字节),中文使用16位二进制 (即二个字节) ,为了区分中文,将其最高位都设定成1
UTF-8: 英文使用 8位二进制(即一个字节),中文使用24位二进制 (即三个字节)
GB18030: 英文使用16位二进制(即二个字节),中文使用16位二进制 (即二 个字节)或者使用32位二进制 (即四个字节)中、英文字符均使用双字节来表示,为了区分中文,将其最高位都设定1.
big5支持繁体中文
utf-8支持几乎所有字符
gb2312是简体中文的码
gbk :对GB2312编码的扩充,支持中简繁 ,日韩字符
GB18030:对gbk 编码基础上的扩充,,支持中简繁 ,日韩字符 ,藏文、蒙文、维吾尔文
在gbk同一个汉字在 GBK18030、GBK、GB2312 三个编码方案中是相同的编码。
gbk是字符集与编码一起定义的,包含这两部分,所以有多少汉字的定义。
utf-8仅是编码,不包含字符集,utf-8 的字符集是unicode
utf-8 20多亿
对中文的支持力度
utf-8目前容纳的汉字范围小于gbk编码 ,有些偏僻字、少数民族的字,utf8不能完全表达, gbk可以正常显示.
GBK、GB2312等与UTF8之间都必须通过Unicode编码才能相互转换:
GBK、GB2312--Unicode--UTF8
UTF8--Unicode--GBK、GB2312
在C#中,string里包含的中文字符只占一个字符长度,也就是一个Char对象
1个汉字字符存储需要2个字节,1个英文字符存储需要1个字节。
Unicode字符的\u4E00到\u9FA5之间为汉字编码,所以使用它来表示汉字的正则匹配范围。
String.Length 属性返回 字符个数,无论字母或者汉字或者符号都是算1个,此实例中 Char 对象的个数
System.Text.Encoding.UTF8.GetBytes(String ).Length 返回的是此编码下字符串所占用的字节数
string text = "程a序12集3";
Debug.Log(text.Length); //7
int chinesLen = System.Text.Encoding.UTF8.GetBytes(text).Length;
Debug.Log(chinesLen); //13
Unicode编码16进制是倒着的 这个叫 大小端 FF FE
比如"集"这个汉字的16进制按照顺序是c696 ,但是Unicode编码要倒着96c6
各种编码
using System;
using UnityEngine;
using System.Text;
public class Test9 : MonoBehaviour
{
void Awake()
{
string text = "斗";
Test2(text, Encoding.UTF8);
Test2(text, Encoding.Unicode);
Test2(text, Encoding.UTF32);
Test2(text, Encoding.GetEncoding("BIG5"));
Test2(text, Encoding.GetEncoding("GB18030"));
Test2(text, Encoding.GetEncoding("gb2312"));
Debug.Log("系统默认的编码格式:"+System.Text.Encoding.Default.HeaderName.ToString());
}
void Test2(string text, Encoding code)
{
//此编码下字符串所占用的字节数
int chinesLen = code.GetBytes(text).Length;
for (int i = 0; i < text.Length; i++)
{
char c = text[i];
//把char再度转换为字符串。
string danGeZi = c.ToString();
//得到这个字符的UTF8编码的字节数组
byte[] bytes = code.GetBytes(danGeZi);
//这个字的十六进制字符串
string binStr = "";
//这个字的十进制进制字符串
string octStr = "";
//这个字的十六进制字符串
string hexStr = "";
for (int j = 0; j < bytes.Length; j++)
{
byte b = bytes[j];
//计算二进制,把字节转换成二进制字符串,"00111100"
string erStr = System.Convert.ToString(b, 2);
//Ascii字符转换后是6位或者7位,所以就在前面补0,补足8位
while (erStr.Length < 8)
{
erStr = "0" + erStr;
}
//"00111100"转换成"0011 1100",就是隔4位数添加空格
erStr = erStr.Insert(4, " ");
binStr = binStr + erStr + (j == bytes.Length - 1 ? "" : " , ");
//计算16进制,Unicode编码16进制的顺序是倒着的
if (code == Encoding.Unicode)
{
string str16 = System.Convert.ToString(b, 16);
//把字节转换成16进制字符串,"af"
hexStr = str16 + hexStr;
}
else
{
string str16 = System.Convert.ToString(b, 16);
//把字节转换成16进制字符串,"af"
hexStr = hexStr + str16;
}
}
octStr = Int32.Parse(hexStr, System.Globalization.NumberStyles.HexNumber).ToString();
Debug.Log(""
+" ,二进制: " + binStr
+" ,十进制: " + octStr
+ " ,十六进制: " + hexStr.ToUpper()
+" ,字符:" + danGeZi
+ " ,占用内存:" + bytes.Length + " Byte(字节)"
+ " ,编码" + code.BodyName);
}
}
}