一、URL编码相关知识
一、URL编码相关知识
首先来看一个URL编码的例子程序:
public static void main(String[] args) throws Exception { String content = "中国"; //这里将字符串转换成字节数组后的形式原样打印 testPrintBytes(content); //d6d0b9fa System.out.println("================="); //这里打印URL编码后的字符串形式 System.out.println(URLEncoder.encode(content,"GBK")); //%D6%D0%B9%FA } public static void testPrintBytes(String strContents) { byte[] byteArray = strContents.getBytes(); for(int i=0; i<byteArray.length; i++) { printBytes(byteArray[i]); } System.out.println(); } //输出字节的内存原样八位十六进制形式 public static void printBytes(byte byteData) { if(byteData > 0) { System.out.print(Integer.toHexString(byteData)); }else { int temp = byteData & 255; System.out.print(Integer.toHexString(temp)); } }
从打印出的内容来看,URL编码是将“中国”等不能出现在URL地址中的字符,以某种编码的二进制形式
的每个字节前面加上“%”,并且将小写的字母编程大写的字母的过程。
不过从原理上来讲URL编码的过程还是比较复杂的,大致过程如下:
1、首先需要将字符串按照某种编码转换成字节数组的形式(这里我们指定的为GBK编码)
2、字节数组的原始内容为 d6d0b9fa
3、通过字节数组d6d0b9fa的内容,构造出URL编码字符串,
这里我们自己来模拟该过程真正的实现未必就是这样,首先定义一个StringBuffer类型的URLBuffer和一个字符数组 chars={0123456789ABCDEF} 我们将十六进制的d6转换成二进制形式为 1101 0110 ,先将该字节高四位转换为一个字节 0000 1101 该字节的数值为13,然后将URLBuffer.append("%") 后再URLBuffer.append(chars[13]),然后将低四位作为一个字节得到 0000 0110 该字节的数值为6,然后URLBuffer.append(chars[6)) 这样一来就得到了URL编码的 %D6 的字符串形式。
模拟过程代码如下:
public static void main(String[] args) throws Exception { StringBuffer URLBuffer = new StringBuffer(); char[] chars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; String content = "中国"; byte[] bytes = content.getBytes("GBK"); for(int i=0; i<bytes.length; i++) { printBytes(bytes[i]); } //输出 d6d0b9fa System.out.println(""); for(int i=0; i<bytes.length; i++) { byte left4Bit = (byte)((bytes[i] >>> 4) & 15); byte right4Bit = (byte)(bytes[i] & 15); System.out.print(left4Bit + " "); System.out.print(right4Bit + " "); URLBuffer.append("%"); URLBuffer.append(chars[left4Bit]); URLBuffer.append(chars[right4Bit]); } //输出 13 6 13 0 11 9 15 10 System.out.println(""); System.out.println(URLBuffer.toString()); //输出 %D6%D0%B9%FA } public static void printBytes(byte byteData) { if (byteData > 0) { System.out.print(Integer.toHexString(byteData)); } else { int temp = byteData & 255; System.out.print(Integer.toHexString(temp)); } }
URL编码的原则如下:
1、对于英文字母数字和*都是原样不进行编码的,例如:*,a,b,c,A,B,C, 0,1,2 等
2、URLEncoder.encode方法是按照HTML4.01的标准进行编码的。编码方式是根据ContextType的不同而区别对待的,在form的ContextType是[x-www-form-urlencoded]的时候会对form中的键/值对进行编码,空格被转义成+,其他字符按照[RFC1738]标准处理成%HH的形式。
加上了以上两条原则的模拟代码如下:
public static void main(String[] args) throws Exception { /* String content = "中国&%abc *"; //这里将字符串转换成字节数组后的形式原样打印 testPrintBytes(content); //d6d0b9fa System.out.println("================="); //这里打印URL编码后的字符串形式 System.out.println(URLEncoder.encode(content,"GBK")); //%D6%D0%B9%FA */ char a = 'a'; System.out.println((int)a); StringBuffer URLBuffer = new StringBuffer(); char[] chars = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; String content = "中国abc* &"; byte[] bytes = content.getBytes("GBK"); for(int i=0; i<bytes.length; i++) { printBytes(bytes[i]); } //输出 d6d0b9fa6162632a2026 System.out.println(""); for(int i=0; i<bytes.length; i++) { //这里实现字母数字和* 的原样输出 if((bytes[i] >= 97 && bytes[i] <= 122) || (bytes[i] >= 65 && bytes[i] <= 90) || (bytes[i] >= 48 && bytes[i] <= 57) || bytes[i] == 42 ) { char c = (char)bytes[i]; URLBuffer.append(c); System.out.print("-"); continue; } //这里实现将" " 转换成"+" if(bytes[i] == 32) { URLBuffer.append("+"); System.out.print("-"); continue; } byte left4Bit = (byte)((bytes[i] >>> 4) & 15); byte right4Bit = (byte)(bytes[i] & 15); System.out.print(left4Bit + " "); System.out.print(right4Bit + " "); URLBuffer.append("%"); URLBuffer.append(chars[left4Bit]); URLBuffer.append(chars[right4Bit]); } //输出 13 6 13 0 11 9 15 10 -----2 6 System.out.println(""); System.out.println(URLBuffer.toString()); //输出 %D6%D0%B9%FAabc*+%26 } public static void printBytes(byte byteData) { if (byteData > 0) { System.out.print(Integer.toHexString(byteData)); } else { int temp = byteData & 255; System.out.print(Integer.toHexString(temp)); } }