簡體   English   中英

如何將long轉換為可打印的字節

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM