美文网首页
计算和截取指定字符串的UTF-8字节数

计算和截取指定字符串的UTF-8字节数

作者: 躺在家里干活 | 来源:发表于2019-08-28 18:20 被阅读0次

由于特殊需求,需要限制输入框内容的长度,但是该长度并不是普通的字数长度而是UTF-8的字节数

UTF-8编码下 字节数

占2个字节的:〇
占3个字节的:基本等同于GBK,含21000多个汉字
占4个字节的:中日韩超大字符集里面的汉字,有5万多个
一个utf8数字占1个字节
一个utf8英文字母占1个字节

Unicode码

1个字节:Unicode码为0 - 127
2个字节:Unicode码为128 - 2047
3个字节:Unicode码为2048 - 0xFFFF
4个字节:Unicode码为65536 - 0x1FFFFF
5个字节:Unicode码为0x200000 - 0x3FFFFFF
6个字节:Unicode码为0x4000000 - 0x7FFFFFFF

计算指定字符串的字节数

function computeByteSize(str){
  for (var i=0,byte=0; i < str.length; i++) {
    var charCode = str.charCodeAt(i);
    if (0 <= charCode && charCode <= 0x7f) {
      byte += 1;
    } else if (128 <= charCode && charCode <= 0x7ff) {
      byte += 2;
    } else if (2048 <= charCode && charCode <= 0xffff) {
      byte += 3;
    } else if (65536 < charCode && charCode <= 0x1FFFFF) {
      byte += 4;
    } else if (0x200000 < charCode && charCode <= 0x3FFFFFF) {
      byte += 5;
    } else if (0x4000000 < charCode && charCode <= 0x7FFFFFFF) {
      byte += 6;
    }
  }
  return byte
}

//es6写法
function computeByteSize(str) {
  let byte=0;
  for (const chr of str) {
    //ES6提供了codePointAt方法,能够正确处理4个字节储存的字符,返回一个字符的码点
    //能正确地识别“?”,返回了它的十进制码点 134071(即十六进制的20BB7)
    let charCode = chr.codePointAt(0)
    if(0 <= charCode && charCode <= 0x7f) {
      byte += 1;
    } else if (128 <= charCode && charCode <= 0x7ff) {
      byte += 2;
    } else if (2048 <= charCode && charCode <= 0xffff) {
      byte += 3;
    } else if (65536 < charCode && charCode <= 0x1FFFFF) {
      byte += 4;
    } else if (0x200000 < charCode && charCode <= 0x3FFFFFF) {
      byte += 5;
    } else if (0x4000000 < charCode && charCode <= 0x7FFFFFFF) {
      byte += 6;
    }
  }
  return byte
}

截取指定字节数的字符串

function cutStr(str,L){
  for (var i=0,byte=0,result=''; i < str.length; i++) {
     var chr = str.charAt(i);
     var charCode = str.charCodeAt(i);
    if (0 <= charCode && charCode <= 0x7f) {
      byte += 1;
    } else if (128 <= charCode && charCode <= 0x7ff) {
      byte += 2;
    } else if (2048 <= charCode && charCode <= 0xffff) {
      byte += 3;
    } else if (65536 < charCode && code <= 0x1FFFFF) {
      byte += 4;
    } else if (0x200000 < charCode && charCode <= 0x3FFFFFF) {
      byte += 5;
    } else if (0x4000000 < charCode && charCode <= 0x7FFFFFFF) {
      byte += 6;
    }
    // 当加上当前字符以后,如果总字节长度小于等于L,则将当前字符真实的+在result后
    if(byte<=L){
      result += chr;
    }else{
      return result;
    }
  }
}

//es6 写法
function cutStr(str, L) {
  let byte=0;
  let result='';
  for(let chr of str){
    let charCode = chr.codePointAt(0)
    if (0 <= charCode && charCode <= 0x7f) {
      byte += 1;
    } else if (128 <= charCode && charCode <= 0x7ff) {
      byte += 2;
    } else if (2048 <= charCode && charCode <= 0xffff) {
      byte += 3;
    } else if (65536 < charCode && charCode <= 0x1FFFFF) {
      byte += 4;
    } else if (0x200000 < charCode && charCode <= 0x3FFFFFF) {
      byte += 5;
    } else if (0x4000000 < charCode && charCode <= 0x7FFFFFFF) {
      byte += 6;
    }
    // 当加上当前字符以后,如果总字节长度小于等于L,则将当前字符真实的+在result后
    if (byte <= L) {
      result += chr;
    } else {
      return result;
    }
  }
}

应用demo

<textarea></textarea>
<div class="number"></div>
<script type="text/javascript" src="js/jquery-3.2.1.js"></script>
<script type="text/javascript">
$(function(){
  //及时监听文本框内容的变化
  $("textarea").bind('input propertychange',function(){
    var str = $(this).val()
    var len = computeByteSize(str)
    if(len>256){
      $(this).val(cutStr(str,256))
    }else{
      $('.number').html(len)
    }
  });
})
</script>

但是目前截取字符串存在一些bug,如果直接复制一段中文内容到文本框,复制的内容超过限制的字节数,则会造成number的内容出错。而且如果输入的为中文,因为一个中文为3个字节数,一个拼音为一个字节数。所以也会出错。有可能造成最后的中文无法显示

注:汉字“?”(注意,这个字不是“吉祥”的“吉”)的码点是0x20BB7,UTF-16 编码为0xD842 0xDFB7(十进制为55362、57271),需要4个字节储存。对于这种4个字节的字符,JavaScript 不能正确处理,字符串长度会误判为2,而且charAt方法无法读取整个字符,charCodeAt方法只能分别返回前两个字节和后两个字节的值。因此ES6 提供了codePointAt方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点。codePointAt 方法在第一个字符上,正确地识别了“?”,返回了它的十进制码点 134071(即十六进制的20BB7)

我的个人博客,有空来坐坐

相关文章

  • 计算和截取指定字符串的UTF-8字节数

    由于特殊需求,需要限制输入框内容的长度,但是该长度并不是普通的字数长度而是UTF-8的字节数 UTF-8编码下 字...

  • Python字节数组与字符串之间的转换

    字节数组 ->字符串 bytes.decode() 字符串 -> 字节数组 str.encode('utf-8')...

  • 常用JS方法整理

    原文链接目录: 截取指定字节数的字符串 判断是否微信 获取时间格式的几个举例 获取字符串字节长度 对象克隆、深拷贝...

  • 个人JS工具库

    1.截取指定字节数的字符串 2.判断是否微信 3.获取时间格式的几个举例 4.获取字符串字节长度 5.对象克隆、深...

  • 2019-05-24

    例如,要截取一个字符串中,两个指定字符串中间的字符串,OC截取方法如下: // 要截取 "> 和

  • OC 字符串的截取

    1、字符串截取 2、从指定位置开始截取n个长度 3、分隔字符串 4、字符串的截取替换 5、替换掉截取某部分的字符串...

  • 常用shell

    AWK 多个分隔符 删除文件中包含指定字符串的行 替换指定字符串 截取n到m列 diff 文件差异 字符串截取 $...

  • 在指定编码环境下,按给定字节数截取字符串问题

    1、题目描述 在GBK编码环境下,编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。但...

  • 字符串(NSString)拼接、截取等

    一、NSString的截取 1.从字符串开头开始截取到指定位置(不包含该位置) 2.从字符串指定位置开始截取到最后...

  • HWOJ按字节截取字符串

    编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。但是要保证汉字不被截半个,如"我AB...

网友评论

      本文标题:计算和截取指定字符串的UTF-8字节数

      本文链接:https://www.haomeiwen.com/subject/jwimectx.html