字串相關工具

  • 中文處理需求
  • 正則表示式處理需求

議題:中文UNICODE非0字面

目前的Unicode字元分為17組編排,每組稱為平面(Plane),而每平面擁有65536(即216)個代碼點。然而目前只用了少數平面1。在中文世界的應用,可能會處理第二字面(表意文字補充平面)及15字面(私人使用區)。

在 Java 中,String保存的就是字元的Unicode碼,以前使用的是UCS-2編碼方案儲存。UCS-2固定使用兩個Byte來編碼一個字元,因此它只能編碼BMP(基本多語言平面,即0×0000-0xFFFF)範圍內的字元。雖然後來發現BMP範圍內的字符不夠用,但是出於內存消耗和兼容性的考慮,Java並沒有升到UCS-4,而是採用了UTF-16,char類型可看作其代碼單元2

這個做法導致了一些麻煩,如果所有字符都在BMP範圍內還沒事,若有BMP外的字符,就不再是一個代碼單元對應一個字元。一些與長度有關的方法,就出現了錯誤:length方法返回的是代碼單元的個數,而不是字符的個數;charAt方法返回的自然也是一個代碼單元而不是一個字元。建構時,也不能直接用\u的脫逸宣告方式對字串設值。

  • 以下示範原生 API 有異常的使用情境。
// JDK String 處理第二字面的文字測試:
final String sampleText = "𠀗𠀖";
final String str1 = new String(new int[] { 0x20016, 0x20017 }, 0, 2);
final String str2 = "\u20016\u20017";  // 無效的宣告方式,得到的結果是 0x2001, 6, 0x2001, 7

LOGGER.info("str1:{}, 應為𠀗𠀖", str1); // str1:𠀖𠀗,     應為𠀗𠀖
LOGGER.info("str2:{}, 應為𠀗𠀖", str2); // str2: 6 7,     應為𠀗𠀖
LOGGER.info("length:{}, 應為2", sampleText.length());           // length:4,     應為2
LOGGER.info("substring(1):{}, 應為𠀖", sampleText.substring(1));// substring(1):?𠀖,     應為𠀖
LOGGER.info("charAt(0):{}, 應為𠀗", sampleText.charAt(0));      // charAt(0):?,     應為𠀗
LOGGER.info("charAt(1):{}, 應為𠀖", sampleText.charAt(1));      // charAt(1):?,     應為𠀖
LOGGER.info("indexOf(𠀖):{}, 應為1", sampleText.indexOf("𠀖")); // indexOf(𠀖):2, 應為1

results matching ""

    No results matching ""