Как закодировать ByteArray в строку base36

Чтобы закодировать ByteArray в Base64, я мог бы просто использовать Base64 из java.util. Но теперь мне нужно изменить свой код, чтобы вместо этого создать base36. К сожалению, java.util не имеет этой функции. Мне нужна функция/метод, который принимает ByteArray и выводит String, содержащую base36. его представление. Никаких других изменений, таких как удаление ведущих нулей.

Итак, этот другой вопрос выглядит похожим, но у нас две проблемы. Сначала вопрос был отредактирован, так что я не понимаю ответа. Во-вторых, в ответе используется BigInteger, и я боюсь, что преобразование ByteArray в BigInteger может привести к потере информации (например, начальным нулям). Похожий вопрос о stackoverflow.


person Yava    schedule 13.09.2020    source источник
comment
Разница в том, что 64 — это точное количество битов, а 36 — нет. Таким образом, вам нужно будет эффективно многократно делить весь массив байтов на 36, принимая каждый остаток как цифру с правого конца, что будет намного проще просто использовать BigInteger. Вы, вероятно, правы, это упадет ведущие нули: нужно ли их сохранять? Если вы, возможно, подсчитали ожидаемую длину выходной строки, используйте метод BigInteger, а затем добавьте начальные нули, необходимые для получения ожидаемой длины.   -  person Rup    schedule 14.09.2020
comment
Да, мне нужны ведущие нули, потому что это не число. Я не уверен, смогу ли я угадать ожидаемую длину, тем временем я ищу альтернативный способ: строку base64 в строку base36. Я думаю, что это неоптимально с ненужным шагом к base64, но, возможно, я найду для этого больше решений.   -  person Yava    schedule 14.09.2020
comment
Если это не число, с какой стати использовать Base36? Это не имеет смысла, так как Base36 нельзя делать инкрементно, так как байты передаются/обрабатываются.   -  person Andreas    schedule 14.09.2020
comment
Все, что я могу сказать, это то, что base36 - это схема кодирования двоичного кода в текст, двоичный файл может содержать все.   -  person Yava    schedule 14.09.2020
comment
В голову не пришло, base36digits = Math.ceil(bytes * Math.log(256) / Math.log(36)). Но base36 звучит так, как будто это неправильная кодировка для использования здесь, поэтому, если вы можете выяснить, зачем она нужна, и вместо этого переключиться на что-то другое, например base64, это было бы разумно.   -  person Rup    schedule 14.09.2020
comment
Как умножить массив байтов? Или вы делаете математику для каждого байта? А почему магическое число 256?   -  person Yava    schedule 22.09.2020
comment
256 = 2 в степени 8 = количество возможных значений байта. Нет, вы не умножаете массив, а только длину массива, то есть количество байтов, которые у вас есть, что я и имел в виду для переменной bytes в расчете.   -  person Rup    schedule 22.09.2020
comment
Math.log(256) / Math.log(36) – это количество цифр с основанием 36, которое вам потребуется для представления одного байта данных, поэтому мы умножаем его на количество имеющихся у вас байтов, а затем округляем в большую сторону, чтобы получить необходимое количество цифр с основанием 36.   -  person Rup    schedule 22.09.2020
comment
В качестве альтернативного подхода к получению правильного количества цифр вы также можете создать массив байтов той же длины, который просто содержит значение 255 для каждого байта, загрузить его также в BigInteger, а затем, когда вы генерируете цифры для вашего входного массива также делите этот новый массив на 36 каждый раз. Когда BigInteger для этого нового массива равен нулю, значит, вы сгенерировали достаточно цифр.   -  person Rup    schedule 22.09.2020
comment
Или на самом деле вы не делите, вы просто используете BigInteger.toString()? Преобразуйте этот второй массив в базу 36, используя BigInteger, а затем дополните первое значение тем же количеством цифр base36.   -  person Rup    schedule 22.09.2020