C# string

 

 

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

 

简体中文 转换 繁体中文

安装 NuGetCHTCHSConv

 

字符清洗 不可见字符清洗

通过借鉴 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);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值