<分享>告别乱码 – 网站编码问题汇总

本文全面解析了计算机编码中的常见问题,从乱码产生的原因入手,详细解释了ANSI、Unicode、UTF-8等概念的区别与联系,并提供了JavaScript URI编码/解码的具体方法。此外,还讨论了不同场景下编码的选择及解决方案。

<分享>告别乱码 – 网站编码问题汇总

相信各位同行或多或少都会碰到过乱码的问题。
从来没有?相信我,只是时候未到,在这行混,迟早会碰到的。
当然,如果你对各类编码非常了解,对浏览器脾气摸得很清楚了,你可以避开或者快速解决此类问题。
希望这篇文章对你有所帮助。

一、为什么会出现乱码?
在计算机中,我们储存的信息都是用二进制码表示的。我们文字和符号用的二进制代码的互相转换,就是编码,转换需要一种规则,就是字符集(charset),我们常用的字符集例如:ascii,gb2312,unicode。
不同的字符集所存储的内容不同, 比如“太平洋”三个字采用gb2312对应的值为4411 3829 4983,utf-8对应为E5 A4 AA E5 B9 B3 E6 B4 8B,这样,当一个gb2312的文件嵌入一个utf-8的文件的时候,问题就来了。

二、ANSI, Unicode, UTF-8, Encode, Charset, HTML实体… 我快疯了
疯完了没,没昏就行了,别着急,听我一一道来。其实这只是同一样东西在不同场合的应用。
A. ANSI, Unicode, UTF-8
这几个归为一类,它们是文件编码。
ANSI指当地编码,比如在大陆它指GB2312,在台湾它指GBK(Win中记事本保存文件的时候的默认选项就是它)。
Unicode是一个通用字符集,它是一个编码标准,这个和GB2312是对应的,但因为字符集过大,Unicode有它的特殊性,在不同应用场合,有不同的具体实现手法,比如应用于互联网传输,采用的存储与传送格式是UTF-8,Windows应用UTF-16,Linux 应用UTF-32。
B. Charset
HTML中的Charset,CSS中的@charset,XML中的encoding等,这几个归为一类。
它们是告诉浏览器如何解码。比如psd后缀是告诉系统这是Photoshop源文件,同样charset设为gb2312是告诉浏览器这是一个简体中文的网页。

C. Encode
Encode和encodeURI,encodeURIComponent归为一类。
这在下一节中进行比较详细的介绍。当浏览器提交数据给服务器时,特殊字符中文一般浏览器会自动编码,但存在部分保留字符,比如”# /”等,这时候需要encode等进行转换。
D. HTML实体
当网页中需要插入某些特殊字符时,需要用到HTML实体,比如插入<,可以使用<或者实体编码<。

三、Javascript URI编码/解码
A.为什么需要URI编码?
通常来说,之所以URI需要进行编码,是因为URI中有些字符可能会引起歧义或者有隐私的数据。
B. 编码与解码的函数?
JS对文字进行编码涉及3个函数:escape,encodeURI,encodeURIComponent,相应3个解码函数:unescape,decodeURI,decodeURIComponent
C. 如何选择?
首先,范围不同。Escape不能编码的字符有: @ * / +;encodeURI:! @ # $& * ( ) = : / ; ? + ‘ ; encodeURIComponent:! * ( ) 。
其次,编码类型不同。encodeURI、encodeURIComponent采用utf-8进行编码;而Escape采用系统编码。
所以,怎么选择?例如内容中要存在URI标识,则用encodeURI,如果想把”#,/”也要编码用escape或encodeURIComponent。

四、Ajax加载的文件中不能用中文?
这一直是让开发人员很头疼的问题之一,也是常见的编码问题,原因很简单,你非得拿羊城通往ATM上插,结果当然是读不出来或者读错。编码问题也是一样,通常出错的情况是,文档编码是GB2312,而浏览器以UTF-8(Ajax默认解码方式)来解码,自然乱码。
怎么解决呢?
1、文档采用UTF-8编码,不会产生任何问题。
2、如果不能用UTF-8,XML文档可以指定它的Encoding,JS文件和JSON数据目前没有好的解决办法。

五、GB2312,UTF-8都可以显示中文,如何选择?
可以显示中文的编码有GB2312、GBK、GB18030、Unicode。前三个保持向后兼容,比如“太平洋”这几个字在这几个编码规则中内码是一样的。它们的不同之处在于字符集不同,GB2312只包括简体中文,GBK还包括繁体,GB18030再加入了少数民族语言,比如藏文。那如果显示简体中文可以任意选择?据我目前测试了解,应该都是可以的,至于速度上是否有差异,还未深究,但GB2312肯定更为通用,而且据我测试已经包含了相当部分繁体。至于Unicode,应用在网页中的UTF-8,中文一般需要占据3个字节(前三种2个字节),所以当中文较多的网页用UTF-8文件将变得更大(我们公司大部分网页4%左右)。

六、UTF-8、UTF-16、UTF-32什么区别?
Unicode所做的是为每个字符定义了一个相应的数字表示。比如,“a“的Unicode值是0×0061,“一”的 Unicde值是0×4E00,这是最简单的情况,每个字符用2个字节表示。 Unicode定义了百万个以上的字符,如果将所有的字符用统一的格式表示,需要的是4个字节。“a“的Unicode表示就会变成 0×00000061,而“一“的Unicode值是0×00004E00。实际上,这就是UTF32,Linux操作系统上所使用的Unicode方案。但是,仔细分析可以发现,其实绝大部分字符只使用2个字节就可以表示了。英文的Unicode范围是0×0000-0×007F,中文的Unicode范围是0×4E00-0×9F**,真正需要扩展到4个字节来表示的字符少之又少,所以有些系统直接使用2个字节来表示Unicode。比如Windows 系统上,Unicode就是两个字节的。对于那些需要4个字节才能表示的字符,使用一种代理的手法来扩展(其实就是在低两个字节上做一个标记,表示这是一个代理,需要连接上随后的两个字节,才能组成一个字符)。这样的好处是大量的节约了存取空间,也提高了处理的速度。这种Unicode表示方法就是 UTF16。一般在Windows平台上,提到Unicode,那就是指UTF16了。 而UTF-8更有意思,它的字节数1-4个不等,如果纯英文的应用环境,自然用它更加节省。

七、CSS、JS的编码可以和HTML不一致吗?
可以。但最好在引用时手动设置Charset,值得注意的是IE、FF默认根据当前页面编码,而Chrome默认是UTF-8。

八、我这人比较懒,直接给点建议吧。
懒得够可以的,好吧,那我想到几条写几条:
1、框架页不受父页面编码影响;
2、关于浏览器编码纠错。
测试:创建utf-8文件,更改meta charset属性为gb2312(文件本身数据编码不变),外链gb2312的JS文件,结论:
IE&Chrome自动以utf-8解析,外链JS乱码;
FF以gb2312解析,外链JS中文显示正常。Demo: 测试自动解析编码.html
3、Ajax加载,如果目标文档文件编码非UTF-8,需指定encoding,否则中文乱码;
XML是可以指定编码的,但如果是JSON,Script之类的数据,无法指定编码,要显示中文只有用UTF-8的编码;
4、外链的js,IE、FF默认根据当前页面编码,Chrome默认是Utf-8。如果JS文件为Unicode编码,给文件加上bom比较保险(IE、FF的智能识别)
5、Get数据,IE678,ff3 GBK编码,Chrome utf-8编码。
6、想完全避免它,如果条件允许,网站前后台数据库全部统一用utf-8吧,万事大吉,想碰到编码问题都难。
全部统一用gb2312?不行,问题照出,原因在上文中。

<think>好的,我现在需要解决用户提出的关于JSP页面中类型不兼容导致的乱码问题,特别是涉及`java.util.ArrayList`和`com.sun.tools.javac.util.List`之间的转换,以及使用JSTL的`c:if`标签的情况。首先,我需要回顾用户之前的问题和我的回答,确保解决方案一致且参考了提供的引用。 用户提到类型不兼容和乱码问题,这两者可能有不同的原因。类型不兼容通常发生在Java代码中,而乱码可能与字符编码有关。但用户可能是在转换集合类型时,由于编码处理不当导致数据显示乱码。此外,用户提到了JSTL的`c:if`标签,可能需要检查在JSP中使用该标签时是否正确处理了数据。 根据用户提供的引用,引用[1]提到了在JSP中使用JSTL需要导入标签库,并且正确配置jar包。引用[2]讨论了JSP中的注释类型,但可能和当前问题关联不大。引用[3]给出了Java环境的版本信息,可能与问题无关,但需要确保环境正确。 首先,检查类型转换是否正确。在之前的回答中,我提到了如何通过迭代转换`ArrayList`和`com.sun.tools.javac.util.List`之间的类型。如果用户正确执行了这些转换,但依然出现乱码,可能是在数据传递到JSP页面时未正确设置字符编码。 其次,考虑JSP页面的编码设置。JSP页面需要声明正确的页面编码,如`<%@ page contentType="text/html;charset=UTF-8" %>`,同时确保Tomcat服务器的编码配置正确,如`server.xml`中的URIEncoding设置为UTF-8。 另外,处理JSTL标签时,尤其是`c:if`,需要确保传递的参数类型正确,避免因类型不匹配导致标签无法正确解析,从而引发错误或显示问题。如果`c:if`的条件表达式涉及到转换后的集合,需要确保集合中的元素类型正确,且没有编码问题。 可能还需要检查HTTP响应和请求的编码设置,确保前后端使用一致的编码格式,例如在Servlet中设置`response.setContentType("text/html;charset=UTF-8")`和`request.setCharacterEncoding("UTF-8")`。 总结可能的解决方案步骤: 1. 确保类型转换正确,使用之前提供的方法转换集合类型。 2. 检查并设置JSP页面的编码声明和服务器配置。 3. 验证JSTL标签的使用是否正确,特别是数据传递和条件判断。 4. 统一整个应用的字符编码设置,包括请求和响应。 同时,需要参考用户提供的引用[1],确保JSTL的jar包正确导入,避免因缺少依赖导致标签无法解析,进而引发页面显示问题。</think>### JSP 页面类型不兼容及乱码问题的解决方案 针对您描述的 **类型不兼容导致乱码** 的问题,结合 `java.util.ArrayList` 与 `com.sun.tools.javac.util.List` 的转换需求以及 JSTL 标签的使用,以下是分步解决方案: --- #### 一、类型不兼容问题解决 ##### 1. 集合类型转换(参考之前回答) 若需将 `java.util.ArrayList` 转换为 `com.sun.tools.javac.util.List`,可使用以下方法: ```java public static <T> com.sun.tools.javac.util.List<T> convert(ArrayList<T> arrayList) { com.sun.tools.javac.util.List<T> javacList = List.nil(); for (T item : arrayList) { javacList = javacList.append(item); } return javacList; } ``` **关键点**:确保转换后的数据在传递到 JSP 前已正确处理字符编码。 --- ##### 2. 数据传递到 JSP 前的编码处理 在 Servlet 或 Controller 中设置响应编码: ```java response.setContentType("text/html;charset=UTF-8"); request.setCharacterEncoding("UTF-8"); ArrayList<String> dataList = new ArrayList<>(); dataList.add("中文内容"); // 转换为目标类型(可选) com.sun.tools.javac.util.List<String> convertedList = convert(dataList); // 直接传递 ArrayList 到 JSP request.setAttribute("dataList", dataList); request.getRequestDispatcher("/page.jsp").forward(request, response); ``` --- #### 二、JSP 页面乱码问题解决 ##### 1. JSP 页面编码声明 在 JSP 文件头部添加编码声明: ```jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ``` ##### 2. Tomcat 服务器配置 修改 `conf/server.xml` 中的 Connector 配置,添加 URI 编码: ```xml <Connector port="8080" protocol="HTTP/1.1" URIEncoding="UTF-8" connectionTimeout="20000" redirectPort="8443" /> ``` --- #### 三、JSTL 标签 `c:if` 的正确使用 ##### 1. 确保 JSTL 依赖已正确引入(参考引用[1]) - 将 `jstl.jar` 和 `standard.jar` 放入 `WEB-INF/lib` 目录。 - JSP 头部声明标签库: ```jsp <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ``` ##### 2. 处理集合数据与条件判断 在 JSP 中遍历 `ArrayList` 并使用 `c:if`: ```jsp <c:forEach items="${dataList}" var="item"> <c:if test="${not empty item}"> <p>${item}</p> </c:if> </c:forEach> ``` **注意**:若集合元素包含特殊字符,可通过 `fn:escapeXml` 避免乱码: ```jsp <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <p>${fn:escapeXml(item)}</p> ``` --- #### 四、验证与调试 1. **检查 HTTP 响应头**: 使用浏览器开发者工具(F12),查看响应头是否包含 `Content-Type: text/html;charset=UTF-8`。 2. **日志输出**: 在 Java 代码中打印集合内容,确认数据本身无编码错误: ```java System.out.println("数据内容:" + new String(item.getBytes(), StandardCharsets.UTF_8)); ``` --- ### 总结 | 问题类型 | 解决方案 | |--------------------|--------------------------------------------------------------------------| | 类型不兼容 | 显式转换集合类型 + 确保编码一致性 | | 乱码问题 | 统一编码声明(JSP/Servlet/Tomcat) + 使用 JSTL 函数处理特殊字符 | | JSTL 标签解析异常 | 检查依赖引入 + 避免直接使用非标准集合类型(优先传递 `ArrayList` 到 JSP) | 通过上述步骤,可同时解决类型不兼容和乱码问题。若仍存在异常,需进一步检查环境配置(如 JDK 版本兼容性,参考引用[3])。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值