2016-12-27
对字符编码时的规则

通常如果一样东西需要编码,说明这样东西并不适合传输。原因多种多样,如Size过大,包含隐私数据。
对于Url来说,之所以要进行编码,一个是因为Url中有些字符会引起歧义。 
例如Url参数字符串中使用key=value键值对这样的形式来传参,键值对之间以&符号分隔,如/s?q=abc&ie=utf-8。如果你的value字符串中包含了=或者&,那么势必会造成接收Url的服务器解析错误,因此必须将引起歧义的&和=符号进行转义,也就是对其进行编码。
另外,Url的编码格式采用的是ASCII码,而不是Unicode(包含中文),这也就是说你不能在Url中包含任何非ASCII字符,例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下,中文可能会造成问题。

编码时的规则:
  • 【字母】字符 "a" 到 "z"、"A" 到 "Z" 和【数字】字符 "0" 到 "9" 保持不变
  • 特殊字符【.】【-】【*】【_】保持不变
  • 空格字符 【 】转换为一个加号【+】
  • 所有其他字符都是不安全的,因此首先使用一些编码机制将它们转换为【一个或多个】字节,然后每个字节用一个包含 3 个字符的字符串【%xy】表示,其中 xy 为该字节的两位十六进制表示形式。
  • 可以指定对这些字符进行解码的编码机制,或者如果未指定的话,则使用平台的默认编码机制。

例如,使用 UTF-8 编码机制,字符串【ü@】将转换为【%C3%BC%40】,因为在 UTF-8 中,字符【ü】编码为两个字节【0xC3和0xBC】,字符【@】编码为一个字节【0x40】。
 

解码时的规则:
  • 将把【%xy】格式的子序列视为【一个字节】,其中 xy 为 8 位的两位十六进制表示形式。
  • 然后,所有连续包含一个或多个这些字节序列的子字符串,将被其编码可生成这些连续字节的字符所代替。
     
测试代码

public class Test {
    public static void main(String[] args) throws Exception {
        String enc = "UTF-8";
        test("aA0 .-*_", enc);//编码【aA0+.-*_】解码【aA0 .-*_】
        test("@", enc);//编码【%40】解码【@】
        test("ü", enc);//编码【%C3%BC】解码【ü】
        test("白", enc);//编码【%E7%99%BD】解码【白】
        test("白", "GBK");//编码【%B0%D7】解码【白】
    }
    /**
     * 测试编解码
     * @param str    原始字符串
     * @param enc    对字符串进行URLEncoder和URLDecoder时使用的编码规则
     * @throws UnsupportedEncodingException
     */
    public static void test(String str, String enc) throws UnsupportedEncodingException {
        String encode = URLEncoder.encode(str, enc);//推荐 UTF-8。如果未指定,则使用平台的默认编码
        String decode = URLDecoder.decode(encode, enc);//编码和解码必须使用同一套码表,否则解码时可能乱码
        System.out.println("原始字符串【" + str + "】编码后【" + encode + "】解码后【" + decode + "】");
        //获取通过UTF8码表编码的字符串的字节数组
        byte[] bytes = str.getBytes(enc);
        System.out.println("        原始字符串对应的字节数组" + Arrays.toString(bytes));
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            //手动对【每个字节】都进行上面【类似URLEncoder】编码规则的算法进行编码(即使字母和数字也进行了编码)
            sb.append(Integer.toHexString(b & 0xFF).toUpperCase() + " ");
        }
        System.out.println("        对每个字节都进行编码【" + sb.toString().trim() + "】");
    }

    //源码
    public static String decode(String s, String enc) throws UnsupportedEncodingException {
        boolean needToChange = false;
        int numChars = s.length();//字符数
        StringBuffer sb = new StringBuffer(numChars > 500 ? numChars / 2 : numChars);
        int i = 0;
        if (enc.length() == 0) throw new UnsupportedEncodingException("URLDecoder: empty string enc parameter");
        char c;
        byte[] bytes = null;
        while (i < numChars) {
            c = s.charAt(i);//逐个遍历所有字符
            switch (c) {
            case '+':
                sb.append(' ');
                i++;
                needToChange = true;
                break;
            case '%':
                try {
                    if (bytes == null) bytes = new byte[(numChars - i) / 3];// (numChars-i)/3 is an upper bound上线 for the number of remaining剩下的 bytes
                    int pos = 0;
                    while (((i + 2) < numChars) && (c == '%')) {
                        int v = Integer.parseInt(s.substring(i + 1, i + 3), 16);//16进制
                        if (v < 0) throw new IllegalArgumentException("URLDecoder: Illegal hex characters in escape (%) pattern - negative value");
                        bytes[pos++] = (byte) v;
                        i += 3;
                        if (i < numChars) c = s.charAt(i);
                    }
                    // A trailing, incomplete不完全的 byte encoding such as "%x" will cause an exception to be thrown
                    if ((i < numChars) && (c == '%')) throw new IllegalArgumentException("URLDecoder: Incomplete trailing escape (%) pattern");
                    sb.append(new String(bytes, 0, pos, enc));
                } catch (NumberFormatException e) {
                    throw new IllegalArgumentException("URLDecoder: Illegal hex characters in escape (%) pattern - " + e.getMessage());
                }
                needToChange = true;
                break;
            default:
                sb.append(c);
                i++;
                break;
            }
        }
        return (needToChange ? sb.toString() : s);
    }
}

URL编码 URLEncoder 示例的更多相关文章

  1. 各种编码问题产生原因以及解决办法---------响应编码,请求编码,URL编码

     响应编码 产生原因以及解决办法: 示例: package cn.yzu; import java.io.IOException; import javax.servlet.ServletExcept ...

  2. PHP转换UTF-8和GB2312的URL编码(转)

    目前WEB的应用中, UTF-8编码和GB2312编码是并存在的,例如百度(baidu.com)和谷歌(google.com)的URL编码分别是GB2312编码和UTF-8编码.由于编码并存引起的乱码 ...

  3. Atitit.软件开发概念(11)--网络子系统--url编码 空格问题URLEncoder java js php

    Atitit.软件开发概念(11)--网络子系统--url编码 空格问题URLEncoder java js php 1. RFC2396标准 including HTML 4.01 section  ...

  4. Web开发须知:URL编码与解码

    通常如果一样东西需要编码,说明这样东西并不适合传输.原因多种多样,如Size过大,包含隐私数据,对于Url来说,之所以要进行编码,是因为Url中有些字符会引起歧义. 例如,Url参数字符串中使用key ...

  5. javaweb请求编码 url编码 响应编码 乱码问题 post编码 get请求编码 中文乱码问题 GET POST参数乱码问题 url乱码问题 get post请求乱码 字符编码

     乱码是一个经常出现的问题 请求中,参数传递的过程中也是经常出现乱码的问题 本文主要整理了请求乱码中的问题以及解决思路   先要理解一个概念前提: 编码就是把图形变成数值码所以说: 图形的字符  -- ...

  6. url 编码(percentcode 百分号编码)(转载)

    原文地址:http://www.cnblogs.com/leaven/archive/2012/07/12/2588746.html   http://www.imkevinyang.com/2009 ...

  7. 浏览器URL编码

    jsp页面中通过请求另一个页面并通过url传递了带有中文的参数,结果在接收端获取参数时乱码了 经检查乱码现象指出新在IE浏览器中,其他浏览器火狐.chrome等不会有问题 最后的解决方式是: 手动将此 ...

  8. 详解JavaScript中的Url编码/解码,表单提交中网址编码

    本文主要针对URI编解码的相关问题做了介绍,对Url编码中哪些字符需要编码.为什么需要编码做了详细的说明,并对比分析了Javascript 中和 编解码相关的几对函数escape / unescape ...

  9. url 编码(percentcode 百分号编码)

    http://www.imkevinyang.com/2009/08/%E8%AF%A6%E8%A7%A3javascript%E4%B8%AD%E7%9A%84url%E7%BC%96%E8%A7% ...

随机推荐

  1. 共享式以太网与交换式以太网的性能比较(OPNET网络仿真实验)

      一.实验目的 比较共享式以太网和交换式以太网在不同网络规模下的性能. 二.实验方法 使用opnet来创建和模拟网络拓扑,并运行分析其性能. 三.实验内容 3.1   实验设置(网络拓扑.参数设置. ...

  2. C#委托(Delegate)学习日记

    在.NET平台下,委托类型用来定义和响应应用程序中的回调.事实上,.NET委托类型是一个类型安全的对象,指向可以以后调用的其他方法.和传统的C++函数指针不同,.NET委托是内置支持多路广播和异步方法 ...

  3. iReport中求和的问题

    数据库取出值TAX_AMT,但是不想在数据库里面计算,太麻烦,后面group by 字段太多.那就放到ireport里面去计算咯 在字段的如下位置进行计算吧.

  4. SQL2000和SQL2005和SQL2008同时安装问题

    原文:SQL2000和SQL2005和SQL2008同时安装问题 SQL2000和SQL2005和SQL2008同时安装问题 1,因为SQL2000安装过程中无法修改实例名称,故安装过程中必须先安装S ...

  5. 利用WITH AS 优化FILTER

    SQL> explain plan for select * from fxqd_list_20131115_new where (acct_no, oper_no, seqno, trans_ ...

  6. bzoj1853 bzoj2393

    两题是类似的,这里说一下bzoj1853 首先我们求出所有的幸运号码,注意如果存在x是y的倍数则x不算在内,避免之后重复计算 下面我们就要统计幸运号码的倍数了,这显然是要用到容斥原理的 但是幸运号码很 ...

  7. c#后台验证

    #region 后台验证 panda /// 验证电话号码的主要代码如下: public bool IsTelephone(string str_telephone) { return System. ...

  8. HDU-1963

    http://acm.hdu.edu.cn/showproblem.php?pid=1963 完全背包. 题意:给出初始资金,还有年数,然后给出每个物品的购买价格与每年获得的利益,要求在给出的年份后所 ...

  9. 利用腾讯企业邮箱开放API获取账户未读邮件数初探

    公司一直使用腾讯提供的免费企业邮箱服务,今天用管理员帐户登录后发现,原来现在腾讯的企业邮箱也开放了部分API 你可以通过开放接口实现以下功能: 数据同步 数据同步可以帮助你同步部门成员信息,你还可以创 ...

  10. 关于OC头文件互相引用的问题

    在OC中头文件互相引用是很常见的一件事,如: A的头文件#import "B.h" 而B的头文件#import "A.h" 这个时候就会出现意想不到的问题.系统 ...