`
java1997
  • 浏览: 2580 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

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内部的某些类书写风格非常不好,同时存在一些Bug。不过这也许是笔者个人感受。偶有所获,愿与大家共同分享,其中疏漏之处望不吝赐教。


分享到:
评论

相关推荐

    java中文乱码问题解决

    本文将深入分析Java中文乱码问题的根本原因,介绍各种编码格式的区别和应用场景,并提供解决乱码问题的方法和经验。 在Java中,常见的编码格式有: * ASCII码:总共有128个,用一个字节的低7位表示,0~31是控制...

    java中文乱码解决问题

    JAVA 中文乱码解决问题 JAVA 中文乱码问题是开发过程中常见的问题之一,解决这个问题需要了解乱码产生的原因,然后对症下药。下面我们对容易产生乱码问题的场景进行分析,并提出解决方案。 1. 以 POST 方法提交的...

    Java 编程技术中汉字问题的分析及解决

    理解汉字编码的基本原理和Java中处理汉字的机制,有助于我们有效地解决乱码问题。 首先,我们需要了解汉字编码的基础知识。ASCII编码是一种单字节编码,仅能表示256个字符,不足以涵盖汉字。因此,汉字通常使用双...

    深入分析 Java 中的中文编码问题

    本文将深入探讨Java中的中文编码问题,以及如何有效地解决这些问题。 首先,我们要了解字符编码的基本概念。字符编码是用来表示文本的规则,比如ASCII、GB2312、GBK、UTF-8等。在中文环境下,最常用的是GBK和UTF-8...

    JAVA中文乱码深度分析

    解决Java中文乱码问题通常涉及以下几个方面: - 源代码编码:使用UTF-8编码保存.java文件,避免与系统默认编码冲突。 - 设置`file.encoding`:通过启动参数`-Dfile.encoding=UTF-8`设定JVM的字符编码。 - 流处理:在...

    JAVA中文问题解析和最优解决办法

    ### JAVA中文问题解析和最优解决办法 #### 一、引言 随着信息技术的快速发展与全球化进程的加速,软件开发越来越需要支持多语言环境,特别是中文环境。Java作为一门跨平台的编程语言,广泛应用于Web应用、企业级...

    深入分析Java中的中文编码问题

    ### 深入分析Java中的中文编码问题 #### 一、引言 在软件开发过程中,尤其是涉及到国际化和多语言支持的应用中,编码问题一直是令开发者头疼的问题之一。尤其是在使用Java这种跨平台语言进行开发时,不同的操作...

    java中文问题分析

    Java编程中的中文问题源于字符编码的不匹配,主要体现在以下几个方面: 1. **操作系统与Java的编码差异**:早期的计算机系统...通过理解Java编码转换的原理,遵循上述原则,可以有效避免和解决Java编程中的中文问题。

    java中文乱码问题

    解决Java中文乱码问题的核心在于:确保每个环节的编码一致,从源代码到最终显示的所有过程都应采用相同的字符编码标准。在实践中,推荐使用UTF-8编码,因为它具有广泛的支持和兼容性。 在实际项目中,当遇到乱码...

    Java语言的中文处理问题完整解决方案

    本文将全面解析Java中的中文处理问题,包括常见问题、原因分析及解决方案,旨在帮助开发者构建出能够正确处理中文字符的程序。 一、字符编码基础 Java采用Unicode字符集,它包含了几乎所有的汉字,保证了对中文...

    文《关于c++与java中文乱码问题分析与解决》中一个bug分析1

    文章《关于C++与Java中文乱码问题分析与解决》深入探讨了这一问题,并提供了一个解决方案。该解决方案涉及到使用`iconv`库进行编码转换,从GBK(中国的GBK编码标准)转换到UTF-8(一种广泛支持的Unicode编码格式)。...

    Java 编程技术中汉字问题的分析及解决.txt

    本文将深入探讨Java中汉字问题的分析与解决方案,旨在帮助开发者更好地理解和掌握如何在Java程序中正确、高效地处理汉字。 ### Java中的汉字编码 在Java中,字符串是以Unicode编码形式存储的,这是Java对字符编码...

    Java中文乱码解决之道

    阅读许多关于中文乱码的解决办法的博文后,发现对于该问题我们都(更加包括我自己)没有一个清晰明了的认识,于是LZ想通过这系列博文(估计只有几篇)来彻底分析、解决java中文乱码问题,如有错误之处望各位同仁指出...

    语义分析实验(java版)

    语义分析是编译器设计中的关键步骤,它在词法分析和语法分析之后进行,...同时,Java作为一种面向对象的语言,它的类型系统和面向对象特性使得语义分析更加复杂和有趣,对于提高学生的编程能力和问题解决能力大有裨益。

    FORM表单中文乱码问题分析与解决

    FORM表单中文乱码问题分析与解决 在 Web 开发中,中文乱码问题是一个常见的问题,尤其是在FORM表单传递参数时。这个问题的根本原因是对中文的编码与解码方式不一致。我们可以理解为对中文的加密与解密的密钥不一致...

    Java中文编码问题研究.pdf

    Java中文编码问题是Java程序中常见的问题,解决这个问题需要了解Java程序的运行原理和编码格式的转换。通过使用统一的编码格式、字符集转换和Java的internationalization支持,可以解决Java中文编码问题。

    常见的java中文问题的解决方法

    本文将深入探讨几种常见的Java中文问题及其解决方案,并着重分析如何通过设置字体来改善用户界面中的中文显示效果。 #### 一、Java GUI中文显示问题 Java图形用户界面(GUI)开发中,中文字符的正确显示是用户体验...

Global site tag (gtag.js) - Google Analytics