我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JAVA中文比较问题的分析和解决是怎样的

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JAVA中文比较问题的分析和解决是怎样的

这篇文章将为大家详细讲解有关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;

 

  //取偏依位置

 

  //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中文比较问题的分析和解决是怎样的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JAVA中文比较问题的分析和解决是怎样的

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JAVA中文比较问题的分析和解决是怎样的

这篇文章将为大家详细讲解有关JAVA中文比较问题的分析和解决是怎样的,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。 Java的中文问题由来已久,前不久需要做内存中的中文比较排序,对字符串进行
2023-06-03

ActiveMQ问题分析和解决是怎样的

ActiveMQ问题分析和解决是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1)KahaDb和AMQ Message Store两种持久方式如何选择?官方:From
2023-06-04

怎样分析JSF的中文问题

怎样分析JSF的中文问题,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。开始学习JSF的时候有遇上中文问题,看了一些文章后突然想起Struts也有中文问题,当时用
2023-06-03

JAVA常见中文问题的解决方案是怎样的呢

JAVA常见中文问题的解决方案是怎样的呢,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。JAVA常见中文问题的解决方法以下解决方案是笔者在日常生活中遇到的,希望能
2023-06-03

CentOS系统中英文问题解决方案是怎样的

今天就跟大家聊聊有关CentOS系统中英文问题解决方案是怎样的,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。在CentOS系统中,文字一直是困扰我们的一个大问题。由于CentOS系统
2023-06-16

SecureCRT中文显示乱码问题的解决方法是怎样的

本篇文章为大家展示了SecureCRT中文显示乱码问题的解决方法是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1. 修改远程linux机器的配置 vim /etc/sysconfig/i18
2023-06-13

C++中堆和栈问题的分析与解决方案

C++中堆和栈问题的分析与解决方案在C++编程中,堆和栈是两种常用的内存管理方式。堆用于动态分配内存,而栈则用于存储局部变量和函数调用的上下文信息。然而,错误的使用堆和栈可能导致内存泄漏、段错误和无法预料的行为。因此,在编写C++代码时需要
2023-10-22

分析和解决 Golang 中数值精度丢失的问题

Golang 精度丢失问题分析与解决方法在使用 Golang 编程语言进行数学运算时,一些情况下会遇到精度丢失的问题。这种问题通常发生在浮点数运算中,特别是涉及到大数值、小数值或者需要高精度计算的情况下。本文将介绍 Golang 中精度丢
分析和解决 Golang 中数值精度丢失的问题
2024-02-24

nf_conntrack中table full, dropping packet问题的解决思路是怎样的

本篇文章为大家展示了nf_conntrack中table full, dropping packet问题的解决思路是怎样的,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。介绍:nf_conntrack
2023-06-13

服务器租用中常见的问题是怎样解决

这篇文章给大家介绍服务器租用中常见的问题是怎样解决,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。现在虽然说大家对于服务器已经有一些了解,但是对于服务器租用和托管,我们还不太熟悉,选择服务器租用的企业一般都是中小企业,服
2023-06-07

Vista SP2更新和升级常见问题和解决方法是怎样的

Vista SP2更新和升级常见问题和解决方法是怎样的,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。微软7月1日凌晨开始通过Windows Update推送Vista SP
2023-06-14

SpringMVC中的跳转方式和视图解析器问题怎么解决

这篇文章主要介绍“SpringMVC中的跳转方式和视图解析器问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringMVC中的跳转方式和视图解析器问题怎么解决”文章能帮助大家解决问题。
2023-07-04

linux中怎样解决文件已删除但空间不释放的问题

这篇文章给大家介绍linux中怎样解决文件已删除但空间不释放的问题,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。1、错误现象运维的监控系统发来通知,报告一台服务器空间满了,登录服务器查看,根分区确实没有空间了:[roo
2023-06-28

windows系统中怎样设置虚拟内存才能解决物理内存较低的问题

windows系统中怎样设置虚拟内存才能解决物理内存较低的问题,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。当我们在运行一些大型的软件,或者是刚刚退出游戏的时候
2023-06-14

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录