注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Computer Science

I Pressed My Words Here. Will You Read ?

 
 
 

日志

 
 

JavaScript 中关于字符串字节长度的计算比较(含汉字字符串)  

2011-06-16 18:04:34|  分类: My Projects |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
书名:Code
豆瓣评分:9.5分(277人评价)
博主评价:
未评价很差较差还行推荐力荐
来自豆瓣读书资源
最近,由于在编写页面时,遇到需要判断用户输入字符串的字节长度。不幸的是,我得面向汉语用户。那种一个字占字节长度为英文字母两倍的文字。所以需要通过JS准确判断用户录入字符串字节长度是否超长。这样有助于高效利用数据库空间。
首先我习惯性的在网上搜索了相关代码,再将相关代码进行比较,参考其代码进行了大概3次优化,而得到了最高效的验证代码。
现在将测试代码及 测试结果记录在下方,供大家参考。

测试源代码:

    //  函数名称:checkHanStrByteLength
    //  功能说明:用于调用各个待测函数,执行测试
    //  参数说明:v_longLen 为用于测试的长字符串样本,v_maxLen 为允许的最大字节长度。
    //  返回值:无。测试中打印测试数据于页面
    function checkHanStrByteLength(v_longLen, v_maxLen){
        ////下面时待测试函数代码////
        //函数名:strByteLength
        //功能介绍:返回字符串的字节长度
        //参数说明:str 要检查的字符串
        //返回值:字符串长度
        function strByteLength(str)
        {
        var i,sum;
        sum=0;
        for(i=0;i<str.length;i++)
        {
        if ((str.charCodeAt(i)>=0) & (str.charCodeAt(i)<=255))
        sum=sum+1;
        else
        sum=sum+2;
        }
        return sum;
        } 
        function checkStrByteLength(txt,len){
            var sum = strByteLength(txt);
            if(sum > len)return false;
            else return true;
        }
        // 函数名:checkByteLength
        function checkByteLength(txt,len) {
            var txtLength = txt.length;
            if(txtLength  > len)return false;
            if(txtLength * 2 <= len)return true;
            //else len >= txtLength > len/2
            var zhMaxNum = len - txtLength;
            for(var i = 0; i< txtLength; i++){
                var word = txt.substring(i, 1);
                if(/[^\x00-\xff]/g.test(word))
                    zhMaxNum --;
            }
            if(zhMaxNum >=0)
                return true;
           
            else return false;
        }
        // 函数名:getBtyeLength
        function getByteLength(txt,len) {
            var txtLen = 0;
            for (var i = 0; i < txt.length; i++) {
            var word = txt.substring(i, 1);
            if (/[^\x00-\xff]/g.test(word))
                txtLen += 2;
             else
                txtLen++;
            }
            if (txtLen > len)
            return false;
             else
            return true;
        }
        // 函数名:checkByteLength2
        function checkByteLength2(txt,len){
            var txtLength = txt.length;
            if(txtLength  > len)return false;
            if(txtLength * 2 <= len)return true;
            //else len >= txtLength > len/2
            var zhMaxNum = len - txtLength;
            while(zhMaxNum && txtLength){
                var word = txt.substring(--txtLength, 1);
                if(/[^\x00-\xff]/g.test(word)) zhMaxNum --;
            }
            //alert(zhMaxNum + ';' + txtLength);
            if(zhMaxNum >0) return true;
            if(zhMaxNum == 0 && txtLength == 0) return true;
            else return false;
        }
        // 函数名:checkByteLength3
        function checkByteLength3(txt,len){
            var txtLength = txt.length;
            if(txtLength  > len)return false;
            if(txtLength * 2 <= len)return true;
            //else len >= txtLength > len/2
            var zhMaxNum = len - txtLength;
            while(zhMaxNum && txtLength){
                var charTxt = txt.charCodeAt(--txtLength);
                if(charTxt > 255 || charTxt < 0) zhMaxNum --;
            }
            //alert(zhMaxNum + ';' + txtLength);
            if(zhMaxNum >0) return true;
            if(zhMaxNum == 0 && txtLength == 0) return true;
            else return false;
        }

        ////开始测试各个函数的代码////
        var dMesg = '';
        var longStr = '';
        var longLen = v_longLen;
        var maxLen = v_maxLen;
        dMesg = dMesg + '比赛条件:被测试汉字' + longLen + '个;\t最大长度:' + maxLen  + '字节.\n比赛开始;\n';
        var d = new Date();
        var dtS = d.getTime();
        while(longLen--){
            longStr += '号';
        }
        var d = new Date();
        var dtE = d.getTime();
        var time = dtE - dtS;
        dMesg = dMesg + '样本字段生成开始于:' + dtS + '  样本字段生成结束于:' + dtE + '\n用时:' + time + '毫秒\n';
        var time1 = 0;
        var time2 = 0;
        var time3 = 0;
        var time4 = 0;
        var time5 = 0;
/* 前三种效率较低的方法在提供代码时,被我默认注释掉了。需要测试效果的请自己去掉注释。
        var d = new Date();
        var dtS = d.getTime();
        dMesg += 'getByteLength(txt):\n'
        dMesg = dMesg + '开始时间:' + dtS + '\n';
        dMesg = dMesg + '结果:' + getByteLength(longStr, maxLen) + '\n';
        var d = new Date();
        var dtE = d.getTime();
        dMesg = dMesg + '结束时间:' + dtE + '\n';
        time1 = dtE - dtS;
        dMesg = dMesg + '用时:' + time1 + '\n=================\n';
        var d = new Date();
        var dtS = d.getTime();
        dMesg = dMesg + 'checkBtyeLength(txt,len):\n开始时间:' + dtS + '\n';
        dMesg = dMesg + '结果:' + checkByteLength(longStr, maxLen) + '\n';
        var d = new Date();
        var dtE = d.getTime();
        dMesg = dMesg + '结束时间:' + dtE + '\n';
        time2 = dtE - dtS;
        dMesg = dMesg + '用时:' + time2 + '\n==================\n';
        var d = new Date();
        var dtS = d.getTime();
        dMesg = dMesg + 'checkBtyeLength2(txt,len):\n开始时间:' + dtS + '\n';
        dMesg = dMesg + '结果:' + checkByteLength2(longStr, maxLen) + '\n';
        var d = new Date();
        var dtE = d.getTime();
        dMesg = dMesg + '结束时间:' + dtE + '\n';
        time3 = dtE - dtS;
        dMesg = dMesg + '用时:' + time3 + '\n==================\n';
*/
        var d = new Date();
        var dtS = d.getTime();
        dMesg = dMesg + 'checkBtyeLength3(txt,len):\n开始时间:' + dtS + '\n';
        dMesg = dMesg + '结果:' + checkByteLength3(longStr, maxLen) + '\n';
        var d = new Date();
        var dtE = d.getTime();
        dMesg = dMesg + '结束时间:' + dtE + '\n';
        time4 = dtE - dtS;
        dMesg = dMesg + '用时:' + time4 + '\n==================\n';
        var d = new Date();
        var dtS = d.getTime();
        dMesg = dMesg + 'checkStrBtyeLength(txt,len):\n开始时间:' + dtS + '\n';
        dMesg = dMesg + '结果:' + checkStrByteLength(longStr, maxLen) + '\n';
        var d = new Date();
        var dtE = d.getTime();
        dMesg = dMesg + '结束时间:' + dtE + '\n';
        time5 = dtE - dtS;
        dMesg = dMesg + '用时:' + time5 + '\n==================\n';
        var minTime = Math.min(time1,time2,time3,time4,time5);
        dMesg =  dMesg + minTime + '\n';
/*
        if(minTime == time1){dMesg += '1胜!\n';}
        if(minTime == time2){dMesg += '2胜!\n';}
        if(minTime == time3){dMesg += '3胜!\n';}
*/
        if(minTime == time4){dMesg += '4胜!\n';}
        if(minTime == time5){dMesg += '5胜!\n';}
    /*
        switch(minTime){
            case time1: dMesg += '1胜!\n';break;
            case time2: dMesg += '2胜!\n';break;
            case time3: dMesg += '3胜!\n';break;
            default:dMesg += '\n';break;
        }
    */
    /*    if(time1 < time2 && time1 < time3) dMesg += '1胜!\n';
        else if(time3 < time) dMesg += '后者胜!\n';
        else dMesg += '平局\n';
    */
        dMesg += 'END';
        showMessage(dMesg,'\n');
    }
    ////调用、执行测试函数////
    checkHanStrByteLength(19200, 25600);//注意:测试时,即便只用最高效的代码,也不要提供10万级及以上的入参,否则,你能用等待的时间,完成这篇文章。

注意:测试时,即便只用最高效的代码,也不要提供10万级及以上的入参,否则,你能用等待的时间,完成这篇文章!
程序运行期间,循环生成大段用于测试的字符串相对计算过程耗时更多。
当前测试代码中于2011年6月17日14时47分59秒加入了对生成样本字段时间的计算。
例:

比赛条件:被测试汉字12801个; 最大长度:25600字节.
比赛开始;
样本字段生成开始于:1308293111635 样本字段生成结束于:1308293128669
用时:17034毫秒


测试比较结果(用时单位:毫秒):

测试环境:

Windows XP Pro SP3

IE 7

CPU T5670 1.8GHz

内存 78MHz 768MB

汉字个数<字节长度上限/2

汉字个数==字节长度上限/2

字节长度上限/2<汉字个数<字节长度上限

汉字个数==字节长度上限

汉字个数>字节长度上限

上万级字符长度测试:





比赛条件:被测试汉字6400个; 最大长度:25600字节.

比赛开始;

getByteLength(txt):

开始时间:1308214202423

结果:true

结束时间:1308214209262

用时:6839

=================

checkBtyeLength(txt,len):

开始时间:1308214209262

结果:true

结束时间:1308214209262

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214209262

结果:true

结束时间:1308214209262

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214209262

结果:true

结束时间:1308214209272

用时:10

==================

checkStrBtyeLength(txt,len):

开始时间:1308214209272

结果:true

结束时间:1308214209292

用时:20

==================

0

2胜!

3胜!

END

// 45表现不错

比赛条件:被测试汉字12800个; 最大长度:25600字节.

比赛开始;

getByteLength(txt):

开始时间:1308214007993

结果:true

结束时间:1308214033550

用时:25557

=================

checkBtyeLength(txt,len):

开始时间:1308214033550

结果:true

结束时间:1308214033550

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214033550

结果:true

结束时间:1308214033550

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214033550

结果:true

结束时间:1308214033550

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214033550

结果:true

结束时间:1308214033600

用时:50

==================

0

2胜!

3胜!

4胜!

END // 5表现不错

比赛条件:被测试汉字29200个; 最大长度:25600字节.

比赛开始;

getByteLength(txt):

开始时间:1308213590322

结果:false

结束时间:1308213710796

用时:120474

=================

checkBtyeLength(txt,len):

开始时间:1308213710796

结果:false

结束时间:1308213710796

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308213710796

结果:false

结束时间:1308213710806

用时:10

==================

checkBtyeLength3(txt,len):

开始时间:1308213710806

结果:false

结束时间:1308213710806

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308213710806

结果:false

结束时间:1308213710936

用时:130

==================

0

2胜!

4胜!

END

// 35表现不错

比赛条件:被测试汉字25600个; 最大长度:25600字节.

比赛开始;

getByteLength(txt):

开始时间:1308212951033

结果:false

结束时间:1308213045489

用时:94456

=================

checkBtyeLength(txt,len):

开始时间:1308213045489

结果:false

结束时间:1308213141838

用时:96349

==================

checkBtyeLength2(txt,len):

开始时间:1308213141848

结果:false

结束时间:1308213141848

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308213141848

结果:false

结束时间:1308213141858

用时:10

==================

checkStrBtyeLength(txt,len):

开始时间:1308213141858

结果:false

结束时间:1308213141968

用时:110

==================

0

3胜!

END

// 4 5 表现不错

比赛条件:被测试汉字30000个; 最大长度:25600字节.

比赛开始;

getByteLength(txt):

开始时间:1308212606408

结果:false

结束时间:1308212733791

用时:127383

=================

checkBtyeLength(txt,len):

开始时间:1308212733791

结果:false

结束时间:1308212733791

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308212733801

结果:false

结束时间:1308212733801

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308212733801

结果:false

结束时间:1308212733801

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308212733801

结果:false

结束时间:1308212733931

用时:130

==================

0

2胜!

3胜!

4胜!

END // 5表现不错

上千级字符长度测试:





比赛条件:被测试汉字1000个; 最大长度:3000字节.

比赛开始;

getByteLength(txt):

开始时间:1308214364836

结果:true

结束时间:1308214365016

用时:180

=================

checkBtyeLength(txt,len):

开始时间:1308214365016

结果:true

结束时间:1308214365016

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214365016

结果:true

结束时间:1308214365026

用时:10

==================

checkBtyeLength3(txt,len):

开始时间:1308214365026

结果:true

结束时间:1308214365026

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214365026

结果:true

结束时间:1308214365026

用时:0

==================

0

2胜!

4胜!

5胜!

END // 3表现不错

比赛条件:被测试汉字1500个; 最大长度:3000字节.

比赛开始;

getByteLength(txt):

开始时间:1308214479781

结果:true

结束时间:1308214480182

用时:401

=================

checkBtyeLength(txt,len):

开始时间:1308214480182

结果:true

结束时间:1308214480182

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214480182

结果:true

结束时间:1308214480182

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214480182

结果:true

结束时间:1308214480182

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214480182

结果:true

结束时间:1308214480192

用时:10

==================

0

2胜!

3胜!

4胜!

END // 5表现不错

比赛条件:被测试汉字2250个; 最大长度:3000字节.

比赛开始;

getByteLength(txt):

开始时间:1308214566015

结果:false

结束时间:1308214566967

用时:952

=================

checkBtyeLength(txt,len):

开始时间:1308214566967

结果:false

结束时间:1308214567858

用时:891

==================

checkBtyeLength2(txt,len):

开始时间:1308214567858

结果:false

结束时间:1308214568339

用时:481

==================

checkBtyeLength3(txt,len):

开始时间:1308214568339

结果:false

结束时间:1308214568339

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214568339

结果:false

结束时间:1308214568349

用时:10

==================

0

4胜!

END

// 5 表现不错

比赛条件:被测试汉字3000个; 最大长度:3000字节.

比赛开始;

getByteLength(txt):

开始时间:1308214613404

结果:false

结束时间:1308214614936

用时:1532

=================

checkBtyeLength(txt,len):

开始时间:1308214614936

结果:false

结束时间:1308214616528

用时:1592

==================

checkBtyeLength2(txt,len):

开始时间:1308214616528

结果:false

结束时间:1308214616528

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214616528

结果:false

结束时间:1308214616528

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214616528

结果:false

结束时间:1308214616548

用时:20

==================

0

3胜!

4胜!

END

// 5 表现不错

比赛条件:被测试汉字3250个; 最大长度:3000字节.

比赛开始;

getByteLength(txt):

开始时间:1308214678727

结果:false

结束时间:1308214680480

用时:1753

=================

checkBtyeLength(txt,len):

开始时间:1308214680480

结果:false

结束时间:1308214680480

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214680480

结果:false

结束时间:1308214680480

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214680480

结果:false

结束时间:1308214680480

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214680480

结果:false

结束时间:1308214680500

用时:20

==================

0

2胜!

3胜!

4胜!

END // 5 表现不错

上百级字符长度测试:





比赛条件:被测试汉字64个; 最大长度:256字节.

比赛开始;

getByteLength(txt):

开始时间:1308214772532

结果:true

结束时间:1308214772532

用时:0

=================

checkBtyeLength(txt,len):

开始时间:1308214772532

结果:true

结束时间:1308214772532

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214772532

结果:true

结束时间:1308214772532

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214772552

结果:true

结束时间:1308214772552

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214772552

结果:true

结束时间:1308214772552

用时:0

==================

0

1胜!

2胜!

3胜!

4胜!

5胜!

END

比赛条件:被测试汉字128个; 最大长度:256字节.

比赛开始;

getByteLength(txt):

开始时间:1308214813331

结果:true

结束时间:1308214813351

用时:20

=================

checkBtyeLength(txt,len):

开始时间:1308214813351

结果:true

结束时间:1308214813351

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214813351

结果:true

结束时间:1308214813351

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214813351

结果:true

结束时间:1308214813351

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214813351

结果:true

结束时间:1308214813351

用时:0

==================

0

2胜!

3胜!

4胜!

5胜!

END

// 1 表现不错

比赛条件:被测试汉字192个; 最大长度:256字节.

比赛开始;

getByteLength(txt):

开始时间:1308214858416

结果:false

结束时间:1308214858416

用时:0

=================

checkBtyeLength(txt,len):

开始时间:1308214858416

结果:false

结束时间:1308214858436

用时:20

==================

checkBtyeLength2(txt,len):

开始时间:1308214858436

结果:false

结束时间:1308214858436

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214858436

结果:false

结束时间:1308214858436

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214858446

结果:false

结束时间:1308214858446

用时:0

==================

0

1胜!

3胜!

4胜!

5胜!

END

// 2 表现不错

比赛条件:被测试汉字256个; 最大长度:256字节.

比赛开始;

getByteLength(txt):

开始时间:1308214907867

结果:false

结束时间:1308214907887

用时:20

=================

checkBtyeLength(txt,len):

开始时间:1308214907887

结果:false

结束时间:1308214907907

用时:20

==================

checkBtyeLength2(txt,len):

开始时间:1308214907907

结果:false

结束时间:1308214907907

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214907907

结果:false

结束时间:1308214907907

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214907917

结果:false

结束时间:1308214907917

用时:0

==================

0

3胜!

4胜!

5胜!

END

// 12表现不错

比赛条件:被测试汉字320个; 最大长度:256字节.

比赛开始;

getByteLength(txt):

开始时间:1308214953643

结果:false

结束时间:1308214953663

用时:20

=================

checkBtyeLength(txt,len):

开始时间:1308214953663

结果:false

结束时间:1308214953663

用时:0

==================

checkBtyeLength2(txt,len):

开始时间:1308214953663

结果:false

结束时间:1308214953663

用时:0

==================

checkBtyeLength3(txt,len):

开始时间:1308214953673

结果:false

结束时间:1308214953673

用时:0

==================

checkStrBtyeLength(txt,len):

开始时间:1308214953673

结果:false

结束时间:1308214953673

用时:0

==================

0

2胜!

3胜!

4胜!

5胜!

END

// 1 表现不错

测试人Will

测试印象:函数5中用的codeCharAt()效率相对substring高许多。根据函数5改良的函数4最稳定且高效。


函数1来源:http://cztom.net/post/2010/12/19/104.htm

函数234Will参考其他方法编写





函数5来源:http://www.angelasp.cn/Html/JS/cyhs/2011122229442057.html



测试结论:
函数5:checkStrByteLength(longStr, maxLen) 在用于计算字符串字节长度时,是首选的参考方案。
函数4:checkByteLength3(longStr, maxLen)在测试中表现最稳定、高效,是检查字符串字节长度是否超长的首选方案。

----------------------------------------------------------------------------------------
补充:十万级字符字节长度测试结果,函数4 150毫秒,函数5 982毫秒。


比赛条件:被测试汉字192000个; 最大长度:256000字节.
比赛开始;
checkBtyeLength3(txt,len):
开始时间:1308219831817
结果:false
结束时间:1308219831967
用时:150
==================
checkStrBtyeLength(txt,len):
开始时间:1308219831967
结果:false
结束时间:1308219832949
用时:982
==================
0
END

估计生成字符串太耗时了。
  评论这张
 
阅读(2494)| 评论(11)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017