成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一個Java字符串中到底有多少個字符?

開發 后端
依照Java的文檔, Java中的字符內部是以UTF-16編碼方式表示的,最小值是 \u0000 (0),最大值是\uffff(65535), 也就是一個字符以2個字節來表示,難道Java最多只能表示 65535個字符?

依照Java的文檔, Java中的字符內部是以UTF-16編碼方式表示的,最小值是 \u0000 (0),***值是\uffff(65535), 也就是一個字符以2個字節來表示,難道Java最多只能表示 65535個字符?

一個Java字符串中到底有多少個字符?

  • 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

首先,讓我們先看個例子:

 

  1. public class Main { 
  2.     public static void main(String[] args) { 
  3.         // 中文常見字 
  4.         String s = "你好"
  5.         System.out.println("1. string length =" + s.length()); 
  6.         System.out.println("1. string bytes length =" + s.getBytes().length); 
  7.         System.out.println("1. string char length =" + s.toCharArray().length); 
  8.         System.out.println(); 
  9.         // emojis 
  10.         s = "👦👩"
  11.         System.out.println("2. string length =" + s.length()); 
  12.         System.out.println("2. string bytes length =" + s.getBytes().length); 
  13.         System.out.println("2. string char length =" + s.toCharArray().length); 
  14.         System.out.println(); 
  15.         // 中文生僻字 
  16.         s = "𡃁妹"
  17.         System.out.println("3. string length =" + s.length()); 
  18.         System.out.println("3. string bytes length =" + s.getBytes().length); 
  19.         System.out.println("3. string char length =" + s.toCharArray().length); 
  20.         System.out.println(); 
  21.     } 

運行這個程序,你覺得輸出結果是什么?

輸出結果:

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

我們知道, 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字符。

責任編輯:未麗燕 來源: 鳥窩
相關推薦

2019-12-16 09:26:05

Java設計操作系統

2023-04-25 15:46:51

Python字符串

2022-11-24 08:01:57

bash腳本字符串

2020-09-18 14:23:50

字符

2022-12-08 15:55:52

JavaScript字符串

2020-12-25 13:13:22

程序員數據軟件

2021-02-02 18:03:00

字符串面試官子序列

2011-06-07 10:15:38

GNULinux

2010-08-26 09:08:04

Google數據中心

2021-11-12 09:44:03

字符串算法復雜度

2022-09-27 09:43:08

物聯網設備物聯網

2020-09-07 07:35:03

Grep命令字符串

2011-05-19 14:00:51

PHP單引號雙引號

2011-05-19 13:45:15

PHP單引號雙引號

2019-08-01 15:06:49

離職成本員工

2022-03-08 22:21:55

網絡包隊列網卡

2021-11-07 07:51:01

JavaString字符串

2011-07-18 13:34:44

SQL Server數拼接字符串

2020-08-12 22:03:17

JavaScript開發技術

2021-08-13 07:00:43

Java字符串對象問題
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩欧美专区 | 久久精品伊人 | 亚洲va中文字幕 | 亚洲精品第一国产综合野 | 欧美日韩在线观看一区 | av中文在线 | 欧美精品一二区 | 欧美精品一区二区三区四区五区 | 亚洲免费视频在线观看 | 亚洲一区综合 | 国产精品欧美一区喷水 | 亚洲三区视频 | 亚洲一区精品在线 | 麻豆久久久久久久久久 | 国产精品一区久久久 | 一区二区在线看 | 97精品超碰一区二区三区 | 亚洲成人精品一区二区 | 日韩欧美一区二区三区在线播放 | 久久精品亚洲精品国产欧美 | 成人黄色网址大全 | 羞羞视频在线观看网站 | 久久精品国产a三级三级三级 | 久久一区二区免费视频 | 在线黄色网 | 成人午夜视频在线观看 | 国产日韩视频在线 | 成人午夜在线观看 | 正在播放一区二区 | h视频在线免费 | 国产成人精品a视频一区www | 日韩免费在线 | 国产高清精品在线 | 久久国产激情视频 | 激情福利视频 | 日韩成人av在线 | 欧美不卡 | 亚洲免费精品 | 日韩在线精品 | 久久毛片 | 日韩一区二区福利 |