`
yyyyy5101
  • 浏览: 153036 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

关于乱码问题

阅读更多
1 乱码的根源
在计算机中所有的数据最终都必须序列化成字节序列,如果数据恰好表示就是字符,这种序列化的过程称作编码 , 反之当要读取序列化的数据,要先反序列化,对字符数据这种过程称之为解码 。 编码和解码过程有着紧密的关联,都由编码 (前述的’编码’是一个动词,这里是一个名词)决定, 一个编码(如UTF-8,GBK)就决定了一个编码过程和一个解码过程。 只有当编码过程和解码过程使用相同的编码时,字符数据才能被正确解释,否则乱码就产生了。 乱码问题的根源就在于对字符数据的编码(写入)和解码(读取)使用了不同的编码 。



为了便于说明,我们称字符数据第一次被序列化(写入或编码)时使用的编码称为初始编码 , 最后一次被序列化时使用的编码称为当前编码 。 要反序列化(读取或解码)字符数据一般来说要使用和初始编码相同的编码。 以文本文件为例,初始编码为GBK的文本文件一般只能使用GBK来解码才能读到正确的内容, 否则就会得到乱码(不正确或毫无意义的内容)。 但是也有例外,初始编码为GB2312的文本文件能够使用GBK编码来读取,这是因为GBK兼容GB2312, 类似的,初始编码为ISO-8859-1的文本文件可以使用UTF-8编码来读取,反之却不行,初始编码 为UTF-8的文本文件不能使用ISO-8859-1来读取。假设一个初始编码为GB2312的文本文件用UTF-8 编码读取,然后再使用UTF-8编码写入到同一个文件, 下次读取时无论使用GB2312编码还是使用UTF-8编码都无法回复到以前的内容。 使用与初始编码不兼容的编码先读取然后写入一般会导致初始内容遭到永久性破坏从而表现出乱码 。 这里的例外是ISO-8859-1,它是个特殊的编码,恰好有256(一个字节能够容纳的数)个字符。 对任意初始编码的文本文件,使用ISO-8859-1读取它的内容(虽然读取的内容可能表现出乱码), 然后再以ISO-8859-1写入原文件,文件内容保持不变,下次仍能以初始编码来读取文件的正确内容。 这或许是为什么JSP的许多默认编码设置成ISO-8859-1的原因。



这种乱码出现在需要多次序列化和反序列的情况下,而这在Java程序中非常常见。 为了避免乱码需要确保所有的序列化和反序列化过程使用相同的编码 ,任何一个过程 使用了不正确的编码都将导致乱码,这使得乱码问题变得十分复杂,这首先要求 我们必须对程序所有的编码和解码过程都十分清楚。下面我们就要探讨常见Java程序的编码和解码过程。

2 编码和解码过程
2.1 Java独立应用程序
在考虑Java应用程序的编码和解码过程时不仅仅要考虑运行时编码和解码过程,而且要考虑编译时的编码和 解码过程。通常Java独立应用程序的第一个编码过程是将Java程序写入到一个后缀为”.java”的文本文件中, 在编译java程序时,编译器需要知道Java文件的编码,其默认使用系统平台的编码,Windows一般是“GBK” ,Linux一般是“UTF-8”,可以使用-encoding选项来指定java文件的编码。 如果编译器使用的编码和Java文件使用的编码不相同,就会造成乱码问题。 单个人使用单个平台开发时一般不会遇到这种问题,多人开发时必须统一Java源文件的编码, 我一般喜欢使用UTF-8,编译时也要指定编码,即使源文件编码与平台默认编码相同也是如此, 这样才不会依赖某个平台。使用不同的方式来编译Java程序时,它们都有自己的方式来指定 源文件的编码,javac通过”-encoding”选项,ant通过javac任务的encoding属性,maven 通过设置compiler插件的encoding元素值。值得注意的是,当指定了错误的编码时,编译 可能都会通不过。



运行时的编码和解码过程主要是对文本文件的读和写。在Java中通过下面的方式的获得一个Writer(字符写入器):

Writer writer = new  OutputStreamWriter(new  FileOutputStream("your_file_name" ), "replace_it_with_encoding" );


当不指定文件编码时,默认编码是系统属性file.encoding的值,可以在java启动时通过”-Dfile.encoding=utf-8”来设置默认 编码为utf-8。最好在创建Writer时指定文件编码,这可以避免对平台的依赖。 通过下面的方式获得一个Reader(字符读取器):

Reader reader = new  InputStreamReader(new  FileInputStream("your_file_name" ), "replace_it_with_encoding" );


同样不指定编码时,默认编码是系统属性file.encoding的值,创建Reader时最好显式指定编码值,这样可以避免对平台的依赖。 对于配置文件(如xml文件)我的建议是统一使用“UTF-8”编码。 一般来说这种乱码问题很容易解决,只需要指定和文件对应的编码就可以了。 一个例外是properties文件的读取,在jdk6之前,没有对属性文件指定编码的API, Properties只有一个load(InputStream)方法,jdk6中增加一个load(Reader)方法, 这样就可以对属性文件指定编码。jdk6之前properties文件的编码必须是ISO-8859-1, 不能表示的字符只能使用Unicode转义符来表示,需要使用native2ascii工具将某种编码 的属性文件转换成属性文件所需的格式。



另一个比较常见的运行时的编码和解码过程是对数据库的读和写。这和文件的读写类似,只不过Java没有提供公开 的API来设置数据库的编码,这一般由驱动器自动检测,在MySQL中可以通过连接参数来设置数据库的编码。

2.2 Java Web应用程序
Java独立应用程序中的编码和解码过程对于Java Web应用程序也是适用的,这里只探讨和Java Web应用程序相关的 编码和解码过程。同对Java源文件的编译一样,我们先要讨论JSP的编译。对JSP的编译一般分为两步,首先要将 JSP文件转换成Java文件,然后再编译这个Java文件得到class文件,因此这有两个编码和解码过程,但是这个过程是 透明的(读取JSP文件和Java文件使用的编码是相同的),我们可以认为JSP编译器直接将JSP文件编译成class文件。 同样我们必须保证JSP编译器读取JSP文件使用的编码是这个JSP文件的初始编码。和Java编译器不同,JSP编译器 使用的编码是在JSP文件中指定的,例如要使JSP编译器使用UTF-8的编码来读取JSP文件,可以使用:

<%@ page  pageEncoding= "utf-8" %>


如果不指定页面编码,默认值为ISO-8859-1,由于上面所说的ISO-8859-1编码的特殊性,只要正确设置响应编码, 一般来说不会观察到乱码。但是在某些特殊情况下,它可能导致原本正确的JSP文件无法编译,更重要的是编译成 Java文件可能是乱码,我们可能有时需要查看这些Java文件,这会造成稍许不便,因而最好还是设置正确的JSP页面 编码。



当响应是字符数据时,这里假设是HTML内容,需要使用某种编码将它序列化成字节序列,浏览器 (或者其它的客户端)读取响应时必须使用相同的编码,否则页面可能就会显示乱码, 一般浏览器会根据响应头Content-Type的值自动检测响应的编码。为了使浏览器能够检测到 正确的编码,可以在JSP中通过如下方式设置Content-Type响应头:

<%@ page   contentType = "text/html;charset=utf-8" %>


上面的代码设置响应头Content-Type的值为“text/html;charset=utf-8”,浏览器会自动使用 UTF-8编码来读取响应内容。如果浏览器自动决定的编码不正确(这是由于没有设置正确的Content-Type响应头), 主流浏览器(如IE和Firefox)都允许手动选择编码。如果在JSP中没有指定ContentType,则会根据 pageEncoding的值来设置响应编码,如果pageEncoding也没有设置,那么响应编码的值就是ISO-8859-1。 另外响应的编码的值可以在运行时调用方法response.setCharacterEncoding(“your_encoding”)来动态改变。



和响应编码对应的是请求编码。请求一般是由浏览器发送的,Firefox和IE中使用的编码是当前页面的编码, Firefox和IE中都可以通过菜单”查看→字符编码”得到当前页面的编码,它通常就是响应编码(如果没有手工设置编码)。 为了读取到正确的内容,服务器端也必须使用同样的编码(通常是响应编码)来读取请求内容。在JSP中无法直接设置请求编码, 但是可以通过request.setCharacterEncoding(“your_encoding”)来设置。不幸的是,在Tomcat中并没有使用请求编码来解码URI, 默认使用ISO-8859-1编码,要修改URI的编码需要在tomcat的配置文件中设置。

分享到:
评论

相关推荐

    乱码问题的解决

    "乱码问题的解决" 在 Web 开发中,乱码问题是常见的难题之一。乱码问题的出现主要是由于编码不一致引起的。编码不一致可能出现在多个方面,如页面编码、服务器编码、客户端编码、数据库编码等。在本文中,我们将...

    ffmpeg.exe在windows修正乱码,命令行支持中文字幕文件名

    首先,关于乱码问题,这通常是因为FFmpeg在Windows上默认不支持Unicode编码,尤其是在命令行环境下,可能会对非ASCII字符(如中文字符)处理不当。为了解决这个问题,开发者可能对FFmpeg进行了编译配置修改,使其...

    解决JSP中文乱码问题

    解决 JSP 中文乱码问题 解决 JSP 中文乱码问题是一个很常见的问题,在 JSP 开发过程中,经常出现中文乱码的问题,可能一至困扰着大家。下面我们将详细讨论 JSP 中文乱码问题的成因和解决方法。 JSP 中文乱码问题的...

    qt乱码问题解决

    qt乱码问题解决

    中文乱码问题分析 自己总结的

    中文乱码问题分析 中文乱码问题是 Java 和 JSP 开发中的一种常见问题,主要是由于 Java 和 JSP 源文件的保存方式是基于字节流的,而编译成 class 文件过程中,使用的编码方式与源文件的编码不一致所致。在 Java ...

    乱码解决 乱码解决 乱码解决 乱码解决 乱码解决

    在IT领域,乱码问题是一个常见的困扰,尤其是在处理文本数据时。乱码通常指的是字符显示不正确或无法识别,这可能由于编码格式不匹配、文件损坏、程序设置不当等原因引起。下面将详细讨论乱码产生的原因、解决方案...

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

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

    润乾报表乱码问题

    在信息技术领域,乱码问题是指字符在计算机中由于编码不一致或者不正确而导致的显示错误,通常表现为无法识别的特殊符号或者乱糟糟的方块。润乾报表乱码问题尤其令人头疼,因为它影响了数据的显示和传输,尤其是对于...

    hadoop中文乱码问题

    【Hadoop中文乱码问题详解】 在大数据处理领域,Hadoop是一个不可或缺的开源框架,它提供了分布式存储(HDFS)和分布式计算(MapReduce)的能力。然而,在处理包含中文字符的数据时,用户可能会遇到中文乱码的问题...

    设置乱码问题(设置乱码问题)

    ### 设置乱码问题详解 #### 一、理解乱码问题 在进行数据库操作时,可能会遇到数据呈现为不可读字符的现象,这种情况通常被称为“乱码”。出现乱码的原因多种多样,比如字符集设置不一致、编码转换错误等。解决...

    js出现乱码问题介绍大全

    ### JS出现乱码问题介绍大全 #### 一、引言 在Web开发中,字符编码问题经常困扰开发者,特别是当涉及到不同语言环境时。JavaScript作为前端开发的核心技术之一,在处理字符编码方面同样会遇到各种各样的乱码问题。...

    解决中文乱码问题

    "解决中文乱码问题" 在Java编程中,中文乱码是一个常见的问题。为了解决这个问题,我们需要从多个方面入手。首先,我们需要将Eclipse的编码方式设置为UTF-8,以便正确地显示中文字符。其次,我们需要在浏览器中将...

    解决Ubuntu和Windows的文件乱码问题

    本文详细介绍了如何解决Ubuntu和Windows在处理文件时发生的乱码问题。 首先,我们需要了解文件乱码的原因。Windows系统中的许多纯文本文件(包括压缩文件)默认使用GBK编码,这是一种针对中文字符的扩展字符集。当...

    Java关于中文乱码问题的多种解决方法

    在Java编程中,中文乱码问题是一个常见的困扰,尤其是在处理文件读写、网络传输或数据库操作时。本文将深入探讨几种解决Java中中文乱码问题的方法,并以MyEclipse为开发环境,结合实际示例进行讲解。 1. 文件读写中...

    JAVA 乱码问题集合

    在Java编程中,乱码问题是一个常见的困扰,尤其是在处理字符编码时。以下是一些关键的知识点,可以帮助理解和解决Java中的乱码问题。 首先,我们需要理解字符编码的基本概念。字符编码是用来表示文本的一种方式,...

    springboot乱码问题解决方案

    SpringBoot乱码问题解决方案 SpringBoot框架是一款流行的Java Web开发框架,但是在实际开发中,开发者经常会遇到乱码问题,导致项目无法正常运行。为了解决这个问题,本文将详细介绍SpringBoot乱码问题解决方案,并...

    中文乱码问题

    中文乱码问题解决方案 中文乱码问题是 web 开发中经常遇到的问题,特别是在使用 JSP、Servlet、Struts 2 等技术时。乱码问题的出现主要是由于字符编码不一致所致。以下是解决中文乱码问题的知识点: JSP 文件的...

    解决linux下oracle中文乱码问题,添加中文支持

    解决linux下oracle中文乱码问题,添加中文支持解决linux下oracle中文乱码问题,添加中文支持解决linux下oracle中文乱码问题,添加中文支持解决linux下oracle中文乱码问题,添加中文支持解决linux下oracle中文乱码...

    Netty进制转换乱码问题

    在使用Netty进行TCP/IP通信时,我们可能会遇到数据进制转换导致的乱码问题。这个问题通常是由于数据编码不一致或者处理方式不当所引起的。在本文中,我们将深入探讨Netty中的进制转换和字符编码,并提供解决方案。 ...

    Java开发乱码问题解决方法汇总

    Java开发乱码问题解决方法汇总 Java开发中乱码问题是非常常见的问题之一,而解决这些问题需要具备一定的技术知识和经验。在本文中,我们将总结一些常见的Java开发乱码问题解决方法,希望能够为读者提供帮助。 1. ...

Global site tag (gtag.js) - Google Analytics