将UInt64表示为字符串的最短方式

时间:2011-11-17 20:59:37

标签: c# .net string compression uint64

我得到一个可能很大的数字(UInt.MaxValue:18446744073709551615)作为正常的base10数字。 这个数字最终将成为文件名:12345678945768.txt

由于Windows上的文件名不仅限于数字,我想将其“压缩”为更短的字符串,但需要确保字符串可以映射回数字。

对于较小的数字:0001365555,hexed比其他任何东西短得多。 到目前为止我发现的所有内容都表明Base64最短,但事实并非如此。

到目前为止,我已经尝试过这个:

//18446744073709551615 - 20
UInt64 i = UInt64.MaxValue; // 0001365555

//"//////////8=" - 12
string encoded = Convert.ToBase64String(BitConverter.GetBytes(i)); 

//"FFFFFFFFFFFFFFFF" - 16
string hexed = i.ToString("X"); 

//"MTg0NDY3NDQwNzM3MDk1NTE2MTU=" - 28
string utf = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(i.ToString())); 

有没有更好的方法来“压缩”整数转换类似于Hex但使用00-zz而不仅仅是00-FF?

提前致谢!

5 个答案:

答案 0 :(得分:3)

你允许的字符集是什么?如果您可以识别可安全使用的7132个不同的Unicode字符,则可以将64位数字编码为5个Unicode字符。另一方面,并​​非所有文件系统都支持此类字符。如果您可以识别139个合法字符,则可以将数据压缩为9个字符的字符串。使用85,您可以使用十个字符的字符串。

答案 1 :(得分:3)

  

到目前为止,我发现的所有内容都表明Base64最短,但事实并非如此。

您不想使用Base64。 Base64编码的文本可以使用/字符,这在Windows上的文件名中是不允许的。你需要拿出别的东西。

  

还有什么?

好吧,您可以编写自己的基本转换,可能是这样的:

public static string Convert(ulong number)
{
    var validCharacters = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&()_-";
    char[] charArray = validCharacters.ToCharArray();
    var buffer = new StringBuilder();
    var quotient = number;
    ulong remainder;
    while (quotient != 0)
    {
        remainder = quotient % (ulong)charArray.LongLength;
        quotient = quotient / (ulong)charArray.LongLength;
        buffer.Insert(0, charArray[remainder].ToString());
    }
    return buffer.ToString();
}

这是“基数为73”的结果,validCharacters中的字符越多,输出就越小。您可以随意添加更多内容,只要它们是您文件系统中的合法字符。

答案 2 :(得分:1)

你误用了Base64。

(System.Text.Encoding.ASCII.GetBytes(i.ToString())

这会产生一个包含base10编码整数的字节序列,并在base64中再次对其进行编码。这显然效率低下。

您需要获取整数的原始字节并使用base64对其进行编码。哪种编码最有效取决于您希望允许的字符数。如果你想要笑

你应该在数组的一边修剪0个字节。

var bytes=BitConverter.GetBytes(input);
int len=8;
for(int i=7;i>=0;i--)
{
  if(bytes[i]!=0)
  {
    len=i+1;
    break;
  }
}
string s=Convert.ToBase64String(bytes,0,len).ReplaceString('/','-');

请注意,这在big-endian系统上无法正常工作。

但也许你应该一起避免使用字节编码,只使用更高基数的整数编码。

简单版本可能是:

string digitChars="0123..."
while(i!=0)
{
  int digit=i%digitChars.Length;
  i/=digitChars.Length;
  result=digitChars[digit]+result;
}

答案 3 :(得分:0)

答案 4 :(得分:0)

以下是一些使用vcsjones答案的代码,但也包含反向转换。就像他的回答一样,如果需要减小字符串大小,可以随意添加更多字符。下面的字符为ulong.MaxValue生成的字符串大小为13。

$server = "localhost";
$username = "root";
$password = "";
$database = "test";

$conn = mysqli_connect($server, $username, 
$password, $database);
if (!$conn) {
    die("Connection failed: " . 
mysqli_connect_error());
}