[ 工具 ] 在Web中的常见的用于参数处理的方法以及在Java中的使用(持续更新)

一、URL编码

该编码一般用于Content-Type:application/x-www-form-urlencoded的数据,如果前端传到后端的是编码后的一段数据,我们就需要进行解码,URL编码和解码可以使用Java api中的URLEncoderURLDecoder(很多Java Api都使用Charset替代String已传递编码参数了,但是URLEncoder和URLDecoder并无变化,虽然影响不大)。

/*
URL编码的使用
 */
String encodedText = "%e4%bd%a0%e7%9c%9f%e5%b8%85";
String decodedText = "你真帅";
System.out.println(URLDecoder.decode(encodedText, StandardCharsets.UTF_8.name()));
System.out.println(URLEncoder.encode(decodedText, StandardCharsets.UTF_8.name()));

学会了如何使用,接下来我们就应该理解一下编码规则:

1、获取相应编码表示下的字节流

2、把每一字节转化成十六进制表示并在前面加一个’%’;

下面是参照URLEncoder转换部分得到的演示代码:

/*
  测试URL编码的规则
 */
byte[] bytes = decodedText.getBytes(StandardCharsets.UTF_8);
for (byte aByte : bytes) {
    System.out.print("%");
	System.out.print(Character.forDigit(aByte >> 4 & 0xF, 16));
	System.out.print(Character.forDigit(aByte & 0x0F, 16));
}

这里需要注意aByte >> 4 & 0xF,如果单单使用aByte >> 4就会出现符号问题,当aByte为负数时,最高位会使用符号位填充,Charater.forDigit(int digit, int radix)是获取0~radix范围内的radix进制表示,负数当然就表示不了了,返回\u0000,也就是字符’\0’。

URLEncoder#encode方法还需要考虑下面两种情况:
1、空格。把空格替换成字符’+’
2、unicode编码的代理码点:高代理(\uD800-\uDBFF)和低代理(\uDC00-\uDFFF)。因为有些代理对是还未被标准定义的, 目前Java对这些非法代理的处理方法是将高代理和低代理各自视为一个字符。

其实第二个情况不考虑也是可以的,因为对于非法代理对,我们上面代码是可以正常工作的,但是产生的编码和URLEncoder#encode的不一样,但是解码结果还是一致的,我们了解到这种情况也算是开拓了我们思路了。

二、Base64

三、Unicode

我在分析活动CF活动请求时,经常会碰到形如"\u975e\u5e38\u62b1\u6b49\uff0c\u60a8\u8fd8\u4e0d\u6ee1\u8db3\u53c2\u52a0\u8be5\u6d3b\u52a8\u7684\u6761\u4ef6\uff01"的响应形式,这是字符串的Unicode表示,我们可以通过简单的转换算法把它转换成对应的字符串。

在此之前我们先了解一下Unicode是怎么表示字符的。

unicode的码点(码点就是对应的int数值,类似ASCII码)范围从0x000000 - 0x10FFFF,char的范围只能是在0x0000到0xFFFF,也就是标准的 2 字节形式通常称作UCS-2,所以在Java中char类型就是双字节的,但unicode码大于0x10000的部分如何用char表示呢?比如😀,想要表示😀这个表情,我们需要引出Java Unicode编码中的高低代理表示方法,Unicode为了表示更多的字符,保留了0xD800 - 0xDFFF范围内的码点,0xD800 - 0xDBFF为高代理码点,0xDC00 - 0xDFFF为低代理码点。高低代理的的码点随机组合用于表示unicode码点大于0x10000范围的字符,所以😀的表示为\uD83D\uDE00,用char数组表示就是char[] arr = {0xD83D,0xDE00}

我们知道了Unicode的表示规则:就是把\u后面的十六进制翻译成int类型,然后一一放进char数组中。

public static String decodeUnicodeString(String text){
	StringBuilder builder = new StringBuilder(text.length());
	for (int i = 0; i < text.length();){
		char ch = text.charAt(i);

		if (ch == '\\'){
			if (i + 1 < text.length() && text.charAt(i + 1) == 'u'){
				/*
				  获取后面4个十六进制字符
				 */
				char[] unicode = new char[4];
				int j = 0, index = i + 2;
				for (; j < 4 && index < text.length(); ++j, ++index){
					unicode[j] = text.charAt(index);
				}
				/*
				转换成int类型
				 */
				if (j == 4){
					int codepoint = Integer.parseInt(new String(unicode), 16);
					builder.append((char)codepoint);
					i = index;
					continue;
				}
			}
		}
		builder.append(ch);
		++i;
	}
	return builder.toString();
}

这代码还是很有工具价值的,因为遇到的需要进行转换的情况还是挺多的。

四、Md5

五、随机字符串

这个可能有些情况下会有用,这也是一种思路。

private static String randomMask = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static String getRandomString(int length){
	if (length <= 0){
		throw new IllegalArgumentException("Length can not be zero or negative");
	}
	StringBuilder builder = new StringBuilder(length);
	for (int i = 0; i < length; ++i){
		int rIndex = (int) (62 * Math.random());
		builder.append(randomMask.charAt(rIndex));
	}
	return builder.toString();
}

六、时间戳和格式化时间互转【需要学习Java新的时间API】

七、Hex–字节数组转换成十六进制字符串

字节转换成十六进制可以使用Apache common codecHex工具类:

String str = "你是谁";
byte[] bytes = str.getBytes(StandardCharsets.UTF_8);
String hexString = Hex.encodeHexString(bytes);
byte[] decodedBytes0 = Hex.decodeHex(hexString);

也可以自己实现:

编码部分:

public static String toHexString(byte[] bytes){
	StringBuilder builder = new StringBuilder(bytes.length * 2);
	for (byte b : bytes){
		builder.append(Character.forDigit(b >> 4 & 0x0F, 16));
		builder.append(Character.forDigit(b & 0x0F, 16));
	}
	return builder.toString();
}

解码部分:

public static byte[] fromHexString(String hexString){
	if ((hexString.length() & 0x01) != 0){
		throw new IllegalArgumentException("The hex string is not valid");
	}

	byte[] bytes = new byte[hexString.length() / 2];

	for (int i = 0, j = 0; j < bytes.length; ++j){
		byte b = 0;
		int hb = Character.digit(hexString.charAt(i++), 16);
		int lb = Character.digit(hexString.charAt(i++), 16);
		b |= hb << 4;
		b |= lb;
		bytes[j] = b;
	}

	return bytes;
}

注意,获取值对应的十六进制表示时不要直接对byte用Integer#toHexString,因为Integer#toHexString会省略高位为0的情况’0’,比如0x01会输出0x1,这不是我们想要的结果。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页