如何在c#中快速编码然后压缩包含数字的短字符串?

我有这样的字符串:

000101456890 348324000433 888000033380 

它们是长度相同的字符串,只包含数字。

我想找到一种方法来编码然后ompress(减少长度)的字符串。 压缩算法只需压缩为ASCII字符,因为它们将用作网页链接。

例如:

 www.stackoverflow.com/000101456890 goes to www.stackoverflow.com/aJks 

有什么方法可以做到这一点,一些方法可以快速压缩。

谢谢,

简单地说 ,你可以认为每个都很long (那里有足够的空间)和hex编码; 这给你:

 60c1bfa 5119ba72b1 cec0ed3264 

base-64会更短,但你需要将它看作big-endian(注意大多数.NET是little-endian)并忽略前导0字节。 这给你:

 Bgwb+g== URm6crE= zsDtMmQ= 

例如:

  static void Main() { long x = 000101456890L, y = 348324000433L, z = 888000033380L; Console.WriteLine(Convert.ToString(x, 16)); Console.WriteLine(Convert.ToString(y, 16)); Console.WriteLine(Convert.ToString(y, 16)); Console.WriteLine(Pack(x)); Console.WriteLine(Pack(y)); Console.WriteLine(Pack(z)); Console.WriteLine(Convert.ToInt64("60c1bfa", 16).ToString().PadLeft(12, '0')); Console.WriteLine(Convert.ToInt64("5119ba72b1", 16).ToString().PadLeft(12, '0')); Console.WriteLine(Convert.ToInt64("cec0ed3264", 16).ToString().PadLeft(12, '0')); Console.WriteLine(Unpack("Bgwb+g==").ToString().PadLeft(12, '0')); Console.WriteLine(Unpack("URm6crE=").ToString().PadLeft(12, '0')); Console.WriteLine(Unpack("zsDtMmQ=").ToString().PadLeft(12, '0')); } static string Pack(long value) { ulong a = (ulong)value; // make shift easy List bytes = new List(8); while (a != 0) { bytes.Add((byte)a); a >>= 8; } bytes.Reverse(); var chunk = bytes.ToArray(); return Convert.ToBase64String(chunk); } static long Unpack(string value) { var chunk = Convert.FromBase64String(value); ulong a = 0; for (int i = 0; i < chunk.Length; i++) { a <<= 8; a |= chunk[i]; } return (long)a; } 

我不确定Base 64是否是url安全的,因为它的索引表中有’/’(所选答案中提供的pack函数将产生非url-safe字符串)。

您可以考虑使用更友好的url或使用其他基础替换’/’符号。 例如,Base 62将在这里完成。

这是一个通用代码,可以从十进制来回转换为任何数字基数<= 64(它可能更快,然后转换为字节然后使用Convert.ToBase64String()):

 static void Main() { Console.WriteLine(Decode("101456890", 10)); Console.WriteLine(Encode(101456890, 62)); Console.WriteLine(Decode("6rhZS", 62)); //Result: //101456890 //6rhZS //101456890 } public static long Decode(string str, int baze) { long result = 0; int place = 1; for (int i = 0; i < str.Length; ++i) { result += Value(str[str.Length - 1 - i]) * place; place *= baze; } return result; } public static string Encode(long val, int baze) { var buffer = new char[64]; int place = 0; long q = val; do { buffer[place++] = Symbol(q % baze); q = q / baze; } while (q > 0); Array.Reverse(buffer, 0, place); return new string(buffer, 0, place); } public static long Value(char c) { if (c == '+') return 62; if (c == '/') return 63; if (c < '0') throw new ArgumentOutOfRangeException("c"); if (c < ':') return c - '0'; if (c < 'A') throw new ArgumentOutOfRangeException("c"); if (c < '[') return c - 'A' + 10; if (c < 'a') throw new ArgumentOutOfRangeException("c"); if (c < '{') return c - 'a' + 36; throw new ArgumentOutOfRangeException("c"); } public static char Symbol(long i) { if (i < 0) throw new ArgumentOutOfRangeException("i"); if (i < 10) return (char)('0' + i); if (i < 36) return (char)('A' + i - 10); if (i < 62) return (char)('a' + i - 36); if (i == 62) return '+'; if (i == 63) return '/'; throw new ArgumentOutOfRangeException("i"); }