整合营销服务商

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

免费咨询热线:

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>

    网页测试


    TML 超文本标记语言(英语:HyperText Markup Language)是一种用于创建网页的标准标记语言。

    【注】对于中文网页需要使用 <meta charset="utf-8"> 声明编码,否则会出现乱码。

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <title>头条</title>
    </head>
    <body>
        <h1>标题1</h1>
        <p>段落1</p>
    </body>
    </html>
    //实例解析
    /**DOCTYPE 声明了文档类型
    位于标签 <html> 与 </html> 描述了文档类型
    位于标签 <body> 与 </body> 为可视化网页内容
    位于标签 <h1> 与 </h1> 作为一个标题使用
    位于标签 <p> 与 </p> 作为一个段落显示 **/

    html在浏览器显示内容区

    HTML 文本相关标签

    • h1-h6 文本标题, 特点: 独占一行, 自带上下间距, 字体加粗
    • p 段落标签, 特点: 独占一行,自带上下间距
    • hr 水平分割线
    • br 换行
    • b 加粗
    • i 斜体
    • u 下划线
    • s 删除线
    • sub 下标
    • sup 上标
    <!--特点: 字体加粗 独占一行 自带上下间距-->
    <h1 align="center">内容标题1</h1>
    <h2 align="right">内容标题2</h2>
    <h3>内容标题3</h3>
    <h4>内容标题4</h4>
    <h5>内容标题5</h5>
    <h6>内容<br>标题6</h6>
    <hr>
    <!--段落标签p 特点: 独占一行 自带上下间距-->
    <p>段落1</p>
    <p>段落2</p><p>段落3</p>
    加粗<b>标签</b>
    斜体<i>标签</i>
    下划线<u>标签</u>
    删除线<s>标签</s>
    <sub> 下标</sub> 
    <sup> 上标</sup>

    HTML 列表标签

    • 无序列表: ul和li 组合 unordered list list item 列表项
    • 有序列表: ol和li 组合 ordered list
    • 列表嵌套: 有序列表和无序列表可以任意无限嵌套 .
    <!--无序列表-->
    <ul>
        <li>貂蝉</li>
        <li>孙尚香</li>
        <li>孙悟空</li>
        <li>猪八戒</li>
        <li>刘禅</li>
    </ul>
    <!--无序、有序列表-->
    <ul>
        <li>凉菜
            <ol>
                <li>拍黄瓜</li>
                <li>凉皮</li>
            </ol>
        </li>
        <li>炒菜
            <ol>
                <li>宫保鸡丁</li>
                <li>辣椒小炒肉</li>
            </ol>
        </li>
    </ul>

    HTML图片标签

    • src: 资源路径

    1)相对路径: 访问站内资源

    图片和页面在同级目录: 直接写图片名

    图片在页面的上级目录: ../图片名

    图片在页面的下级目录: 文件夹名/图片名

    2)绝对路径: 访问站外资源, 图片盗链, 有找不到图片的风险

    • alt: 图片不能正常显示时显示的文本
    • title: 图片标题
    • width/height: 设置宽高 , 只设置宽度时高度会自动等比例缩放

    ①像素

    ②上级元素百分比

    <!--alt: 当图片不能正常显示时 显示的文本-->
    <!--title: 图片标题-->
    <img src="aa.jpg" alt="这是个美女图片">
    <img src="../b.jpg" title="这是标题" alt="">
    <!--width/height-->
    两种赋值方式: 1. 像素  2. 上级元素的百分比
    只设置宽度时 高度会自动等比例缩放-->
    <img src="abc/c.jpg" width="50" alt="">
    <img src="abc/c.jpg" width="50%" alt="">
    <img src="https://www.baidu.com/e47f5058f84a655.png" alt="">

    HTML超链接a

    • href: 资源路径, 作用类似图片标签的src
    • a标签包裹文本为文本超链接, 包裹图片为图片超链接
    • 页面内部跳转, 在目的地的元素里面添加id=xxx 然后在超链接里面添加href="#xxx"
    <!--超链接-->
    <a id="top" href="http://www.baidu.com">超链接1</a>
    <a href="day01.html">超链接2</a>
    <a href="a.jpg">超链接3</a>
    <a href="http://www.celinf.cn"><img src="a.jpg" width="100"></a>
    <a href="#top">回到顶部</a>

    HTML表格table

    • 相关标签: table tr表示行 td表示列 th表头 caption标题
    • 相关属性: border边框 colspan跨列 rowspan跨行
    <!--表格一 -->
    <table border="1">
        <tr>
            <td colspan="2">1-1</td><td rowspan="2">1-3</td>
        </tr>
        <tr>
            <td rowspan="2">2-1</td><td>2-2</td>
        </tr>
        <tr>
            <td colspan="2">3-2</td>
        </tr>
    </table>
    <!--表格二 -->
    <table border="1">
        <caption>购物车</caption>
        <tr>
            <th>编号</th><th>商品名</th><th>价格</th>
        </tr>
        <tr>
            <td>1</td><td>小米12 pro</td><td>5000</td>
        </tr>
        <tr>
            <td>2</td><td>华为电视</td><td>4000</td>
        </tr>
        <tr>
            <td>总价:</td><td colspan="2">9000元</td>
        </tr>
    </table>

    HTML表单form

    • 作用: 获取用户输入的各种信息 并提交给服务器
    • 学习form表单主要学习的就是下面这些控件
    <form action="http://www.baidu.com" method="get">
        <!--maxlength最大字符长度  value设置默认值  readonly只读-->
       用户名:<input type="text" name="username" maxlength="5" value="abc" readonly ><br>
        密码:<input type="password" name="password"><br>
        <!--value是单选框必须添加的属性 否则提交on  checked默认选中-->
        性别:<input type="radio" name="gender" value="m" id="r1">
        <label for="r1">男</label>
        <input type="radio" name="gender" checked value="w">女<br>
         <!--多选框--> 
        兴趣爱好:<input type="checkbox" name="hobby" value="cy">成员
        <input type="checkbox" name="hobby" checked value="hj">环境
        <input type="checkbox" name="hobby" value="tt">团体<br>
         <!--日期--> 
        生日:<input type="date" name="birthday"><br>
        <!--文件-->     
        文件:<input type="file" name="pic"><br>
        所在地:
        <!--value设置提交的内容    selected默认选中-->
        <select name="city">
            <option value="bj">北京</option>
            <option value="sh">上海</option>
            <option value="gz" selected>广州</option>
        </select><br>
        <input type="submit" value="注册">
    </form>

    HTML分区标签

    • 作用: 可以理解为是一个容器,将多个有相关性的标签进行统一管理
    • 块级分区标签div: 特点是独占一行
    • 行内分区标签span: 特点是共占一行
    • 页面区域如何划分? 至少分为三大区(头,体,脚) 每个大的区域再划分n个小的区域
    • HTML5的标准中新增了一些语义更强的分区标签,为了提高代码的可读性. 这几个标签的作用和div一样都是块级分区标签
    1. header
    2. footer
    3. main主体
    4. section区域
    5. nav 导航

    CSS 层叠样式表Cascading Style Sheet)

    作用: 美化页面(好比装修)

    如何在HTML页面中添加CSS样式代码三种引入方式:

    • 内联样式: 在标签的style属性中添加样式代码, 弊端:不能复用
    • 内部样式: 在head标签里面添加一个style标签, 在标签体内写样式代码, 可以实现复用但是只能在本页面复用
    • 外部样式: 在单独的css样式文件中写样式代码, 在html页面中通过link标签引入, 可以实现多页面复用, 可以将html代码和css样式代码分离
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    		<!--内部样式-->
        <style>
           h2{color: blue}
        </style>
        <!--引入外部的css样式文件-->
        <link rel="stylesheet" href="my.css">
    </head>
    <body>
    <h1 style="color: red">内联样式1</h1>
    <h1 style="color: red">内联样式2</h1>
    <h2>内部样式1</h2>
    <h2>内部样式2</h2>
    <h3>外部样式1</h3>
    <h3>外部样式2</h3>

    选择器

    1. 标签名选择器: 选取页面中所有同名标签 格式: 标签名{样式代码}
    2. id选择器: 当需要选择页面中某一个元素时使用 格式: #id{样式代码}
    3. 类选择器: 当需要选择多个不相关的元素时,给多个元素添加相同的class属性,然后通过类选择器进行选择 格式: .class{样式代码}
    4. 分组选择器: 分组选择器可以将多个选择器合并成一个 h4,#id,.class{样式代码}
    5. 属性选择器: 通过元素的属性选择元素 格式: 标签名[属性名="属性值"]{样式代码}
    6. 任意元素选择器: 选择页面中所有标签 格式: *{样式代码}
    <head>   
    	<meta charset="UTF-8">
        <title>Title</title>
        <style>
            /*id选择器*/
            #p1{color: red}
            /*类选择器*/
            .c1{color: yellow}
            /*分组选择器*/
            h4,#p1,.c1{background-color: blue}
            /*属性选择器*/
            input[type="text"]{color: red}
            /*任意元素选择器*/
            /*边框: 粗细 样式 颜色*/
            *{border: 1px solid purple}
        </style>
    </head>
    <body>
    <input type="text">
    <input type="password">
    <p id="p1">苹果</p>
    <p class="c1">香蕉</p>
    <p>橘子</p>
    <h3>冰箱</h3>
    <h3 class="c1">洗衣机</h3>
    <h3>电视机</h3>
    <h4>张三</h4>

    Idea快捷键

    • Alt+Insert 生成代码(如get,set方法,构造函数等) 或者右键(Generate)
    • fori/sout/psvm + Tab 【Tab快捷,下:】
    1. iter 快速生成 for…in 语句
    2. inst 快速生成”if instanceof ”语句
    3. itco 快速生成 iterator 的 for 循环
    4. itit 快速生成 iterator 的 while 循环
    5. itli 快速生成 list 的 for(i)循环
    6. psf 快速生成“public static final” 语句
    7. thr 快速生成“throw new” 语句
    • CTRL+ALT+T 把选中的代码放在 TRY{} IF{} ELSE{} 里
    • ALT+/ 代码提示
    • Ctrl+X 删除行
    • Ctrl+D 复制行
    • Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/…/ )
    • Alt+F1 查找代码所在位置
    • CTRL+Z 倒退(撤销)
    • ALT+F1 查找文件所在目录位置
    • Alt+Shift+F9,选择 Debug
    • Alt+Shift+F10,选择 Run
    • Alt+F9,运行至断点处
    • Alt+F10,定位到断点
    • Shift+F6,重命名
    • Alt+F12 打开命令终端
    • Shift+Shift 搜索文件

    学习记录,如有侵权请联系删除。