整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Web开发中常见的“乱码”

Web开发中常见的“乱码”

题来源:

在微信公众号开发指定回复消息为文本格式的时候,尝试了几种换行方式都不行,最终了解即 XML 的换行应使用:

是字符实体编号(16进制),可以用于处理XML中文本的换行。

对应的正确代码在第9行(部分文字有修改):

<xml>
 <ToUserName><![CDATA[<%=toUserName %>]]></ToUserName>
 <FromUserName><![CDATA[<%=fromUserName %>]]></FromUserName>
 <CreateTime><% createTime %></CreateTime>
 <MsgType><![CDATA[<%=msgType %>]]></MsgType>
 <% if (msgType==='text') { if(content!=="zs") { %>
 <Content><![CDATA[<%=content %>]]></Content>
 <% } else { %>
 <Content>欢迎来到报名图书馆暑假工!
报名步骤:
①将招聘推文转发至朋友圈或者40人以上的群,让更多同学了解本招聘。为招聘方宣传以找到更多优质学生员工。
→<a href="http://a.xiumi.us/board/v5/29Ndm/47380885">点此进入招聘推文</a>
②回复你的资料:报名+姓名+电话号码+深圳哪个区+可上班时间
</Content>
 <% }} else if (msgType==='zs') { %>
 <Content><a href="http://www.baidu.com/?k381740148">ddwadwada</a></Content>
 <% } else if (msgType==='image') { %>
 <Image>
 <MediaId><![CDATA[<%=content.mediaId %>]]></MediaId>
 </Image>
 ...
</xml>

由这个问题,我们想到web开发中还有一些类似的“乱码”,这些乱码又有哪些规律呢?

字符实体

字符实体是XML和HTML中的字符编码方式,也就是上面事例中提到的,格式为:

& + 实体名称 + ;
& + (# + unicode编码) + ;

实体名称一般是有意义的词,方便大家记忆,比如小于号<的实体名称是lt,也就是less than的缩写。只有部分符号是有实体名称的,使用unicode编码是更通用的写法。

像文字类一般不会采用这种编码方式,主要用于在HTML或XML文档中输出一些保留字符和空格,比如我想在HTML中展示一段html代码就需要使用字符实体

比如我们要展示`<p>情深深雨蒙蒙</p>` 以下两种表示是等效的
?
<pre>
 <p>情深深雨蒙蒙</p>
 <p>情深深雨蒙蒙</p>
</pre>

总而言之,字符实体是HTML和XML中的编码方式,比如在HTML文档中写入:我,那么最终页面上看到的是我这个汉字。

unicode字符

编程语言中的unicode字符的格式为:

\u + 16进制unicode编码

绝大多数编程语言,包括CSS中都支持unicode字符,不过HTML和XML是不支持的。那么什么时候使用unicode字符呢?一般来说有两种场景:

  1. 避免文件保存时采用不同编码导致的乱码,因为\u已经声明了是unicode。
  2. 正则匹配中的一些应用:Unicode编码及在正则表达式中的使用

在JS中可以使用charCodeAt()获取字符串的10进制unicode编码

URL编码

类似%E6%88%91这样的,叫做URL编码,在链接的参数里非常常见

网络标准RFC 1738做了硬性规定:

“只有字母和数字[0-9a-zA-Z]、一些特殊符号”$-_.+!*'(),”[不包括双引号]、以及某些保留字,才可以不经过编码直接用于URL。”

所以像汉字,空格这些都必须经过转码。上面讲的unicode字符,字符实体用的都是unicode编号,而URL编码用的则是utf-8, 规则是将utf-8编码每隔两个字符加一个%

UTF 是英文 Unicode Transformation Format 的缩写,意为把 Unicode 字符转换为某种格式。unicode和utf-8并不是同一种东西,但是又存在着联系:unicode是信源编码,对字符集数字化; utf-8,utf-16这些是信道编码,为更好的存储和传输。

简单说,unicode就是一组数字,每一个数字对应一个字符。utf-8就是对字符的传输和保存时的规则。比如说“我”这个字,unicode码(16进制)是6211,utf-8是E68891, 那么对应的URL编码就是%E6%88%91;

{
 Unicode编码: 0x6211,
 UTF8编码: E68891,
 UTF16编码: FEFF6211,
 UTF32编码: 0000FEFF00006211
 URL编码: %E6%88%91
}

更多细节可以参考《阮一峰:关于URL编码》

总结

Web开发中常见的几种乱码包括:Unicode字符、字符实体、URL编码。如以下情况都表示“我”

Unicode字符: \u6211
字符实体编号(16进制):我
字符实体编号(10进制):我
URL编码:%E6%88%91

这些编码规则的本质都是一些特殊符号 + Unicode编码 所组成。

希望本文能帮助到您!

点赞+转发,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓-_-)

关注 {我},享受文章首发体验!

每周重点攻克一个前端技术难点。更多精彩前端内容私信 我 回复“教程”

原文链接:http://eux.baidu.com/blog/fe/web%E5%BC%80%E5%8F%91%E4%B8%AD%E5%B8%B8%E8%A7%81%E7%9A%84%E4%B9%B1%E7%A0%81

作者: 郑佳润

开发过程中,经常遇到中文乱码问题,以前总是解决就好,并没有对该问题总结一下,现在来总结一下开发过程中常见的中文乱码问题。

一、有必要了解一些基本的编码知识:

  • 这篇字符编码笔记是必读的

  • jsp的三次编码

    第一阶段:JVM将.jsp文件编译为.java文件。JVM先读取pageEncoding的值,根据该值去读取.jsp文件,然后由指定的编码方案生成UTF-8的.java文件。

    第二阶段:JVM将.java文件转换为.class文件,从UTF-8至UTF-8。这个过程就与任何编码的设置都没有关系了,经过这个阶段后.java文件就转换成了统一的UTF-8编码的.class文件了。

    第三阶段:服务器将处理的结果返回给浏览器,这个阶段则依靠contentType的charset,如果设置了charset则浏览器就会使用指定的编码格式进行解码,否则采用默认的ISO-8859-1编码格式进行解码处理。

  • jsp中的编码设置

  1. pageEncoding:<%@ page pageEncoding=”UTF-8”%>

    上文中第一阶段,使用该值去读取jsp文件,为避免中文乱码,跟jsp文件编码一致;对服务器响应进行重新编码,即jsp的输出流在浏览器中显示的编码(不是主要作用)。

  2. contentType: <%@ page contentType=”text/html;charset=UTF-8”%>

    使用该值对服务器响应进行重新编码,即jsp的输出流在浏览器中显示的编码;对表单get和post请求数据编码;上文中第一阶段,使用该值去读取jsp文件(不是主要作用)。

  3. < META http-equiv=”Content-Type” content=”text/html;charset=UTF-8”>

    网页的编码信息 ,说明页面制作所使用的编码。

  4. request.setCharacterEncoding()

    可用在servlet和jsp页面中,作用是设置对客户端请求进行重新编码的编码,即post方式提交的数据进行编码。

  5. response.setCharacterEncoding()

    与<%@ page contentType=”text/html;charset=UTF-8”%>一样。

  6. response.setContentType()

    与<%@ page contentType=”text/html;charset=UTF-8”%>一样。

  7. response.setHeader(“Content-Type”,”text/html;charset=UTF-8”)

    与< META http-equiv=”Content-Type” content=”text/html; charset=UTF-8”>一样。

    注意:上文1,2,3中有部分功能是一样的,是有优先级的,在读取jsp文件时,1>2;在对服务器响应进行编码的时候,2>1>3,一般情况下,1,2都写。

  • http请求默认以”ISO-8859-1”的编码来传送URL的。

  • 二、中文乱码的几种情况及最简单的解决方案:

    • pageEncoding设置错误

      pageEncoding设置为jsp文件的编码类型。

    • 查询字符串包含中文

      中文的编码方式取决于浏览器,chrome为UTF-8,IE为GB2312,这是由于浏览器并没有遵循URI编码规范。有两种解决方法:

    1. 开发过程中,将查询字符串提前编码,

      如:http://www.baidu.com/demo?demo=%D6%D0%B9%FA (UTF-8编码)

    2. 在Servlet的doGet()方法中添加

    1
    String value=new String(request.getParameter("parameterName").getBytes("ISO-8859-1"),"浏览器的编码方式");
    • 表单中的get和post数据包含中文

      中文的编码方式取决于上文的contentType中的charset,有两种解决办法:

    1. 在Servlet的doPost()方法中添加request.setCharacterEncoding(“charset的值”);(仅对post有用)

    2. 在Servlet的doPost()方法中添加

    1
    String value=new String(request.getParameter("parameterName").getBytes("ISO-8859-1"),"charset的值");

    三、原理

    我们通过上面的方法可以解决乱码问题,下面讲讲原理:

    • 客户端发到服务器的数据需要在客户端进行编码,类似于:String parameterName="中国".getBytes("UTF-8")然后将编码后的数据发到服务器。

    • 客户端接受数据,request.getParameter(“”)的作用就是对接收到的数据进行解码,默认使用ISO-8859-1进行解码,可以使用request.setCharacterEncoding(“”)进行设置,但仅对post有用。假如我们使用默认的ISO-8859-1,肯定乱码,因为编码跟解码不一致,那此时怎么办呢,引出了上文中的两种解决方案:使用request.setCharacterEncoding(“”)改变request.getParameter(“”)的解码方式或者new String(request.getParameter("parameterName").getBytes("ISO-8859-1"),"charset的值")将request.getParameter(“”)解码的数据重新编码再解码。

    四、其他

    在jsp中的页面使用response.setContentType()等设置字符集会破坏jsp容器自身的页面编码,会引起html中字符乱码,脚本不会乱,所以不建议设置。在开发中多采用page指令设置字符集。

    1234567891011121314151617
    <%	response.setContentType("text/html;charset=UTF-8");	String str=new String("你好".getBytes("iso-8859-1"),"utf-8");%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><p>你好</p><br><%=str %></body></html>

    网页测试

    版规则

    缩进

    使用2个空格缩进

    <ul>
      <li>Fantastic</li>
      <li>Great</li>
    </ul>
    .example {
      color: blue;
    }

    大小写

    只允许使用小写。

    所有的代码都用小写字母:适用于元素名,属性,属性值(除了文本和CDATA), 选择器,特性,特性值(除了字符串)。

    <!-- 不推荐 -->
    <A HREF="/">Home</A>
    <!-- 推荐 -->
    <img src="google.png"
    alt="Google">

    行为空格

    建议删除行尾白空格。

    <!-- 不推荐 -->
    <p>What?  </p>
    <!-- 推荐 -->
    <p>Yes please.</p>

    常规Meta规则

    编码

    如果没有特殊需求,一般采用utf-8编码。如果是cms站点,则遵守该站点的编码规则。

    <!-- 网页编码 -->
    <meta charset="utf-8">

    注释

    尽可能的去解释你写的代码。说明该代码包括什么、目的是什么、能做什么、为什么使用它等。

    注释是否需要详尽,取决于项目的复杂程度。

    一般单行注释:

    <!-- col -->

    模块间注释:

    <!-- news -->
    <div class="news">
      <h2>News</h2>
      <p>...</p>
    </div>
    <!--/ news -->

    循环注释:

    <ul>
      <!-- loop: new list -->
      <li>new's title 1</li>
      <li>new's title 2</li>
      <li>new's title 3</li>
      <li>new's title 4</li>
      <li>new's title 5</li>
      <!-- /loop: new list -->
    </ul>

    cms输出注释:

    <!-- cms: news list -->
    <ul>
      <li>new's title 1</li>
      <li>new's title 2</li>
      <li>new's title 3</li>
      <li>new's title 4</li>
      <li>new's title 5</li>
    </ul>
    <!-- /cms: news list -->

    Tab选项卡内容注释:

    <!-- tab: news list -->
    <div class="tab"></div>
    <!-- /tab: news list -->

    常规HTML设计规则

    文档类型

    使用html5文档声明,不再使用XHTML(application/xhtml+xml)。

    HTML5是目前所有HTML文档类型中的首选:

    <!DOCTYPE html>

    HTML 的正确性

    编写有效、正确的HTML代码,否则很难达到性能上的提升。

    可以使用一些工具验证你的代码,如 W3C HTML validator

    HTML 的语义性

    根据HTML各个元素的用途而去使用它们。

    <!-- 不推荐 -->
    <div class="col">
      <div class="title">
    news</div>
      <p>list1</p>
      <p>list2</p>
      <p>list3</p>
    </div>
    <!-- 推荐 -->
    <div class="col">
      <h2 class="title">
    news</h2>
      <p>list1</p>
      <p>list2</p>
      <p>list3</p>
    </div>

    部分标签说明:

    • div 主要用于布局,分割页面的结构;
    • ul/ol 主要用于无序/有序列表;
    • dl/dt/dd 当页面中出现第一行为类似标题/简述,然后下面为详细描述的内容时应该使用该标签;
    • span 没有特殊的意义,可以用作排版的辅助,然后在css中定义span;
    • h1-h6 标题, 根据重要性依次递减;
    • h1 最重要的标题;
    • label 使表单更有亲和力而且能辅助表单排版;

    不推荐使用的标签:

    • font 文字的外观,大小和颜色;
    • u 文本下划线;
    • center 居中对齐;
    • s 删除线;
    • strike 删除线;
    • noframes 无视框时的内容;
    • iframe 定义嵌入视图;
    • isindex 不建议使用(可搜寻,使用input代替);
    • dir 目录式列举;
    • menu 菜单列表;
    • basefont 定义基本字体;
    • applet 定义java程序;
    • frame 定义个别视框;
    • frameset 视框格式总定义;

    多媒体元素降级处理

    给多媒体元素,比如canvas、videos、 images增加alt属性,提高可用性(特别是常用的img标签,尽可量得加上alt属性,提供图片的描述信息)。

    <!-- 不推荐 -->
    <img src="world.jpg">
    <!-- 推荐 -->
    <img src="world.jpg"
    alt="our world images">

    type属性

    在样式表和脚本的标签中忽略type属性。

    HTML5默认type为text/css和text/javascript类型,所以没必要指定。即便是老浏览器也是支持的。

    <!-- 不推荐 -->
    <link rel="stylesheet"
     href="//www.google.com/css/maia.css"
     type="text/css">
    <script src="
     //www.google.com/
     js/gweb/analytics/autotrack.js"
     type="text/javascript">
     </script>
    <!-- 推荐 -->
    <link rel="stylesheet"
     href="//www.google.com/css/maia.css">
    <script src="
     //www.google.com/
     js/gweb/analytics/autotrack.js">
     </script>

    HTML代码格式规则

    每个块元素、列表元素或表格元素都独占一行,每个子元素都相对于父元素进行缩进。按设计稿划分模块,尽量使页面模块化,模块与模块之前要有清晰的注释。

    如上面页面框架,推荐写法:

    <!-- hader -->
    <div class="header">header</div>
    <!-- /hader -->
    <!-- nav -->
    <div class="nav">nav</div>
    <!-- /nav -->
    <!-- main -->
    <div class="main">
      <!-- container -->
      <div class="container">
        <!--news-->
        <div class="news">
          <h2>news<h2>
          <p>...</p>
        </div>
        <!--news-->
      </div>
      <!--/container-->
      <!--sidebar-->
      <div class="sidebar">
    sidebar</div>
      <!--sidebar-->
    </div>
    <!--/main-->
    <!--footer-->
    <div class="footer">
    footer</div>
    <!--/footer-->

    HTML与SEO

    页面良好层次

    保证整个页面在未加载样式表时仍有较好的层次清晰的页面结构。

    <!-- 不推荐 -->
    <div class="logo">My Site</div>
    <div class="nav">
      <a href="#">Home</a>
      <a href="#">News</a>
      <a href="#">Mobile</a>
    </div>
    <div class="news">
      <div>News</div>
      <a href="#">
    news list 1</a>
      <a href="#">
    news list 2</a>
      <a href="#">
    news list 3</a>
    </div>
    <!-- 推荐 -->
    <h1 class="logo">My Site</h1>
    <ul class="nav">
      <li><a href="#">
    Home</a></li>
      <li><a href="#">
    News</a></li>
      <li><a href="#">
    Mobile</a></li>
    </ul>
    <div class="news">
      <h2>News</h2>
      <ul>
        <li><a href="#">
    news list 1</a>
    </li>
        <li><a href="#">
    news list 2</a>
    </li>
        <li><a href="#">
    news list 3</a>
    </li>
      </ul>
    </div>

    权重标签使用

    H标签使用

    • h1 权重高,体现当前网页中相对比较重要的信息,但不宜过多,建议一个页面只放一个;
    • h2 可以做副标题;
    • h3 可以做新闻列表;
    • h4-h6 可做相关新闻的列表标签属性完整;

    strong、b使用

    将需要加粗的文字使用b标签来显示。

    将需要强调的文字(主要指包含关键词的信息)使用strong标签来强调主要内容。

    注:b是粗体标签,属于实体标签,它所包围的字符将被设为bold(粗体);strong 是加重语气标签,属于逻辑标签,它的作用是加强字符语气。

    标签属性使用

    在很多情况下,a都要使用title来说明该链接的相关说明或目的意义。

    例如:当使用overflow隐藏掉a中的溢出文字时,该a中的title是必不可少的,它可以告诉用户被隐藏掉的文字内容是什么;又或者当一个图片型链接出现时,该a中的title同样是必不可少的,它可以告诉用户这个图片链接是做什么用的。

    注:仅在img里添加alt标签在火狐提示文字是出不来的,alt是图片加载失败或未加载完全时显示出来的提示文字,要想鼠标移上去显示提示信息应该用title,严谨的写法是img里加入alt和title这两个标签。

    精简代码

    代码保持精简,最优化,这样搜索引擎才更喜欢。