我有一个表示长的字符串。像"12345678901"
(11个字符长)。
我使用Long.parse()
将其转换为long,这很好。
现在,我希望将这个长字符串作为短字符串发送,例如"eR%s"
。
目标是让最后一个字符串尽可能短。知道最好的方法是什么?我可以使用更多字符作为URL编码(就像我可以使用/,%,:等)
答案 0 :(得分:1)
Java可以使用数字0 - 9和小写字母a - z处理高达36的基数。
> Long.toString(12345678901L, 36)
"5o6aqt1"
> Long.parseLong("5o6aqt1", 36)
12345678901
您可以使用66个未保留的URI字符中的65个来创建自己的编码(因此您的URI不需要转义)。 ' - '符号需要用于负数:
> Long65.toString(12345678901L)
"aFDIbA"
> Long65.parseLong65("aFDIbA")
12345678901
以下是Long65()
import java.math.BigInteger;
public class Long65 {
private static int base = 65;
private static String URIchars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_.~";
public static String toString(Long aNumber) {
StringBuilder result = new StringBuilder();
if (aNumber < 0) {
result.append('-');
aNumber = -aNumber;
}
int r = (int)(aNumber % base);
if (aNumber - r == 0)
result.append(URIchars.charAt(r));
else
result.append(Long65.toString((aNumber - r) / base) + URIchars.charAt(r));
return result.toString();
}
public static long parseLong65(String aNumber) {
char[] digits;
int sign = 1;
if (aNumber.charAt(0) == '-') {
sign = -1;
digits = aNumber.substring(1).toCharArray();
} else {
digits = aNumber.toCharArray();
}
BigInteger bigBase = BigInteger.valueOf(base);
BigInteger power = bigBase.pow(digits.length);
BigInteger total = BigInteger.valueOf(0);
for (char digit : digits){
power = power.divide(bigBase);
total = total.add(power.multiply(BigInteger.valueOf(URIchars.indexOf(digit))));
}
return sign * total.longValue();
}
}
答案 1 :(得分:0)
如果您想要更短的代表,请为您的号码使用不同的基数。
答案 2 :(得分:0)
您使用的数字基数越大,表示越小。您可以尝试使用base 16,例如:
Long.toString(num, 16)
这应返回最多16个字符的字符串。
如果它不够小,你可以在更大的基础上建立一个表示。但是,如果生成的字符串需要进行URL转义,则可能没用。例如,在256中,对于任何数字,8个字符就足够了,但256个字符中的许多字符需要被转义,从而使得结果文本更长。因此,如果您选择自己实施这样的编码/解码方案,则必须仔细选择字母。
以http://en.wikipedia.org/wiki/Base64为例。您可以使用this Java implementation。您可能也对Base85 and its implementations感兴趣。
答案 3 :(得分:0)
要回复评论Base64 vs其他选项,我会说,这完全取决于你对字符集的限制。我不是在谈论通过URL进行传输,而是通过需要是文本流的字符串流进行传输。我不能简单地发送一个字节数组,因为不可打印的字符可能会导致某些问题。
所以我构建了类似的东西(见下文),它在base92(几乎)中转换了很长的内容。它使用除了减号和管道之外的所有可打印字符,我用它来分隔符。
它几乎是Base65的剪切和过去,我只是动态地构建有效数字列表。可以重复使用任何基数或任何有效数字列表。
<!-- language: java -->
public class LongConverter {
private static String URIchars;
static {
StringBuilder result = new StringBuilder();
for (int i = 32; i < 255; i++) {
if ((i != 45) && (i != 124))
result.append((char)i);
}
URIchars = result.toString();
}
public static String toString(Long aNumber) {
int base = URIchars.length();
StringBuilder result = new StringBuilder();
if (aNumber < 0) {
result.append('-');
aNumber = -aNumber;
}
int r = (int) (aNumber % base);
if (aNumber - r == 0) result.append(URIchars.charAt(r));
else result.append(Long65.toString((aNumber - r) / base) + URIchars.charAt(r));
return result.toString();
}
public static long parseLong(String aNumber) {
int base = URIchars.length();
char[] digits;
int sign = 1;
if (aNumber.charAt(0) == '-') {
sign = -1;
digits = aNumber.substring(1).toCharArray();
} else {
digits = aNumber.toCharArray();
}
long total = 0;
long power = 1;
for (int i = 0; i < digits.length; i++)
power *= base;
for (char digit : digits) {
power /= base;
total += URIchars.indexOf(digit) * power;
}
return sign * total;
}
}