前后台实现精确截取指定长度字符串(考虑全角半角)
页面上很多显示新闻列表时,考虑面子问题,常常需要限制标题长度。
以前都是用
<%#Eval("title").ToString().Length > 10 ? Eval("title").ToString().Substring(0, 8) + "..." : Eval("title").ToString()%>
这样的方式实现,这样代码即繁多又不能重用,不过这个还不是问题,因为可以在后台写个传字符串和指定长度的方法来简化。
问题是很多情况下要截取的字符串里即有汉字也有字母数字标点符号甚至是空格等。
如此以来就会出现这样的情况
博客园万岁万岁万万岁
博客园成立于20...
12345678...
而实际上,下面两条数据可能是“博客园成立于2004年”“12345678910111213”虽然超过了10个字符,但是长度足以全部显示。
博客园万岁万岁万万岁
博客园成立于2004年
12345678910111213
这时候就需要考虑字符本身是全角还是半角。我终于忍不住这个问题,自己写了个可以精确截取长度的方法,虽然没什么技术含量,但是很实用,这是属于细节问题,不是技术问题。
此方法按照全角长度截取,如“博客园成立于2004年”有11个字符,但有4个数字,属于半角,两个半角等于一个全角,所以此字符串相当于9个汉字。可以全部显示,为了尽可能满足样式,有奇数个半角字符并且影响到截取时,会截取x.5个全角。如“博客园万岁万岁万万s岁”则会截取为“博客园万岁万岁万万s”,如果“博客园万岁万岁万万sui”,则“博客园万岁万岁万万su”。
截取字符串(按全角长度,一个全角等于两个半角)
/// <summary>
/// 截取字符串(按全角长度,一个全角等于两个半角)
/// </summary>
/// <param name="str">字符串</param>
/// <param name="length">截取长度(全角)</param>
/// <param name="length1">此处填0</param>
/// <returns></returns>
public String InterceptString(String str, Int32 length, Int32 length1)
{
str = ClearBlank(str);
//System.Text.RegularExpressions.Regex.Replace(str, "");
if (str.Length > length)
{
if (length1 == 0)
{
length1 = length;
}
if (str.Length >= length1)
{
String str_left = str.Substring(0, length1);
String str_right = str.Remove(0, length1);
int banjiao = 0, other = 0;
char[] chars = str_left.Trim().ToCharArray();
foreach (char ch in chars)
{
if (ch >= 33 && ch <= 126)
{
banjiao++;
}
else// if(ch>=65281 && ch<=65374)
{
other++;
}
}
if ((other + (float)banjiao / 2) > length || (other + (float)banjiao / 2) - length == 0.5)
{
str_left = str_left.Remove(str_left.Length - 1, 1);
return str_left;
}
else if ((other + (float)banjiao / 2) - length != 0)
{
if (length1 + 1 <= str.Length)
{
str_left = InterceptString(str, length, length1 + 1);
}
}
return str_left;
}
else
{
return str;
}
}
else
{
return str;
}
}
/// <summary>
/// 去掉字符串中所有空格
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public String ClearBlank(String str)
{
CharEnumerator myenum = str.GetEnumerator();
str = String.Empty;
while (myenum.MoveNext())
{
byte[] array = new byte[1];
array = System.Text.Encoding.ASCII.GetBytes(myenum.Current.ToString());
int asciiCode = (short)(array[0]);
if (asciiCode != 32)
{
str += myenum.Current.ToString();
}
}
return str;
}
<%#InterceptString(Eval("title").ToString(), 10, 0)%>
各种情况显示效果
原字符串 截取后
博客园万岁万岁万万岁 博客园万岁万岁万万岁 (少于等于10个,正常显示)
博客园成立于2004年 博客园成立于2004年 (大于10个但有半角字符,按两个半角等于一个全角长度)
博客园万岁万岁万万sui 博客园万岁万岁万万su (截取到整10个全角长度正好)
博客园万岁万岁万万s岁 博客园万岁万岁万万s (多截取一个字符大于10则不截,截取9.5全角长度)
另附上js版:
//按指定长度截取字符串(按全角长度)
代码
function InterceptString(str,length,length1)
{
str=str.replace(/[" "|" "]/g,"");//去半角+全角空格
//str=str.replace(/\s+/g,"");//去半角空格
//str=str.replace(/[\u3000]/g,"")去全角空格
//str=str.replace(/\s/ig,'');去半角空格
if(str.length>length)
{
if(length1==0)
{
length1=length;
}
if (str.length >= length1)
{
var str_left = str.substr(0, length1);
var str_right = str.substr(length1);
var banjiao = 0;
var quanjiao = 0;
var strCode;
for(var i=0;i<str_left.length;i++)
{
strCode=str.charCodeAt(i);
if (strCode>= 33 && strCode <= 126)
{
banjiao++;
}
else
{
quanjiao++;
}
}
if ((quanjiao + banjiao / 2) > length || (quanjiao + banjiao / 2) - length == 0.5)
{
str_left = str_left.substr(0,str_left.length-1);
return str_left;
}
else if ((quanjiao + banjiao / 2) - length != 0)
{
if (length1 + 1 <= str.length)
{
str_left = InterceptString(str, length, length1 + 1);
}
}
return str_left;
}
}
}
其实在网页里面显示出来的字母I和M以及1和9是没有差异的
如图: (10个i&I 10个m&M 10个汉字“我”)可以看出来一个汉字相当于两个字母以及数字,当然还有标点等一些特殊符号