`
kewb
  • 浏览: 85849 次
  • 性别: Icon_minigender_1
  • 来自: 东莞
社区版块
存档分类
最新评论

几种误解,以及乱码产生的原因和解决办法

阅读更多
几种误解,以及乱码产生的原因和解决办法
3.1 容易产生的误解
  对编码的误解
误解一 在将“字节串”转化成“UNICODE 字符串”时,比如在读取文本文件时,或者通过网络传输文本时,容易将“字节串”简单地作为单字节字符串,采用每“一个字节”就是“一个字符”的方法进行转化。

而实际上,在非英文的环境中,应该将“字节串”作为 ANSI 字符串,采用适当的编码来得到 UNICODE 字符串,有可能“多个字节”才能得到“一个字符”。

通常,一直在英文环境下做开发的程序员们,容易有这种误解。
误解二 在 DOS,Windows 98 等非 UNICODE 环境下,字符串都是以 ANSI 编码的字节形式存在的。这种以字节形式存在的字符串,必须知道是哪种编码才能被正确地使用。这使我们形成了一个惯性思维:“字符串的编码”。

当 UNICODE 被支持后,Java 中的 String 是以字符的“序号”来存储的,不是以“某种编码的字节”来存储的,因此已经不存在“字符串的编码”这个概念了。只有在“字符串”与“字节串”转化时,或者,将一个“字节串”当成一个 ANSI 字符串时,才有编码的概念。

不少的人都有这个误解。

第一种误解,往往是导致乱码产生的原因。第二种误解,往往导致本来容易纠正的乱码问题变得更复杂。

在这里,我们可以看到,其中所讲的“误解一”,即采用每“一个字节”就是“一个字符”的转化方法,实际上也就等同于采用 iso-8859-1 进行转化。因此,我们常常使用 bytes = string.getBytes("iso-8859-1") 来进行逆向操作,得到原始的“字节串”。然后再使用正确的 ANSI 编码,比如 string = new String(bytes, "GB2312"),来得到正确的“UNICODE 字符串”。

3.2 非 UNICODE 程序在不同语言环境间移植时的乱码

非 UNICODE 程序中的字符串,都是以某种 ANSI 编码形式存在的。如果程序运行时的语言环境与开发时的语言环境不同,将会导致 ANSI 字符串的显示失败。

比如,在日文环境下开发的非 UNICODE 的日文程序界面,拿到中文环境下运行时,界面上将显示乱码。如果这个日文程序界面改为采用 UNICODE 来记录字符串,那么当在中文环境下运行时,界面上将可以显示正常的日文。

由于客观原因,有时候我们必须在中文操作系统下运行非 UNICODE 的日文软件,这时我们可以采用一些工具,比如,南极星,AppLocale 等,暂时的模拟不同的语言环境。

3.3 网页提交字符串

当页面中的表单提交字符串时,首先把字符串按照当前页面的编码,转化成字节串。然后再将每个字节转化成 "%XX" 的格式提交到 Web 服务器。比如,一个编码为 GB2312 的页面,提交 "中" 这个字符串时,提交给服务器的内容为 "%D6%D0"。

在服务器端,Web 服务器把收到的 "%D6%D0" 转化成 [0xD6, 0xD0] 两个字节,然后再根据 GB2312 编码规则得到 "中" 字。

在 Tomcat 服务器中,request.getParameter() 得到乱码时,常常是因为前面提到的“误解一”造成的。默认情况下,当提交 "%D6%D0" 给 Tomcat 服务器时,request.getParameter() 将返回 [0x00D6, 0x00D0] 两个 UNICODE 字符,而不是返回一个 "中" 字符。因此,我们需要使用 bytes = string.getBytes("iso-8859-1") 得到原始的字节串,再用 string = new String(bytes, "GB2312") 重新得到正确的字符串 "中"。

3.4 从数据库读取字符串

通过数据库客户端(比如 ODBC 或 JDBC)从数据库服务器中读取字符串时,客户端需要从服务器获知所使用的 ANSI 编码。当数据库服务器发送字节流给客户端时,客户端负责将字节流按照正确的编码转化成 UNICODE 字符串。

如果从数据库读取字符串时得到乱码,而数据库中存放的数据又是正确的,那么往往还是因为前面提到的“误解一”造成的。解决的办法还是通过 string = new String( string.getBytes("iso-8859-1"), "GB2312") 的方法,重新得到原始的字节串,再重新使用正确的编码转化成字符串。

3.5 电子邮件中的字符串

当一段 Text 或者 HTML 通过电子邮件传送时,发送的内容首先通过一种指定的字符编码转化成“字节串”,然后再把“字节串”通过一种指定的传输编码(Content-Transfer-Encoding)进行转化得到另一串“字节串”。比如,打开一封电子邮件源代码,可以看到类似的内容:

Content-Type: text/plain;
        charset="gb2312"
Content-Transfer-Encoding: base64

sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==

最常用的 Content-Transfer-Encoding 有 Base64 和 Quoted-Printable 两种。在对二进制文件或者中文文本进行转化时,Base64 得到的“字节串”比 Quoted-Printable 更短。在对英文文本进行转化时,Quoted-Printable 得到的“字节串”比 Base64 更短。

邮件的标题,用了一种更简短的格式来标注“字符编码”和“传输编码”。比如,标题内容为 "中",则在邮件源代码中表示为:

// 正确的标题格式
Subject: =?GB2312?B?1tA=?=

其中,

  • 第一个“=?”与“?”中间的部分指定了字符编码,在这个例子中指定的是 GB2312。
  • “?”与“?”中间的“B”代表 Base64。如果是“Q”则代表 Quoted-Printable。
  • 最后“?”与“?=”之间的部分,就是经过 GB2312 转化成字节串,再经过 Base64 转化后的标题内容。

如果“传输编码”改为 Quoted-Printable,同样,如果标题内容为 "中":

// 正确的标题格式
Subject: =?GB2312?Q?=D6=D0?=

如果阅读邮件时出现乱码,一般是因为“字符编码”或“传输编码”指定有误,或者是没有指定。比如,有的发邮件组件在发送邮件时,标题 "中":

// 错误的标题格式
Subject: =?ISO-8859-1?Q?=D6=D0?=

这样的表示,实际上是明确指明了标题为 [0x00D6, 0x00D0],即 "中",而不是 "中"。

4. 几种错误理解的纠正

误解:“ISO-8859-1 是国际编码?”

非也。iso-8859-1 只是单字节字符集中最简单的一种,也就是“字节编号”与“UNICODE 字符编号”一致的那种编码规则。当我们要把一个“字节串”转化成“字符串”,而又不知道它是哪一种 ANSI 编码时,先暂时地把“每一个字节”作为“一个字符”进行转化,不会造成信息丢失。然后再使用 bytes = string.getBytes("iso-8859-1") 的方法可恢复到原始的字节串。

误解:“Java 中,怎样知道某个字符串的内码?”

Java 中,字符串类 java.lang.String 处理的是 UNICODE 字符串,不是 ANSI 字符串。我们只需要把字符串作为“抽象的符号的串”来看待。因此不存在字符串的内码的问题。



KE 2007-09-13 22:34 发表评论
分享到:
评论

相关推荐

    tera term中文乱码问题

    首先,我们要理解中文乱码产生的原因。通常,当终端与远程服务器之间的字符编码不匹配时,就会出现乱码。Tera Term默认可能使用UTF-8编码,而服务器可能配置为使用GB18030或其他编码格式。因此,解决这个问题的关键...

    web 开发中遇到的乱码问题

    在实际开发中,理解字符编码的原理和作用,以及如何在不同环境和组件间正确转换,对于避免和解决乱码问题至关重要。通过学习和掌握这些知识,可以显著提升web应用的用户体验,避免因乱码导致的信息丢失或误解。

    字符,字节和编码.中文问题”,“乱码问题”。

    本文介绍了字符与编码的发展过程,相关概念的正确理解。...然后,本文讲述了通常对字符与编码的几种误解,由于这些误解而导致乱码产生的原因,以及消除乱码的办法。本文的内容涵盖了“中文问题”,“乱码问题”。

    TT模拟器7.5不发乱码

    这在很大程度上提升了用户体验,使得操作更加简便,避免了因乱码导致的误解或操作错误。 爱富丽TT模拟器的主要功能是让用户能够直接通过计算机来控制灯光设备,实现对灯光的精确调节和管理。这种模拟器适用于各种...

    java字符编码

    本文介绍了字符与编码的发展过程,相关概念的正确理解。...然后,本文讲述了通常对字符与编码的几种误解,由于这些误解而导致乱码产生的原因,以及消除乱码的办法。本文的内容涵盖了“中文问题”,“乱码问题”。

    字符,字节和编码基础知识

    本文介绍了字符与编码的发展过程,相关概念的正确理解。...然后,本文讲述了通常对字符与编码的几种误解,由于这些误解而导致乱码产生的原因,以及消除乱码的办法。本文的内容涵盖了“中文问题”,“乱码问题”。

    Unicode码字符转换器

    有了Unicode码字符转换器,用户可以方便地解决这类问题,避免信息丢失或误解。 在实际应用中,Unicode码字符转换器还可能包含其他功能,如解码、编码识别、字符映射查看等,以满足不同用户的需求。此外,对于编程...

    教师信息化课堂教学领导力开发.pdf

    由于提供的文件内容存在大量的乱码和无法识别的字符,无法从中准确提取和生成与“教师信息化课堂教学领导力开发”相关知识点。但根据文件的标题和描述,我们可以推测该文档应当涉及以下几个方面的内容: 1. 教师...

    算法参考资料飞思卡尔电磁组赛道检测

    在赛道检测算法中,通常会用到几种关键技术: 1. 数据采集:使用电磁传感器来采集赛道上的电磁信号。这些电磁传感器一般安装在智能车的底部,能够感应赛道中埋设的金属导线产生的电磁场。 2. 信号预处理:采集到的...

    SQL Server索引使用的几个误区.pdf

    标题中提到的“SQL Server索引使用的几个误区.pdf”指明了文档的主题是关于SQL Server数据库中索引的使用,同时强调了一些常见错误和误解。这部分内容通常会涉及索引在数据库中的作用、种类以及如何正确使用索引来...

    首经贸会计硕士复试分数线是多少.pdf

    会计硕士专业学位(Master of Professional Accounting,简称MPAcc),是一种专业硕士学位,主要针对已有一定工作经验,希望在会计专业领域进行深入学习和研究的在职人员或者应届毕业生。MPAcc旨在培养具备良好的...

    全国手机号码段归属地数据库(包括区号,邮编,共36万+条记录)

    阅读这个文件可以帮助用户更好地理解和使用数据库,避免误解或误操作。 综上所述,这个手机号码段归属地数据库是一个强大的工具,可用于开发电话号码验证服务、地理位置分析、市场营销策略制定等多种用途。掌握如何...

    给排水管道安装技术交底.pdf

    由于提供的文件内容存在大量的数字、字母和数字串混合的乱码,以及部分由于OCR技术问题导致的识别错误,这使得直接解读文本内容并从中提取知识点非常困难。但是,考虑到文件的标题和描述提及了“给排水管道安装技术...

    穆勒最新选型手册一.pdf

    为了更有效地利用选型手册,建议采取以下几种策略: - **全面了解需求**:在查阅手册之前,首先要清楚自己的具体需求,这样才能有针对性地寻找相关信息。 - **对比分析**:如果同时考虑多个选项,可以通过制作对比...

    JS失效 提示HTML1114: (UNICODE 字节顺序标记)的代码页 utf-8 覆盖(META 标记)的冲突的代码页 utf-8

    这部分内容还提到了编码设置的常见误解和实际操作情况。在实际开发中,尽管页面可能以gb2312编码保存,但JavaScript文件往往使用UTF-8编码,尤其是当页面不包含中文字符时,这种差异通常不会引起问题。开发者可以...

    易游英文目录转

    对于游戏运营团队或者技术维护人员来说,这样的工具可以提高工作效率,减少因语言障碍可能导致的误解或操作错误。 在游戏运营过程中,目录结构的清晰和易读性至关重要。英文目录对于非英语背景的用户可能造成困扰,...

    Qt知识点梳理 —— 国际化 QtLinguist 应用

    1. **编码规范**:确保.ts文件和源代码使用相同的字符编码,以防止乱码问题。 2. **翻译资源管理**:对于大型项目,可能需要管理多个.ts文件,应合理组织和命名,以便管理和维护。 3. **更新处理**:当源代码中的...

    小程序“微信电商”或奇袭阿里.pdf

    由于提供的文件内容片段较为混乱,且包含大量乱码,本回答尝试从有限的信息中提取潜在的知识点,但请注意信息的不完整性可能导致理解上的偏差。 标题所提及的小程序“微信电商”,即指依托微信平台的电子商务应用,...

    coding_note_2020:注意编码

    这些只是编码过程中需要注意的一些基本要点,实际的编码笔记可能涵盖了更具体的技术细节、陷阱和解决方案。通过深入学习和实践,开发者可以不断提升自己的编程技能,编写出高质量、易于维护的代码。

Global site tag (gtag.js) - Google Analytics