日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

一个字符串中到底能有多少个字符? 我竟然算错了!

發(fā)布時(shí)間:2024/4/11 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个字符串中到底能有多少个字符? 我竟然算错了! 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

點(diǎn)擊上方“朱小廝的博客”,選擇“設(shè)為星標(biāo)”

后臺(tái)回復(fù)”加群“加入公眾號(hào)專屬技術(shù)群

來(lái)源:rrd.me/fpv95

依照J(rèn)ava的文檔, Java中的字符內(nèi)部是以UTF-16編碼方式表示的,最小值是 \u0000 (0),最大值是\uffff(65535), 也就是一個(gè)字符以2個(gè)字節(jié)來(lái)表示,難道Java最多只能表示 65535個(gè)字符?

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

首先,讓我們先看個(gè)例子:

public?class?Main?{public?static?void?main(String[]?args)?{//?中文常見(jiàn)字String?s?=?"你好";System.out.println("1.?string?length?="?+?s.length());System.out.println("1.?string?bytes?length?="?+?s.getBytes().length);System.out.println("1.?string?char?length?="?+?s.toCharArray().length);System.out.println();//?emojiss?=?"????????";System.out.println("2.?string?length?="?+?s.length());System.out.println("2.?string?bytes?length?="?+?s.getBytes().length);System.out.println("2.?string?char?length?="?+?s.toCharArray().length);System.out.println();//?中文生僻字s?=?"????妹";System.out.println("3.?string?length?="?+?s.length());System.out.println("3.?string?bytes?length?="?+?s.getBytes().length);System.out.println("3.?string?char?length?="?+?s.toCharArray().length);System.out.println();} }

運(yùn)行這個(gè)程序,你覺(jué)得輸出結(jié)果是什么?

輸出結(jié)果:

1.?string?length?=2 1.?string?bytes?length?=6 1.?string?char?length?=2 2.?string?length?=4 2.?string?bytes?length?=8 2.?string?char?length?=4 3.?string?length?=3 3.?string?bytes?length?=7 3.?string?char?length?=3

我們知道, String.getBytes()如果不指定編碼格式,Java會(huì)使用操作系統(tǒng)的編碼格式得到字節(jié)數(shù)組,在我的MacOS中,默認(rèn)使用UTF-8作為字符編碼(locale命令可以查看操作系統(tǒng)的編碼),所以在我的機(jī)器運(yùn)行,String.getBytes()會(huì)返回UTF-8編碼的字節(jié)數(shù)組。

  • String.length返回Unicode code units的長(zhǎng)度。

  • String.toCharArray返回字符數(shù)組。

我們?cè)O(shè)置的字符串都是兩個(gè)unicode字符,輸出結(jié)果:

  • 普通的中文字:字符串的長(zhǎng)度是2,每個(gè)中文字按UTF-8編碼是三個(gè)字節(jié),字符數(shù)組的長(zhǎng)度看起來(lái)也沒(méi)問(wèn)題

  • emojis字符:我們?cè)O(shè)置了兩個(gè)emojis字符,男女頭像。結(jié)果字符串的長(zhǎng)度是4, UTF-8編碼8個(gè)字節(jié),字符數(shù)組的長(zhǎng)度是4

  • 生僻的中文字:我們?cè)O(shè)置了兩個(gè)中文字,其中一個(gè)是生僻的中文字。結(jié)果字符串的長(zhǎng)度是3, UTF-8編碼7個(gè)字節(jié),字符數(shù)組的長(zhǎng)度是3

看起來(lái)字符串的字符數(shù)和我們預(yù)期的有點(diǎn)不一樣,我們的字符串只有兩個(gè)unicode字符, 可是輸出結(jié)果有時(shí)候是2,有時(shí)候是3, 有時(shí)候是4,為什么呢?

這還得從Java的歷史說(shuō)起。

Java最初設(shè)計(jì)的Charactor用兩個(gè)字節(jié)來(lái)表示unicode字符,這沒(méi)有問(wèn)題, 因?yàn)樽畛鮱nicode中的字符還比較少, 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開(kāi)始支持Unicode 4.0。

直到Unicode 3.0, Java用兩個(gè)字節(jié)來(lái)表示unicode字符還沒(méi)有問(wèn)題,因?yàn)閁nicode 3.0最多49,259個(gè)字符, 兩個(gè)字節(jié)可以表示65,535個(gè)字符,還足夠容的下所有的uicode3.0字符。

但是Unicode 4.0(事實(shí)上自Unicode 3.1), 字符集進(jìn)行很大的擴(kuò)充,已經(jīng)達(dá)到了96,447個(gè)字符,Unicode 11.0已經(jīng)包含137,374個(gè)字符。

在Unicode中,為每一個(gè)字符對(duì)應(yīng)一個(gè)編碼點(diǎn)(一個(gè)整數(shù)),用 U+緊跟著十六進(jìn)制數(shù)表示。所有字符按照使用上的頻繁度劃分為 17 個(gè)平面(編號(hào)為 0-16),即基本的多語(yǔ)言平面和增補(bǔ)平面。基本的多語(yǔ)言平面(英文為 Basic Multilingual Plane,簡(jiǎn)稱 BMP)又稱平面 0,收集了使用最廣泛的字符。

這樣一來(lái),Java的Charactor的兩個(gè)字節(jié)的設(shè)計(jì),已經(jīng)不足以容納所有的Unicode 4的字符, 所以可能需要4個(gè)字節(jié)才能表示擴(kuò)展字符,所以現(xiàn)在的Charactor代表的已經(jīng)不再是一個(gè)字符 (代碼點(diǎn) code point), 而是一個(gè)代碼單元(code unit)。

  • Code Point:代碼點(diǎn),一個(gè)字符的數(shù)字表示。一個(gè)字符集一般可以用一張或多張由多個(gè)行和多個(gè)列所構(gòu)成的二維表來(lái)表示。二維表中行與列交叉的點(diǎn)稱之為代碼點(diǎn),每個(gè)碼點(diǎn)分配一個(gè)唯一的編號(hào)數(shù)字,稱之為碼點(diǎn)值或碼點(diǎn)編號(hào),除開(kāi)某些特殊區(qū)域(比如代理區(qū)、專用區(qū))的非字符代碼點(diǎn)和保留代碼點(diǎn),每個(gè)代碼點(diǎn)唯一對(duì)應(yīng)于一個(gè)字符。從U+0000 到 U+10FFFF。

  • Code Unit:代碼單元,是指一個(gè)已編碼的文本中具有最短的比特組合的單元。對(duì)于 UTF-8 來(lái)說(shuō),代碼單元是 8 比特長(zhǎng);對(duì)于 UTF-16 來(lái)說(shuō),代碼單元是 16 比特長(zhǎng)。換一種說(shuō)法就是 UTF-8 的是以一個(gè)字節(jié)為最小單位的,UTF-16 是以兩個(gè)字節(jié)為最小單位的。

Java的字符在內(nèi)部以UTF-16編碼方式來(lái)表示,String.length返回的是Code Unit的長(zhǎng)度,而不再是Unicode中字符的長(zhǎng)度。對(duì)于傳統(tǒng)的BMP平面的代碼點(diǎn),String.length和我們傳統(tǒng)理解的字符的數(shù)量是一致的,對(duì)于擴(kuò)展的字符,String.length可能是我們理解的字符長(zhǎng)度的兩倍。

有可能你會(huì)問(wèn), 對(duì)于一個(gè)UTF-16編碼的擴(kuò)展字符,它以4個(gè)字節(jié)來(lái)表示,那么前兩個(gè)字節(jié)會(huì)不會(huì)和BMP平面沖突,導(dǎo)致程序不知道它是擴(kuò)展字符還是BMP平面的字符?

其實(shí)是不會(huì)的, 幸運(yùn)的是, 在BMP平面中, U+D800到U+DFFF之間的碼位是永久保留不映射到Unicode字符,UTF-16就利用保留下來(lái)的0xD800-0xDFFF區(qū)塊的碼位來(lái)對(duì)輔助平面的字符的碼位進(jìn)行編碼。

UTF-16編碼中,輔助平面中的碼位從U+10000到U+10FFFF,共計(jì)FFFFF個(gè),需要20位來(lái)表示。第一個(gè)整數(shù)(兩個(gè)字節(jié),稱為前導(dǎo)代理)要容納上述20位的前10位,第二個(gè)整數(shù)(稱為后尾代理)容納上述20位的后10位。前導(dǎo)代理的值的范圍是0xD800到0xDBFF,后尾代理的0xDC00~0xDFFF。

可以看到前導(dǎo)代理和后尾代理的范圍都落在了BMP平面中不用來(lái)映射的碼位,所以不會(huì)產(chǎn)生沖突,而且前導(dǎo)代理和后尾代理也沒(méi)有重合。這樣我們得到兩個(gè)字節(jié)的,就可以直接判斷它是否是BMP平面的字符,還是擴(kuò)展字符中的前導(dǎo)代理還是后尾代碼。

國(guó)外的有些用戶用emojis字符做自己的昵稱,導(dǎo)致有些系統(tǒng)不能正確的顯示出來(lái),這是因?yàn)檫@些系統(tǒng)粗暴的使用Charactor來(lái)表示,在顯示的時(shí)候截?cái)嗟臅r(shí)候有時(shí)候可能不是在正確的代碼點(diǎn)上進(jìn)行截?cái)唷?/p>

我們?cè)谶M(jìn)行字符串截取的時(shí)候,比如String.substring有可能會(huì)踩到一些坑,尤其經(jīng)常使用的emojis字符。

自 Java 1.5 java.lang.String就提供了Code Point方法, 用來(lái)獲取完整的Unicode字符和Unicode字符數(shù)量:

public?int?codePointAt(int?index) public?int?codePointBefore(int?index) public?int?codePointCount(int?beginIndex,?int?endIndex)

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

想知道更多?描下面的二維碼關(guān)注我

【限時(shí)推廣1】

極客時(shí)間雙十二全場(chǎng)優(yōu)惠,特定申請(qǐng)了一個(gè)15元(滿40減15)優(yōu)惠口令:NIUBISIDA(上次的SIDANIUBI用掉了...),有效期截止日期本月月底。

【精彩推薦】

  • 入侵你Linux服務(wù)器的一萬(wàn)種玩法...

  • 955 不加班的公司名單:955.WLB

  • 阿里巴巴的獨(dú)立環(huán)境是如何實(shí)現(xiàn)的

朕已閱?

超強(qiáng)干貨來(lái)襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生

總結(jié)

以上是生活随笔為你收集整理的一个字符串中到底能有多少个字符? 我竟然算错了!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 公侵犯人妻一区二区 | 亚洲人毛茸茸 | 亚洲美女性生活视频 | 天天狠狠操 | 久热精品视频 | 国产美女明星三级做爰 | 国产不卡在线观看 | 久草网在线视频 | 在线黄网站 | 免费在线看污视频 | 奇米在线观看 | 情侣自拍av | 天堂岛av| 在线视频麻豆 | 国产色一区二区 | 亚洲色图网友自拍 | 蜜臀久久99精品久久久无需会员 | a级片在线免费观看 | 久久人爽| 欧美一级久久 | 最近2018年手机中文字幕版 | 久久国产精品网站 | 永久免费av在线 | 亚洲视频导航 | 96免费视频 | 米奇影音| 久精品国产| 精品国产三级片在线观看 | 深夜小视频在线观看 | 污视频免费看 | 99re这里| 看a网站| 精品一区二区三区国产 | 中文字幕人妻色偷偷久久 | 伊人福利在线 | 人人人超碰 | 白石茉莉奈黑人 | 黑人巨大精品欧美一区免费视频 | 色婷婷激情网 | 国产主播一区二区 | 激情久久视频 | 日本xxxx色 | 亚洲在线日韩 | 亚洲乱色熟女一区二区三区 | 男生桶女生肌肌 | 婷婷在线观看视频 | www.好了av | 日韩乱码一区二区三区 | 亚洲综合视频在线播放 | www.黄色片| 麻豆偷拍 | 黄色片免费观看视频 | 精品中文字幕一区二区 | 日本中文字幕在线视频 | 黄色资源在线播放 | 国内久久精品 | 91香蕉国产 | 操女人的逼逼 | 一区二区精品国产 | 最新视频 - x88av| 蜜臀久久99精品久久久久宅男 | 亚洲性生活网站 | 刘亦菲久久免费一区二区 | 91九色pron| 久久精品中文字幕 | 欧美日韩视频无码一区二区三 | 天天操天天插天天干 | 午夜亚洲 | 亚洲福利在线播放 | 国产一级免费观看 | 激情国产视频 | 熟妇人妻精品一区二区三区视频 | 亚洲天堂国产精品 | 欧美色图中文字幕 | 婷婷在线免费观看 | 久久免费在线观看 | 龚玥菲三级露全乳视频 | 国产午夜手机精彩视频 | 日日夜夜狠狠操 | 国产精品视频 | 激情亚洲色图 | 亚洲最大在线 | www日本xxx | 97久久精品视频 | 99网站| 欧美一区二区三区的 | 黄色在线一区 | 成人手机在线播放 | 久久加勒比 | 一区二区激情视频 | 谁有av网址| 中文字幕123 | 亚洲不卡在线视频 | 完全免费在线视频 | 欧美性大战久久久久xxx | 天天曰天天爽 | 成人gav| 深夜福利网址 | 日本精品久久久久 |