字符串屏蔽算法
字符串在编程过程中必不可少,程序中不同模块的交互也少不了传递字符串。
有时候,我们可能有这样的需求:字符串中某个子字符串是个特殊的标记,在传输过程中会对程序造成干扰,必须屏蔽它。最常见的例子:发起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 }
算法思路:
既然要屏蔽字符串,就直接把要屏蔽的字符串从原始字符串中消除,为了能还原,必须记住消除的位置,因此要在原始字符串前加一个数据段,来记录消除位置信息。
数据段以任意字符分割,小菜默认选用的%(读者可自行更换),第一部分是消除的总个数,其它部分是消除的位置。之所以记录消除总个数,是为了方便确定数据段边界。不能用某个特殊标记作为边界,因为你无法保证原始字符串中不出现这个特殊标记。
算法特点:
·安全稳定
·灵活易用
·编码短小精悍
·支持多重编码
本算法仅仅是一个编码算法,用来屏蔽掉特殊标记,并不能起到加密的作用。
希望这个小算法能给大家带来帮助,不当之处欢迎与我交流。