字符串数组长度怎么算_字符串长度怎样自己数

依照Java的文档, Java中的字符内部是以UTF-16编码方式表示的,最小值是 \u0000 (0),最大值是\uffff(65535), 也就是一个字符以2个字节来表示,难道Java最多只能表示 65535个字符?

char: The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).

from The Java Tutorials

首先,让我们先看个例子:

字符串数组长度怎么算_字符串长度怎样自己数

运行这个程序,你觉得输出结果是什么?

输出结果:

字符串数组长度怎么算_字符串长度怎样自己数

我们知道, String.getBytes()如果不指定编码格式,Java会使用操作系统的编码格式得到字节数组,在我的MacOS中,默认使用UTF-8作为字符编码(locale命令可以查看操作系统的编码),所以在我的机器运行,String.getBytes()会返回UTF-8编码的字节数组。

  • String.length返回Unicode code units的长度。
  • String.toCharArray返回字符数组。

我们设置的字符串都是两个unicode字符,输出结果:

  • 普通的中文字:字符串的长度是2,每个中文字按UTF-8编码是三个字节,字符数组的长度看起来也没问题
  • emojis字符:我们设置了两个emojis字符,男女头像。结果字符串的长度是4, UTF-8编码8个字节,字符数组的长度是4
  • 生僻的中文字:我们设置了两个中文字,其中一个是生僻的中文字。结果字符串的长度是3, UTF-8编码7个字节,字符数组的长度是3

看起来字符串的字符数和我们预期的有点不一样,我们的字符串只有两个unicode字符, 可是输出结果有时候是2,有时候是3, 有时候是4,为什么呢?

这还得从Java的历史说起。

Java最初设计的Charactor用两个字节来表示unicode字符,这没有问题, 因为最初unicode中的字符还比较少, Java 1.1之前采用Unicode version 1.1.5, JDK 1.1中支持Unicode 2.0, JDK 1.1.7支持Unicode 2.1, Java SE 1.4 支持 Unicode 3.0, Java SE 5.0开始支持Unicode 4.0。

直到Unicode 3.0, Java用两个字节来表示unicode字符还没有问题,因为Unicode 3.0最多49,259个字符, 两个字节可以表示65,535个字符,还足够容的下所有的uicode3.0字符。

但是Unicode 4.0(事实上自Unicode 3.1), 字符集进行很大的扩充,已经达到了96,447个字符,Unicode 11.0已经包含137,374个字符。

在Unicode中,为每一个字符对应一个编码点(一个整数),用 U+紧跟着十六进制数表示。所有字符按照使用上的频繁度划分为 17 个平面(编号为 0-16),即基本的多语言平面和增补平面。基本的多语言平面(英文为 Basic Multilingual Plane,简称 BMP)又称平面 0,收集了使用最广泛的字符。

这样一来,Java的Charactor的两个字节的设计,已经不足以容纳所有的Unicode 4的字符, 所以可能需要4个字节才能表示扩展字符,所以现在的Charactor代表的已经不再是一个字符 (代码点 code point), 而是一个代码单元(code unit)。

  • Code Point:代码点,一个字符的数字表示。一个字符集一般可以用一张或多张由多个行和多个列所构成的二维表来表示。二维表中行与列交叉的点称之为代码点,每个码点分配一个唯一的编号数字,称之为码点值或码点编号,除开某些特殊区域(比如代理区、专用区)的非字符代码点和保留代码点,每个代码点唯一对应于一个字符。从U+0000 到 U+10FFFF。
  • Code Unit:代码单元,是指一个已编码的文本中具有最短的比特组合的单元。对于 UTF-8 来说,代码单元是 8 比特长;对于 UTF-16 来说,代码单元是 16 比特长。换一种说法就是 UTF-8 的是以一个字节为最小单位的,UTF-16 是以两个字节为最小单位的。

Java的字符在内部以UTF-16编码方式来表示,String.length返回的是Code Unit的长度,而不再是Unicode中字符的长度。对于传统的BMP平面的代码点,String.length和我们传统理解的字符的数量是一致的,对于扩展的字符,String.length可能是我们理解的字符长度的两倍。

有可能你会问, 对于一个UTF-16编码的扩展字符,它以4个字节来表示,那么前两个字节会不会和BMP平面冲突,导致程序不知道它是扩展字符还是BMP平面的字符?

其实是不会的, 幸运的是, 在BMP平面中, U+D800到U+DFFF之间的码位是永久保留不映射到Unicode字符,UTF-16就利用保留下来的0xD800-0xDFFF区块的码位来对辅助平面的字符的码位进行编码。

UTF-16编码中,辅助平面中的码位从U+10000到U+10FFFF,共计FFFFF个,需要20位来表示。第一个整数(两个字节,称为前导代理)要容纳上述20位的前10位,第二个整数(称为后尾代理)容纳上述20位的后10位。前导代理的值的范围是0xD800到0xDBFF,后尾代理的0xDC00~0xDFFF。

可以看到前导代理和后尾代理的范围都落在了BMP平面中不用来映射的码位,所以不会产生冲突,而且前导代理和后尾代理也没有重合。这样我们得到两个字节的,就可以直接判断它是否是BMP平面的字符,还是扩展字符中的前导代理还是后尾代码。

国外的有些用户用emojis字符做自己的昵称,导致有些系统不能正确的显示出来,这是因为这些系统粗暴的使用Charactor来表示,在显示的时候截断的时候有时候可能不是在正确的代码点上进行截断。

我们在进行字符串截取的时候,比如String.substring有可能会踩到一些坑,尤其经常使用的emojis字符。

自 Java 1.5 java.lang.String就提供了Code Point方法, 用来获取完整的Unicode字符和Unicode字符数量:

publicintcodePointAt(intindex) publicintcodePointBefore(intindex) publicintcodePointCount(intbeginIndex,intendIndex)

注意这些方法中的index使用的是code unit值。

本文【字符串数组长度怎么算_字符串长度怎样自己数】由作者: 前端后端 提供,本站不拥有所有权,只提供储存服务,如有侵权,联系删除!
本文链接:https://www.cuoshuo.com/blog/4151.html

(0)
上一篇 2023-03-09 08:51:01
下一篇 2023-03-09 09:05:02

相关推荐

  • python语言变量命名规则_python的变量命名规则

    在Python中使用变量时,需要遵守一些规则和指南。违反这些规则将引发错误,而指南旨在让你编写的代码更容易阅读和理解。请务必牢记下述有关变量的规则。 1.变量名只能包含字母、数字和下划线。变量名能以字母或下划线打头,但不能以数字打头。例如,可将变量命名为message_1,但不能将其命名为1_message. 2.变量名不能包含空格,但能使用下划线来分隔其中…

    2023-03-10
    300
  • 电脑操作快捷键大全表格_70个电脑常用快捷键

    花了一天时间,整理出了一份含有54+Excel精选快捷键的使用技巧。并从中选出4个使用频率最高的快捷键,用熟练了,起码节省一半工作时间!(建议所有初学者都要会,下面附快捷键具体操作 快速拆分文本:Ctrl+E 一秒求和:Alt+= 迅速生成柱状图:Alt+F1 一键美化表格,实现表格数据筛选:Ctrl+T 1、快速拆分文本:Ctrl+E(不允许有人不会,是我…

    2023-03-14
    300
  • 华为win10关闭自动更新方法(怎么设置windows不自动更新)

    目前大多数人所使用的电脑还是Win10系统,但是它有一个让我们非常头疼的问题,就是系统总会自动更新。如果我们不想要自动更新,有什么方法可以帮到我们吗?win10怎么关闭自动更新?那就看看本文的三大方法! 操作环境: 演示机型:Dell optiplex 7050 系统版本:Windows 10 一、Windows设置 我们想要关闭系统的自动更新,win10更…

    2023-03-14
    100
  • QQ数据库可以查到什么

    扁平化设计已经成为一种流行趋势,无论是操作系统还是应用软件,各个方面都有所体现。最新版本的QQ软件中,也增加了几个全新的头像,这些头像就是采用的扁平化设计,看上去非常可爱。那么如何将这些全新的头像提取出来呢? 深挖QQ数据库文件 QQ头像等信息,都集中在一个名为Data.rdb的数据库文件中。如果用户已经安装最新版本的QQ软件,那么进入到X:\Program…

    2023-03-21
    000
  • dropdownlist怎么清空

    下拉列表,又称下拉框,是一个可切换列表,其中包含多个选项,一次只能选择一个选项。 当你需要从多个答案中选中某一个时,可以采用此部件。比如国家的选择/地区的选择等。 添加,删除和重新排序Droplist选项 9DropList.png 元件添加:直接从左侧元件库上拖入; 下拉列表的编辑:直接双击Droplist; 选项的添加:点击左侧上方添加按钮(上图中第一个…

    2023-03-20
    000
  • 二分法查找的时间复杂度(二分查找的比较次数怎么算的)

    二分查找:又称折半查找,输入一个有序的元素列表(必须是有序的),将列表中间位置记录的元素与查找元素比较,如果查找的元素包含在列表中,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的元素大于查找元素,则进一步查找前一子表,否则进一步查找后一子表,重复以上过程,直到找到满足条件的记录,使查找成功,二分查找返回其位置;或直到子表不存在为止…

    2023-03-12
    300
  • 自然语言处理包括哪些内容_自然语言处理的应用

    对于ChatGPT来说,相信各位最近都被它铺天盖地的新闻报道所淹没,肯定还有不少人已经体验到了ChatGPT,大有人工智能已经高度进化之势。ChatGPT的出现,好像已经对当今互联网产生了巨大的影响,如果在这么发展下去,甚至看到了在未来能代替不少职业的趋势,比如客服、编程、广告、秘书工作等等。 什么是ChatGPT呢?ChatGPT,是美国OpenAI研发的…

    2023-03-12
    500
  • 看门狗程序是什么意思_看门狗程序是干什么

    学习嵌入式一定要对单片机有一个好的掌握,我们入门嵌入式刚开始也是以单片机开始,当然这也只是最基础的,如果想要更深一步了解嵌入式,这里小编给大家一个资料的共享加微信领取资料,接下来我们来了解一下单片机的看门狗攻能。 单片机的程序在运行过程中为了增加系统的可靠性,防止芯片受到外界干扰而程序跑飞等系统异常,于是我们就引入了看门狗的功能Watch Dog Timer…

    2023-03-18
    000
  • 函数iserror是什么意思

    小伙伴们好啊,今天咱们一起来认识几个常用函数。 SUM:作用是对数据区域或者手工输入的参数来求和。 例如,要对下图中的可售面积进行求和,公式为: =SUM(C2:C8) COUNTA:作用是统计数据区域中的非空单元格个数。 例如,要在下图中统计物业类型数,公式为: =COUNTA(A2:A8) COUNT:作用是统计数据区域中的数值个数。 例如,要在下图中统…

    2023-03-17
    200
  • 正则表达式不包含空格

    前言 正则表达式作为一名合格的程序员的必备的基本技术之一,其有用性不言而喻。但是它为什么会非常难以掌握,甚至想用一用也都感觉难以下手呢?本文将会让你一次就看会如何使用Python正则表达式。 1. 正则表达式的组成 在介绍如何使用Python的正则表达式时,我们需要先认识一下正则表达式的各种功能,以及其组成形式如何。 正则表达式可以从非结构化的文本中提取到我…

    2023-03-17
    100

发表回复

登录后才能评论
返回顶部
错说博客上线啦!