字符串在编程过程中必不可少,程序中不同模块的交互也少不了传递字符串。
有时候,我们可能有这样的需求:字符串中某个子字符串是个特殊的标记,在传输过程中会对程序造成干扰,必须屏蔽它。最常见的例子:发起GET请求时,URL上的参数中如果有&符号,可能会导致参数列表被截断,最终导致传参失败。
遇到这种情况,我们首先能想到的是把参数加密,然后传输,最终处理的时候再解密,这样就巧妙的转换了特殊标记的表现形式,貌似可以解决问题。
但是,你不能保证加密算法本身不会产生特殊标记,也就是说,万一加密后的字符串中又出现了特殊标记怎么办?
因此,你不得不仔细筛选加密算法,确保不会冲突。但这种做法并不通用,如果特殊标记有变,你又要换算法了。
今天小菜分享给大家一个字符串屏蔽算法,通过该算法,可以对字符串进行编码,进而屏蔽掉特殊标记。
举例说明:
原始字符串: %&%1@4&af&&d%a&&%&45%&%&
屏蔽&符号编码(escape("%&%1@4&af&&d%a&&%&45%&%&","&")): 10%1%4%2%0%3%0%1%3%1%0%%%1@4afd%a%45%%
屏蔽&符号解码(unescape("10%1%4%2%0%3%0%1%3%1%0%%%1@4afd%a%45%%","&")): %&%1@4&af&&d%a&&%&45%&%&
算法代码:
1 /**
2 * 字符串特殊片段编码
3 * @author 杨元
4 *
5 */
6 public class ReplaceExt {
7
8 private static final String SPLIT_MARK="%";
9
10 /**
11 * 编码
12 * @param expression 要编码的原始字符串
13 * @param find 要编码的字符串片段,该参数为正则表达式,注意转义
14 * @return 如果出现异常,返回空字符串
15 */
16 public static String escape(String expression,String find){
17
18 String result = "";
19 StringBuilder newExpression = new StringBuilder(64);
20 String[] expressionArray;
21
22 try {
23 //按照指定字符串分割原始字符串
24 expressionArray = expression.split(find,-1);
25 //记录总分段数
26 newExpression.append(expressionArray.length);
27 newExpression.append(SPLIT_MARK);
28 //记录每段的长度
29 for(String s : expressionArray){
30 newExpression.append(s.length());
31 newExpression.append(SPLIT_MARK);
32 }
33 //记录每段的具体数据
34 for(String s : expressionArray){
35 newExpression.append(s);
36 }
37
38 result = newExpression.toString();
39
40 } catch (Exception e) {
41 result = "";
42 }
43
44 return result;
45 }
46
47 /**
48 * 解码
49 * @param expression 要解码的编码字符串
50 * @param find 要还原的字符串片段
51 * @return 如果出现异常,返回原字符串
52 */
53 public static String unescape(String expression,String find){
54
55 String result = "";
56 String[] expressionArray;
57 StringBuilder oldExpression = new StringBuilder(64);
58 String oldStr = "";
59 StringBuilder newExpression = new StringBuilder(64);
60 int allParts;
61 int start = 0;
62 int length = 0;
63
64 try {
65 //用SPLIT_MARK分割已经编码的字符串
66 expressionArray = expression.split(SPLIT_MARK,-1);
67 //第一部分为总段数
68 allParts = Integer.valueOf(expressionArray[0]);
69 //构造原字符串
70 for(int i=allParts+1;i<expressionArray.length;i++){
71 oldExpression.append(expressionArray[i]);
72 oldExpression.append(SPLIT_MARK);
73 }
74 oldStr = oldExpression.substring(0, oldExpression.length()-SPLIT_MARK.length());
75 //循环获取每一段
76 for(int i=1;i<=allParts;i++){
77 length = Integer.valueOf(expressionArray[i]);
78 newExpression.append(oldStr.substring(start,start+length));
79 newExpression.append(find);
80 start += length;
81 }
82 //去掉多余部分
83 result = newExpression.substring(0,newExpression.length()-find.length());
84
85 } catch (Exception e) {
86 result = expression;
87 }
88
89 return result;
90 }
91
92 public static void main(String[] args){
93 String testStr = "%&%1@4&af&&d%a&&%&45%&%&";
94 System.out.println(escape(testStr, "&"));
95 System.out.println(unescape(escape(testStr, "&"), "&"));
96 }
97 }
算法思路:
既然要屏蔽字符串,就直接把要屏蔽的字符串从原始字符串中消除,为了能还原,必须记住消除的位置,因此要在原始字符串前加一个数据段,来记录消除位置信息。
数据段以任意字符分割,小菜默认选用的%(读者可自行更换),第一部分是消除的总个数,其它部分是消除的位置。之所以记录消除总个数,是为了方便确定数据段边界。不能用某个特殊标记作为边界,因为你无法保证原始字符串中不出现这个特殊标记。
算法特点:
·安全稳定
·灵活易用
·编码短小精悍
·支持多重编码
本算法仅仅是一个编码算法,用来屏蔽掉特殊标记,并不能起到加密的作用。
希望这个小算法能给大家带来帮助,不当之处欢迎与我交流。