这与 Nathan Hughes 的解决方案相比并没有太大的改进,但字符串越长,您获得的节省就越多。
编码:创建一个以“1”开头的String,使源字符串中的每个数字为2位,因此“0”变为“00”,“5”变为“05”,“99”变为“99”等。以 36 为基数表示结果数。
解码:取base 36的数字/字符串,改回base 10,跳过第一个“1”,然后将每2个数字/字母转成一个int,重建原始字符串。
示例代码:
String s = "1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,3,0,4,0,0,0,4,0,3";
// ENCODE the string
StringTokenizer tokenizer = new StringTokenizer(s,",");
StringBuilder b = new StringBuilder();
b.append("1"); // This is a primer character, in case we end up with a bunch of zeroes at the beginning
while(tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken().trim();
if(token.length()==1) {
b.append("0");
b.append(token);
}
else {
b.append(token);
}
}
System.out.println(b);
// We get this String: 101020000000000000000000000000000000000010202030004000000040003
String encoded = (new BigInteger(b.toString())).toString(36);
System.out.println(encoded);
// We get this String: kcocwisb8v46v8lbqjw0n3oaad49dkfdbc5zl9vn
// DECODE the string
String decoded = (new BigInteger(encoded, 36)).toString();
System.out.println(decoded);
// We should get this String: 101020000000000000000000000000000000000010202030004000000040003
StringBuilder p = new StringBuilder();
int index = 1; // we skip the first "1", it was our primer
while(index<decoded.length()) {
if(index>1) {
p.append(",");
}
p.append(Integer.parseInt(decoded.substring(index,index+2)));
index = index+2;
}
System.out.println(p);
// We should get this String: 1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,2,3,0,4,0,0,0,4,0,3
我不知道将大数转换为基数 64 的简单方法。精心选择的符号(如 +、、-)可以进行 URL 编码,因此 0-9、a-z、A-Z、带有“”和“-”的为 64。BigInteger.toString() 方法最多只占用 Character.MAX_RADIX,即 36(无大写字母)。如果你能想办法把一个大数改成base 64,那么得到的编码String会更短。
编辑:看起来这是为你做的:http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Base64.html