您的位置:首页 > 其它

网址的url编码解码讲解

2018-01-04 17:39 211 查看

问题

这是某个网站url的编码,也就是网址所显示的字符。

%E8%AF%84%E8%AE%BA%E7%AE%A1%E7%90%86


原来的内容是

评论管理




原理说明

这实际上是url的字符进行encode编码操作,想知道原来的内容是什么则将其decode解码即可。

评论管理
进行encode编码操作变成
%E8%AF%84%E8%AE%BA%E7%AE%A1%E7%90%86


%E8%AF%84%E8%AE%BA%E7%AE%A1%E7%90%86
进行decode解码即可得到
评论管理


API说明

JAVA的url编码解码API说明

URLEncoder.encode(input,”utf-8”):将字符串input使用utf-8编码方式进行url编码。

URLDecoder.decode(output,”utf-8”):将字符串output使用utf-8进行url解码

API使用代码

String input = "评论管理 abcefg";
String output = URLEncoder.encode(input,"utf-8");
String restore = URLDecoder.decode(output,"utf-8");
System.out.println(output);
System.out.println(restore);


执行结果:

%E8%AF%84%E8%AE%BA%E7%AE%A1%E7%90%86+abcefg

评论管理 abcefg


Java实现原理说明

这里以URLEncoder.encode进行讲解,URLEncoder.encode方法里使用了BitSet类。

encode方法内首先对Bitset类进行初始化,将大小写字母(a~z,A~Z)、数字(0~9)、空格( )、下划线(_)、中划线(-)、点(.)、星号(*)通过Bitset的set方法加入到符号集中。

执行encode方法时,对输入的字符串s进行遍历,如果s[i]在字符集里,空格转化为+,其余的保持不变,然后加到out数组;

若s[i]不在字符集内,则把连续不在字符集的字符拼接起来,获取其字节数组,然后通过Character.forDigit((ba[j] >> 4) & 0xF, 16)进行编码,最后拼接到out数组,详细内容可以查看下面的代码讲解。

部分代码和讲解

encode方法中BitSet初始化的代码

static BitSet dontNeedEncoding;
static {
dontNeedEncoding = new BitSet(256);
int i;
for (i = 'a'; i <= 'z'; i++) {
dontNeedEncoding.set(i);
}
for (i = 'A'; i <= 'Z'; i++) {
dontNeedEncoding.set(i);
}
for (i = '0'; i <= '9'; i++) {
dontNeedEncoding.set(i);
}
dontNeedEncoding.set(' '); /* encoding a space to a + is done
* in the encode() method */
dontNeedEncoding.set('-');
dontNeedEncoding.set('_');
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');

dfltEncName = AccessController.doPrivileged(
new GetPropertyAction("file.encoding")
);
}


encode方法讲解

// 输入s , 编码enc
public static String encode(String s, String enc)
throws UnsupportedEncodingException {

// 标记是否需要转化
boolean needToChange = false;
// 将需要编码的字符串缓冲到StringBuffer
StringBuffer out = new StringBuffer(s.length());
Charset charset;
CharArrayWriter charArrayWriter = new CharArrayWriter();

// 抛出编码为空的异常
if (enc == null)
throw new NullPointerException("charsetName");

try {
// 设置编码
charset = Charset.forName(enc);
} catch (IllegalCharsetNameException e) {
throw new UnsupportedEncodingException(enc);
} catch (UnsupportedCharsetException e) {
throw new UnsupportedEncodingException(enc);
}

for (int i = 0; i < s.length();) {
int c = (int) s.charAt(i);
// 是否在设置的字符集里面
if (dontNeedEncoding.get(c)) {
// 空格设置为+,其他的不变
if (c == ' ') {
c = '+';
needToChange = true;
}
out.append((char)c);
i++;
} else {
// 当出现不在字符集里的字符,开始遍历,将不在字符集里的字符加到charArrayWriter,直到出现在字符里的字符时停止遍历
do {
charArrayWriter.write(c);

if (c >= 0xD800 && c <= 0xDBFF) {
if ( (i+1) < s.length()) {
int d = (int) s.charAt(i+1);
// utf-16的高位区
if (d >= 0xDC00 && d <= 0xDFFF) {

charArrayWriter.write(d);
i++;
}
}
}
i++;
} while (i < s.length() && !dontNeedEncoding.get((c = (int) s.charAt(i))));
// 清空charArrayWriter的内容
charArrayWriter.flush();
String str = new String(charArrayWriter.toCharArray());
// 获取字节数组
byte[] ba = str.getBytes(charset);
// 遍历数组,将编码后的字符加到out中,其中caseDiff是大小写字符的距离('a' - 'A')
for (int j = 0; j < ba.length; j++) {
out.append('%');
char ch = Character.forDigit((ba[j] >> 4) & 0xF, 16);
// converting to use uppercase letter as part of
// the hex value if ch is a letter.
if (Character.isLetter(ch)) {
ch -= caseDiff;
}
out.append(ch);
ch = Character.forDigit(ba[j] & 0xF, 16);
if (Character.isLetter(ch)) {
ch -= caseDiff;
}
out.append(ch);
}
charArrayWriter.reset();
needToChange = true;
}
}
// 如果转化过,则输出out,否则输出原来的字符串即可
return (needToChange? out.toString() : s);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  url编码