问题
Given an arbitrary set of letters
String range = "0123456789abcdefghijklmnopABCD#";
I am looking for 2 methods to encode/decode from long <-> String
String s = encode( range, l );
and
long l = decode( range, s );
So decode(range, encode(range, 123456789L)) == 123456789L
And if range is "0123456789" thats the usual way of encoding.
回答1:
The following code does what you need:
static long decode(String s, String symbols) {
final int B = symbols.length();
long num = 0;
for (char ch : s.toCharArray()) {
num *= B;
num += symbols.indexOf(ch);
}
return num;
}
static String encode(long num, String symbols) {
final int B = symbols.length();
StringBuilder sb = new StringBuilder();
while (num != 0) {
sb.append(symbols.charAt((int) (num % B)));
num /= B;
}
return sb.reverse().toString();
}
public static void main(String[] args) {
String range = "0123456789abcdefghijklmnopABCD#";
System.out.println(decode(encode(123456789L, range), range));
// prints "123456789"
System.out.println(encode(255L, "0123456789ABCDEF"));
// prints "FF"
System.out.println(decode("100", "01234567"));
// prints "64"
}
Note that this is essentially base conversion with a custom set of symbols.
Related questions
- substitution cypher with different alphabet length
回答2:
This is simply a matter of performing base conversion. Simply convert the long to the appropriate numeric base, corresponding to the number of characters in your string, and use the range string as your set of "digits".
For example, suppose you have the string "0123456789ABCDEF", then this means you must convert to base 16, hexadecimal. If the string is "01234567", then you convert to base 8, octal.
result = "";
while (number > 0)
{
result = range[(number % range.length)] + result;
number = number / 16; //integer division, decimals discarded
}
For going back, take the first character, find its position in the string, and add it to the result. Then, for each subsequent character, multiply the current result by the base before adding the position of the next character.
result = 0;
for (int i = 0; i < input.length; i++)
{
result = result * range.length;
result = range.indexOf(input[i])
}
回答3:
look for Patten and matcher. Here is my snippet
private static final String LUCENE_ENCODE_ESCAPE_CHARS = "[\\+\-\!\(\)\:\^\]\{\}\~\*\?]";
private static final String LUCENE_DECODE_ESCAPE_CHARS = "\\\\";
private static final String REPLACEMENT_STRING = "\\\\$0";
private static final Pattern LUCENE_ENCODE_PATTERN = Pattern.compile(LUCENE_ENCODE_ESCAPE_CHARS);
private static final Pattern LUCENE_DECODE_PATTERN = Pattern.compile(LUCENE_DECODE_ESCAPE_CHARS);
@Test
public void test() {
String encodeMe = "\\ this + is ~ awesome ! ";
String encode = LUCENE_ENCODE_PATTERN.matcher(encodeMe).replaceAll(REPLACEMENT_STRING);
String decode = LUCENE_DECODE_PATTERN.matcher(encode).replaceAll("");
System.out.println("Encode " + encode);
System.out.println("Decode " + decode);
}
来源:https://stackoverflow.com/questions/2938482/encode-decode-a-long-to-a-string-using-a-fixed-set-of-letters-in-java