`
oznyang
  • 浏览: 161468 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

字符编码在编程中的问题

阅读更多
[概述]
      在编程中字符编码绝对是个值得重视的问题,当读取一个文件或是得到一个输入流,你需要分析数据的编码方式、形态,以便能正确的处理、显示数据所表示的字符。

[细节]
      1)  在简体中文操作系统中,从键盘输入的原始字符采用的是GBK编码方式,对应到其他操作系统,采用的应是系统默认的本地字符集。而在程序设计语言中,字符和字符串则通常是使用Unicode编码方式,这一点可以用下列代码说明(使用Java语言描述)。

      int ch = System.in.read(); //从键盘输入中读取一个字节的数据
      如果输入“中国”两个字符,使用上面的代码将所有的数据读取,将得到“D6 D0 B9 FA”,这写数据正是“中国”两个字符的GBK编码值。
      String tmp = "中国"; //定义字符串并赋值
      for(int i=0;i<tmp.length();i++)
      {
      //将字符串中的每个字符编码值以十六进制形式显示
         System.out.println(Integer.toHexString(ch));
      }

      上面代码最后显示的内容是“4E2D 56FD”,而这正是“中国”两个字符的Unicode编码值。
 
      2) 不仅是输入的原始字符采用GBK编码,屏幕输出的最终数据也要采用GBK编码,下面的代码能说明问题。

      String tmp = "中国"; //定义字符串并赋值
      System.out.println(tmp); //将字符串tmp输出到显示屏

      代码运行后,在显示屏上显然能看到“中国”两个字符,而字符串tmp分明是采用Unicode进行编码的,是不是刚才提出的命题站不住脚呢?其实,在调用println()方法后,该方法自动的将字符串tmp的编码方式从Unicode转换成了本地编码GBK,这样才能在屏幕上正常的显示中文。如果你仍然怀疑,请继续往下看。

      byte [] buf1 = tmp.getBytes("Unicode"); //将字符串tmp以Unicode编码方式储存在字节数组中
      byte [] buf2 = tmp.getBytes("GB2312"); //将字符串tmp以UGBK编码方式储存在字节数组中
      //在屏幕输出流中直接写字节数组
      System.out.write(buf1);
      System.out.write(buf2);

      这样的作法将会得到什么结果呢?结果也许会令你感到惊讶,buf1的数据输出后显示为乱码,而buf2的数据输出后赫然显示为“中国”两个字符。可以把命题说得明确点:如果要在屏幕上输出汉字,那么字符的最终编码方式必须是GBK编码方式。对于数字和英文字母,以及ASCII编码集中包含的符号,字符的最终编码方式可以是ASCII,这种情况下如果使用Unicode编码,那么显示的结果会是这样“1 2 3 a b c ”,本来想显示的内容是“123abc”。显示结果字符间多了个貌似空格的字符,这是因为ASCII编码使用一个字节,Unicode编码使用两个字节,在ASCII编码转换为Unicode时候,只是单纯地在编码值前面补充一个全为0的字节,这个字节在最终显示的时候被看做是空字符NUL。
 
      3) 在涉及网页、网络流和关系数据库方面编程的时候,字符编码总喜欢戏弄编程人员,不花心思去驯服它的结果将是得到一堆乱码。例如在读取数据数据时候,数据库中的内容是中文字符,如果数据库没有考虑到中文支持问题就很容易得到乱码。再例如程序运行的平台默认编码并非GBK,在获取GBK编码的字符数据时候,程序会将数据看作默认编码,这样也容易产生乱码。在上述情况中编写程序的时候,就应该耐心的分析数据的编码方式,合理的编写代码防止乱码。
 
[例子]   
      记得在《Java手机程序设计入门与应用》(王森 编著)一书的第13章-MIDP网络程序设计中有一段使用HTTP进行网络连接的实例代码,部分代码如下所示。

      String url = " http://127.0.0.1/test.html ";
      HttpConnection hc = (HttpConnection)Connector.open(url);
      DataInputStream dis = new DataInputStream(hc.openInputStream());
      String content = "";
      int ic;
      while((ic = dis.read()) != -1)
      {
          content += (char)ic;
      }
      Form f = new Form("HTTP Test");
      f.append(content);
      Display.getDisplay(this).setCurrent(f);

      这段代码让手机通过HTTP协议与网络中的主机进行通信,然后获得网络主机上的文件test.html并将文件内容读取到字符串变量中,最后显示到程序窗体中。如果程序这般执行的话,你会发现MIDlet显示出来中文都是乱码。作者称“之所以会有这种结果,原因在于我们的仿真器支持Unicode的缘故。”,作者的意思似乎是MIDlet将本地编码的字符数据误认为了Unicode编码的数据,因此不能正常显示,然后推荐了一种解决方法:使用ASCII形态的Unicode。
      所谓ASCII形态的Unicode指的是使用ASCII编码的字符来表示Unicode编码值,反过来说就是将Unicode的编码值看做字符,再用ASCII对这些字符进行编码存放。比如“中国”这两个字符的ASCII形态的Unicode编码字符为“\u4e2d\u56fd”,0x4E2D 0x56FD 分别为“中”和“国”的Unicode编码值,将编码值作为字符,然后在前面添加“\u”标识符,以便进行还原。再对这些字符进行ASCII编码就得到了ASCII形态的Unicode编码值,最终的值为“5C 75 34 65 32 64 5C 75 35 36 66 64”,一共12个字节的数据,分别对应了“\u4e2d\u56fd”中的一个字符。使用jdk*\bin文件夹下的native2ascii.exe程序可以很方便的将一个文件转换为ASCII形态的Unicode编码。将文件test.html转换形态后,MIDlet中需要再次将ASCII形态的Unicode转换为Unicode编码,这个转换方法需要自己写,最后MIDlet中显示出来的就是正常的中文字符。

      在我看来,那本书的作者没有把握住问题的真正原因,也或许是我们使用的模拟器和平台不同。如果把握住真正的原因,问题的解决方法就变得很简单了。前面说过,要在屏幕上显示出中文,字符的最终编码形式必须是GBK,在中国大陆发现的手机都能显示中文,也就说明手机中都支持GBK编码。那为什么会出现中文字符乱码的问题呢?我的理由是手机中采用的默认编码是ISO8859-1,对于从网络中读入的字符数据,在没有指明的情况下,MIDlet一律将它们看作是ISO8859-1编码的数据。而test.html的编码方式是GBK,MIDlet犯了个错误,它将GBK编码的数据误认为了ISO8859-1编码的数据,然后在显示的时候又进行了一次ISO8859-1到GBK的编码转换,这样的结果是数据遭到了破坏,显示出来的中文也就变成了乱码。
      把握住了原因,解决起来就十分方便了。既然MIDlet将GBK编码的数据误认为ISO8859-1编码的数据,那么我们只要在程序中指明数据的编码方式就可以了,而不用使用“ASCII形态的Unicode”这样的舍本求末的方法。下面是解决MIDlet网络连接中文乱码问题的代码,这些代码将证明我的观点。

      http://127.0.0.1/test.html;
      HttpConnection hc = (HttpConnection)Connector.open(url);
      byte [] buf = new byte[1024];
      int len = hc.openInputStream().read(buf);  //读取网络数据
      String content = new String(buf,0,len,"GB2312");  //指定数据为GBK编码
      Form f = new Form("HTTP Test");
      f.append(content); 
      display.setCurrent(f);

      上述代码中关键的一句是:
      String content = new String(buf,0,len,"GB2312");
      这句代码告诉MIDlet从网络中读取的数据使用的是GBK编码方式,然后MIDlet便能争取处理和显示这些数据。
      如果将这句代码改写为: 
      String content = new String(buf,0,len);
      或者是:
      String content = new String(buf,0,len,"ISO8859-1");
      都将出现同样的中文乱码现象,由此断定错误的原因是手机默认编码使用ISO8859-1,MIDlet将从网络中读取的GBK编码的数据误认成了ISO8859-1编码的数据。
分享到:
评论

相关推荐

    易语言字符编码转换

    在处理字符串和文本数据时,字符编码转换是一个常见的需求,因为不同的系统和应用可能使用不同的字符编码标准来表示文本。本资源提供了易语言字符编码转换的源码,帮助开发者理解和实现这一功能。 字符编码是用来...

    VB转换字符编码(构造发送字符消息的准备工作)

    在VB(Visual Basic)编程中,处理字符编码是至关重要的,尤其是在进行进程间通信或者数据传输时。"VB转换字符编码(构造发送字符消息的准备工作)"这个标题涉及到的关键点是字符编码的转换以及如何为发送字符消息做好...

    中英文字符编码查询助手.zip

    - 在编程和文本处理时,正确理解字符编码有助于避免乱码问题,例如在读取、保存或者传输文件时。 - 对于多语言应用,理解编码转换规则能确保不同语言的字符正确显示。 4. **"中英文字符编码查询助手"的功能**: ...

    字符编码解决方案

    本文主要针对C++编程中遇到的乱码问题,从编码原理、Unicode的意义出发,详细讲解了四个典型场景下的乱码问题及其解决方案。 首先,我们要理解编码的基本概念。在计算机中,所有的信息都是由二进制表示的,而字符...

    字符集和字符编码详解

    字符集和字符编码是计算机处理文字的基础,它们决定了如何在二进制的世界中表示和传输人类语言。本文将深入探讨这两个概念,以及相关的知识点。 首先,我们要理解什么是字符集。字符集,顾名思义,就是一个集合,...

    字符编码文档

    字符编码是计算机科学领域中一个基础且重要的概念,它涉及到信息的存储、传输和处理。字符编码定义了如何将文字、符号等字符...在实际工作中,正确处理字符编码能避免许多不必要的问题,提高软件的稳定性和用户体验。

    关于 字符编码的 转换 知识

    尽管Unicode解决了字符编码的兼容性和统一性问题,但在实际应用中仍面临与ASCII编码不兼容的问题。为此,UTF-8编码被设计出来,它通过一种特殊的编码规则实现了与ASCII编码的兼容性。UTF-8编码的核心思想是对Unicode...

    字符编码

    在描述中提到的“博文链接”是一个关于字符编码问题的讨论,虽然具体内容没有给出,但通常这类问题可能涉及Java编程语言中遇到的字符编码问题。在Java中,字符编码问题往往出现在输入输出流的处理、字符串的转换或者...

    字符编码解码工具字符编码,解码

    在编程中,处理字符编码和解码的函数和库广泛存在。例如,在Python中,你可以使用`codecs`模块进行编码和解码操作。`encode()`函数用于将字符串编码为字节,而`decode()`函数则用于将字节解码为字符串。在Java中,`...

    中英文字符编码查询_V1.1.rar

    在实际应用中,开发者可以利用这款工具快速查找并处理字符编码问题,提高开发效率,减少调试时间。对于STM32这样的嵌入式系统,尤其是涉及到屏幕显示的应用,正确理解和使用字符编码是至关重要的。 总之,《中英文...

    字符编码查询工具.rar

    在编程和数据处理过程中,理解字符编码是至关重要的。GBK和BIG5主要用于简体中文和繁体中文,而UTF-8则支持全球多种语言,因此在跨语言的项目中通常首选UTF-8。字符编码查询工具的使用可以帮助我们避免编码不匹配...

    字符编码查询之星

    3. **十六进制展示**:使用十六进制表示字符编码,有助于理解字符在内存中的存储形式,对于程序开发和数据分析人员来说,这是一种直观的查看方式。 4. **绿色软件**:无需安装,直接运行,不占用系统资源,方便用户...

    Lucene 字符编码问题

    在IT行业中,字符编码是一个非常基础且重要的概念,特别是在处理文本数据时,如搜索引擎Lucene。Lucene是一个高性能、全文本检索库,广泛应用于各种信息检索系统。在使用Lucene时,可能会遇到字符编码问题,这通常是...

    完整版字符编码查看器.rar

    在信息化时代,理解和掌握字符编码至关重要,尤其对于编程、数据交换以及国际化的文本处理。"完整版字符编码查看器"是一款实用工具,它可以帮助用户查看和理解各种字符编码格式,包括常见的ASCII、Unicode(如UTF-8...

    字符编码 自动识别 编码类型

    在IT领域,尤其是编程和文件处理中,理解不同的字符编码至关重要,因为错误的编码设置可能导致乱码问题。本篇将详细介绍字符编码、自动识别以及常见的编码类型,并提供解决显示乱码的方法。 首先,字符编码是一种...

    JAVA 转换字符编码工具

    在Java编程语言中,字符编码是一个非常重要的概念,特别是在处理文本数据时。字符编码决定了如何将字符转换为字节序列,以及如何从字节序列恢复字符。本篇将围绕"JAVA 转换字符编码工具"这个主题,深入探讨字符编码...

    常用字符集及字符编码简介

    字符编码的转换和处理常常是编程中需要解决的问题,特别是在处理跨语言数据时。不正确的字符编码可能导致乱码,影响文本的正常显示。例如,将一个使用GB2312编码的文件误认为是UTF-8编码时,可能会出现无法识别的...

    java使用URLDecoder和URLEncoder对中文字符进行编码和解码

    在Java编程语言中,`URLDecoder`和`URLEncoder`是两个非常重要的工具类,主要用于处理URL中的中文字符和其他特殊字符。这两个类位于`java.net`包下,可以帮助开发者进行字符串编码和解码,确保数据在网络传输过程中...

    工具-字符编码转换

    标题“工具-字符编码转换”指的是一个用于处理字符编码转换的软件工具,它可能帮助用户在不同的字符编码之间进行转换,以解决不同系统或程序之间的兼容性问题。字符编码是计算机存储和显示文本的一种方式,常见的有...

Global site tag (gtag.js) - Google Analytics