现在的位置: 首页 > 综合 > 正文

字符串的长度Check

2014年02月28日 ⁄ 综合 ⁄ 共 3700字 ⁄ 字号 评论关闭

C#处理输入字符串的最大长度的时候常常会遇到Unicode编码方式和ANSI编码方式的困扰,尤其是在英数字与汉字混合的情况下。因为数据库中,数据的长度不管是char还是varchar都是使用ANSI来计算字节数的,而在C#中,无论是string.length还是string.substring等方法都是使用Unicode来计算字符个数的,甚至在Textbox中MaxLength属性中也是使用的计算Unicode字符个数的方法,这就给我们文章开头叙述的那种情况带来了很大的麻烦。
    事实上,解决这样的问题也并不困难,下面是我总结出的几种常见常用到的方法:
一、直接获取字符串的ASCI字节数,根据此数来进行长度判断
       System.Text.Encoding.Default.GetByteCount(p_sContext)
       该语段返回一个int型的值,表示字符串p_sContext的ASCI字节数
    这种做法很简单,显示当中也很实用,相应的由ASCI向Unicode转换的方法也很容易
    
二、另外就是在网上看到一个为 TextBox 控件增加一个限制最大字节数的属性的文章
   (http://www.cnblogs.com/lemony/archive/2007/04/10/707474.html)
    觉得想法很好,毕竟对于输入字符串的长度进行Check大多数是在TextBox文本框中的,这种做法有点一劳永逸的意思,即使不是TextBox也可以借鉴,比如ComboBox、TextArea等等

为 textbox 增加一个限制最大字节数的属性:MaxByteLength 。

建立新组件

我们先新建一个组件 TextBoxEx,继承于 TextBox ,增加一个 MaxByteLength  属性

public partial class TextBoxEx : TextBox
    {
        public TextBoxEx()
        {
            InitializeComponent();
        }

        #region 属性

        private int m_MaxByteLength = 0;
        [Description("获取或设置用户可在文本框控件中键入或粘贴的最大字节数。0 为允许无限长度。")]
        /// <summary>
        /// 获取或设置用户可在文本框控件中键入或粘贴的最大字节数。0 为允许无限长度。
        /// </summary>
        public int MaxByteLength
        {
            get { return m_MaxByteLength; }
            set { m_MaxByteLength = value; }
        }
}

然后重写 WndProc ,实现输入和粘贴的时候对字节长度进行判断。(已修正输入“.”号没有判断的问题)

        protected override void WndProc(ref Message m)
        {
            //如果该属性没有设置,则允许输入
            if (m_MaxByteLength == 0)
            {
                base.WndProc(ref m);
                return;
            }

            switch (m.Msg)
            {
                case WM_CHAR:
                    int i = (int)m.WParam;
                    bool isBack = (i == (int)Keys.Back);
                    bool isCtr = (i == 24) || (i == 22) || (i == 26) || (i == 3);

                    if (isBack || isCtr)
                    {
                        //控制键不作处理
                    }
                    else
                    {
                        char c = (char)i;
                        if (CheckByteLengthFlow(c.ToString()))
                        {
                            break;
                        }
                    }
                    base.WndProc(ref m);
                    break;
                case WM_PASTE:
                    IDataObject iData = Clipboard.GetDataObject();//取剪贴板对象
                    if (iData.GetDataPresent(DataFormats.Text)) //判断是否是Text
                    {
                        string text = (string)iData.GetData(DataFormats.Text);//取数据
                        if (CheckByteLengthFlow(text))
                        {
                            m.Result = (IntPtr)0;//不可以粘贴
                            break;
                        }
                    }
                    base.WndProc(ref m);
                    break;
                default:
                    base.WndProc(ref m);
                    break;
            }
        }

        /// <summary>
        /// 判断即将输入的文本长度是否溢出
        /// </summary>
        /// <param name="text">文本</param>
        /// <returns>是否溢出</returns>
        private bool CheckByteLengthFlow(string text)
        {
            int len = GetByteLength(text);    //输入的字符的长度
            int tlen = GetByteLength(this.Text);  //文本框原有文本的长度
            int slen = GetByteLength(this.SelectedText);    //文本框选中文本的长度
            return (m_MaxByteLength < (tlen - slen + len));
        }

        /// <summary>
        /// 计算文本字节长度,区分多字节字符
        /// </summary>
        /// <param name="text">文本</param>
        /// <returns>文本字节长度</returns>
        private int GetByteLength(string text)
        {
            return System.Text.Encoding.Default.GetBytes(text).Length;
        }

另外,增加一个 RealText 属性,该属性返回具有合法长度的文本, 不会截断多字节字符

public string RealText
        {
            get
            {
                if (m_MaxByteLength == 0)
                {
                    return this.Text;
                }

                if (m_MaxByteLength >= GetByteLength(this.Text))
                {
                    return this.Text;
                }

                string text = this.Text;

                if (string.IsNullOrEmpty(text))
                {
                    return text;
                }

                char[] c = text.ToCharArray();
                StringBuilder sb = new StringBuilder();
                int count = 0;

                for (int i = 0; i < c.Length; i++)
                {
                    count += GetByteLength(c[i].ToString());
                    if (m_MaxByteLength >= count)
                    {
                        sb.Append(c[i]);
                    }
                }

                return sb.ToString();
            }
        }

至此,可以通过设置 MaxByteLength  来限制最大字节数了。

抱歉!评论已关闭.