中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JAVA中文比較問題的分析和解決是怎樣的

發布時間:2021-12-08 11:51:17 來源:億速云 閱讀:318 作者:柒染 欄目:編程語言

這篇文章將為大家詳細講解有關JAVA中文比較問題的分析和解決是怎樣的,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

 Java的中文問題由來已久,前不久需要做內存中的中文比較排序,對字符串進行GBK或者GB2312編碼以后,使用String.compareTo方法仍然不能得到正確結果。因此,懷著懷疑的態度,對jdk中String類的源代碼做了一翻探究。(使用JDK為1.3.1版本)

以下是String.java中compareTo的源代碼,請注意其中的注釋:

public class String

{

  …

  public int compareTo(String anotherString) {

  int len1 = count;

  int len2 = anotherString.count;

 

 

  //n為兩個字符串長度的最小者

  int n = Math.min(len1, len2);

 

  //獲取字符數組

  char v1[] = value;

  char v2[] = anotherString.value;

 

  //取偏依位置

  /** The offset is the first index of the storage that is used. */

  //offset 是第一個存儲索引

 

  int i = offset;

  int j = anotherString.offset;

 

  //如果i == j

  //這里可能是判斷取同一內存中兩個字符串的情景。。。

  // A  <--  <----

  // B  s1  |

  // C  <--  |

  // D  s2

  // E  |

  // F  |

  // G  <----------

  // 可能這種情況 i = j

  if (i == j) {

    int k = i;

    int lim = n + i;

 

    while (k < lim)

  {

  char c1 = v1[k];

  char c2 = v2[k];

 

  if (c1 != c2) file://直到找到一個不相等的字符返回c1 - c2

  return c1 - c2;

  k++;

    }

  } else {

    while (n-- != 0) file://直到兩個字符串長度記數為0

  {

  char c1 = v1[i++]; file://分別取字符

  char c2 = v2[j++];

  if (c1 != c2) {  //發現不相等立即返回c1 - c2;

  return c1 - c2;

  }

    }

  }

  return len1 - len2;

//最后這里可能出現的情況是: 兩個字符串比較完之后還沒有得到結果。相等的情況

  }

}//end of class String

為什么Java在做漢字的CompareTo時比較會有問題呢?通過對compareTo源代碼的分析發現,關鍵在于JDK的compareTo實現是直接使用Char來進行比較的:

  char c1 = v1[k];

  char c2 = v2[k];

可是當Java使用GB2312編碼時,一個對漢字所獲取到的Char值卻是不規則的,即一個漢字在Java中作為一個char來處理(雙字節字符)時,將這樣的雙字節字符進行強制轉換成int類型時,所得到的不是包含了漢字編碼順序的中文內碼。可以看一下一組測試數據可以看到其中奧妙:

字符

Char值

Byte[]值

按Byte[]合成的值

25105

[50:46]

[-5046]

29233

[80:82]

[-8082]

21271

[79:79]

[-7979]

20140

[66:87]

[-6687]

22825

[52:20]

[-5220]

23433

[80:78]

[-8078]

38376

[61:59]

[-6159]

A

65

[-65]

[65]

B

66

[-66]

[66]

C

67

[-67]

[67]

D

68

[-68]

[68]

按照中文順序:“我”字應該在“愛”字后面,因此理論上來講"我"字的Char值應該比“愛"字的char值要大。可是不知道為什么Java的漢字char(兩個byte)->int類型的轉換會發生很大偏差。而失去了漢字原本在GBK規范當中,按內碼排列好的順序。但從一個漢字拆分成2個字節的byte[]時,所得到的值并沒有打亂GBK編碼規定的順序,因此得到解決問題的思路:將String進行GB2312編碼后取得某個漢字獲取其Char值時,將漢字拆分成2個字節byte[]再進行計算,從而得到正確的內碼。

因此我自己寫了下面這樣幾個函數,基本上解決了漢字比較的問題:

  函數包括三個,你可以隨意放置到任何類當中作為輔助函數使用(Private Helper)。

n  public int compare(String s1, String s2) :主要工作是為比較做一些前期的編碼工作可以說是系統的一個外殼。

n  public int chineseCompareTo(String s1, String s2):該函數則是中文字符串比較主體,其內部實現了比較的最基本邏輯,和JDK的compareTo所使用的邏輯是一樣的。調用接口也一樣。

n  public static int getCharCode(String s):該函數則負責將一個以字符串形式存在的字符轉換成為int編碼,兒不損失其位置信息。注意輸入通常是:“我”或者“A”,如果輸入更長的字符串,則改函數獲得的是第一個字符的值。

private static String __ENCODE__ = "GBK"; file://一定要是GBK

private static String __SERVER_ENCODE__ = "GB2312"; file://服務器上的缺省編碼

/*

比較兩字符串

*/

  public int compare(String s1, String s2)

  {

  String m_s1 = null, m_s2 = null;

  try

  {

  //先將兩字符串編碼成GBK

  m_s1 = new String ( s1.getBytes(__SERVER_ENCODE__), __ENCODE__);

  m_s2 = new String ( s2.getBytes(__SERVER_ENCODE__), __ENCODE__);

  }

  catch( Exception ex)

  {

  return s1.compareTo(s2);

  }

  int res = chineseCompareTo(m_s1, m_s2);

 

  System.out.println("比較" + s1 + " | " + s2 + "==== Result: " + res);

  return res;

  }

 

//獲取一個漢字/字母的Char

  public static int getCharCode(String s)

  {

  if (s==null && s.equals(“”)) return -1; file://保護代碼

byte [] b = s.getBytes();

  int value = 0;

  //保證取第一個字符(漢字或者英文)

  for (int i = 0; i < b.length && i <= 2; i ++)

  {

  value = value * 100 + b[i];

  }

  return value;

  }

 

//比較兩個字符串

  public int chineseCompareTo(String s1, String s2)

  {

  int len1 = s1.length();

  int len2 = s2.length();

 

  int n = Math.min(len1, len2);

 

  for (int i = 0; i < n; i ++)

  {

  int s1_code = getCharCode(s1.charAt(i) + "");

  int s2_code = getCharCode(s2.charAt(i) + "");

  if (s1_code != s2_code) return s1_code - s2_code;

  }

  return len1 - len2;

  }

關于JAVA中文比較問題的分析和解決是怎樣的就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

佛坪县| 宁明县| 沁源县| 宜宾市| 枣庄市| 信宜市| 泰宁县| 柳林县| 乐业县| 山东省| 泽普县| 湖南省| 新民市| 鄢陵县| 双城市| 光山县| 鲁甸县| 珲春市| 拉萨市| 左云县| 永吉县| 华安县| 邹城市| 东源县| 洪湖市| 昭平县| 乐陵市| 蛟河市| 图片| 贵德县| 台中县| 蒙自县| 龙南县| 武宁县| 云林县| 镇平县| 军事| 新余市| 临澧县| 固阳县| 南平市|