[英]How to convert a long into printable bytes
我有一個代表長字符串。 如"12345678901"
(11個字符長)。
我使用Long.parse()
將其轉換為long,這很好。
現在,我想以短字符串的形式發送,例如通過電線發送"eR%s"
。
目標是使最后的字符串盡可能短。 知道什么是最好的方法嗎? 我可以使用更多字符作為URL編碼(就像我可以使用/,%、:等)。
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();
}
}
如果您想要更短的表示形式,請為您的數字使用其他基數。
使用的數字基數越大,表示形式越小。 您可以嘗試以16為基數:
Long.toString(num, 16)
這應該返回最多16個字符的字符串。
如果還不夠小,則可以在更大的基礎上構建表示形式。 但是,如果需要對結果字符串進行URL轉義,則可能沒有用。 例如,以256為基數,任何數字8個字符就足夠了,但是256個字符中的許多字符都需要轉義,從而使生成的文本更長。 因此,如果您選擇自己實現這種編碼/解碼方案,則必須謹慎選擇字母。
例如,看一下http://en.wikipedia.org/wiki/Base64 。 您可以使用此Java實現 。 您可能還對Base85及其實現感興趣。
為了回答Base64與其他選項的評論,我將說,這完全取決於您對字符集的約束。 我不是在談論通過URL傳輸,而是在char流上傳輸,char流必須是文本流。 我不能簡單地發送字節數組,因為不可打印的字符可能會導致某些問題。
因此,我構建了類似的內容(請參見下文),該內容可以轉換base92中的一個long(幾乎)。 它使用除負號和豎線(用於定界符)之外的所有可打印字符。
這幾乎是對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;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.