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 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 ,实现输入和粘贴的时候对字节长度进行判断。(已修正输入“.”号没有判断的问题)
{
// 如果该属性没有设置,则允许输入
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 属性,该属性返回具有合法长度的文本, 不会截断多字节字符
{
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 来限制最大字节数了。