我正在寻找一种方法来尽可能缩短已经很短的字符串。
该字符串是主机名:端口组合,可能看起来像“我的域名.se:2121" or "123.211.80.4:2122".
我知道由于所需的开销和缺乏重复,对于这么短的字符串来说常规压缩几乎是不可能的,但我知道如何做到这一点。
因为字母表限制为 39 个字符([a-z][0-9]-:。)每个字符可以容纳 6 位。与 ASCII 相比,长度最多可减少 25%。所以我的建议是这样的:
- 使用某种自定义编码将字符串编码为字节数组
- 将字节数组解码为 UTF-8 或 ASCII 字符串(该字符串显然没有任何意义)。
然后逆向处理即可得到原始字符串。
所以我的问题是:
- 这行得通吗?
- 有没有更好的办法?
- How?
您可以将字符串编码为基数 40,它比基数 64 更紧凑。这将为您提供 12 个这样的标记,长度为 64 位。第 40 个标记可能是字符串标记的结尾,用于给出长度(因为它不再是整数字节)
如果您使用算术编码,它可能会小得多,但您需要每个标记的频率表。 (使用一长串可能的例子)
class Encoder {
public static final int BASE = 40;
StringBuilder chars = new StringBuilder(BASE);
byte[] index = new byte[256];
{
chars.append('\0');
for (char ch = 'a'; ch <= 'z'; ch++) chars.append(ch);
for (char ch = '0'; ch <= '9'; ch++) chars.append(ch);
chars.append("-:.");
Arrays.fill(index, (byte) -1);
for (byte i = 0; i < chars.length(); i++)
index[chars.charAt(i)] = i;
}
public byte[] encode(String address) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
for (int i = 0; i < address.length(); i += 3) {
switch (Math.min(3, address.length() - i)) {
case 1: // last one.
byte b = index[address.charAt(i)];
dos.writeByte(b);
break;
case 2:
char ch = (char) ((index[address.charAt(i+1)]) * 40 + index[address.charAt(i)]);
dos.writeChar(ch);
break;
case 3:
char ch2 = (char) ((index[address.charAt(i+2)] * 40 + index[address.charAt(i + 1)]) * 40 + index[address.charAt(i)]);
dos.writeChar(ch2);
break;
}
}
return baos.toByteArray();
} catch (IOException e) {
throw new AssertionError(e);
}
}
public static void main(String[] args) {
Encoder encoder = new Encoder();
for (String s : "twitter.com:2122,123.211.80.4:2122,my-domain.se:2121,www.stackoverflow.com:80".split(",")) {
System.out.println(s + " (" + s.length() + " chars) encoded is " + encoder.encode(s).length + " bytes.");
}
}
}
prints
twitter.com:2122 (16 chars) encoded is 11 bytes.
123.211.80.4:2122 (17 chars) encoded is 12 bytes.
my-domain.se:2121 (17 chars) encoded is 12 bytes.
www.stackoverflow.com:80 (24 chars) encoded is 16 bytes.
我把解码作为练习。 ;)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)