Кодировать / декодировать long в строку, используя фиксированный набор букв в Java - PullRequest
4 голосов
/ 30 мая 2010

Учитывая произвольный набор букв

String range = "0123456789abcdefghijklmnopABCD#";

Я ищу 2 метода для кодирования / декодирования длинных <-> строк

String s = encode( range, l );

и

long l = decode( range, s );

Итак decode(range, encode(range, 123456789L)) == 123456789L

А если диапазон "0123456789", это обычный способ кодирования.

Ответы [ 3 ]

13 голосов
/ 30 мая 2010

Следующий код делает то, что вам нужно:

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"
}

Обратите внимание, что это по сути базовое преобразование с пользовательским набором символов.

Смежные вопросы

1 голос
/ 30 мая 2010

Это просто вопрос выполнения базового преобразования. Просто преобразуйте long в соответствующую числовую базу, соответствующую количеству символов в вашей строке, и используйте строку диапазона в качестве набора «цифр».

Например, предположим, что у вас есть строка "0123456789ABCDEF", то это означает, что вы должны преобразовать в шестнадцатеричное основание 16 Если строка "01234567", то вы преобразуете в восьмеричное основание 8.

result = "";
while (number > 0)
{
  result = range[(number % range.length)] + result;
  number = number / 16; //integer division, decimals discarded
}

Чтобы вернуться назад, возьмите первый символ, найдите его положение в строке и добавьте его к результату. Затем для каждого последующего символа умножьте текущий результат на основание, прежде чем добавлять позицию следующего символа.

result = 0;
for (int i = 0; i < input.length; i++)
{
  result = result * range.length;
  result = range.indexOf(input[i])
}
0 голосов
/ 26 декабря 2012

Ищите Паттена и Мэтчера. Вот мой фрагмент

частная статическая конечная строка 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);
}
...