2011-11-17 79 views
0

我得到一個可能的大數字(UInt.MaxValue:18446744073709551615)作爲正常的base10數字。 這個數字最終將成爲一個文件名:12345678945768.txt將UInt64表示爲字符串的最短途徑

由於在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())); 

有沒有更好的方式來「壓縮」整數類似轉換爲十六進制,但使用00-ZZ,而不僅僅是00-FF?

在此先感謝!

+0

可能有些愚蠢的問題,但_why_你需要「壓縮」這些名字嗎? – Oded

+0

這種壓縮的目的是什麼?你希望保存什麼? – Eilon

+0

文件路徑進入數據庫字段。這個領域是有限的,隨着數字的增長,他們可能無法適應該領域。更改數據庫架構不是一個選項。 – Leon

回答

3

一切到目前爲止,我已經找到指出的Base64是最短的,但事實並非如此。

你不想使用Base64。 Base64編碼文本可以使用/字符,這在Windows上的文件名中是不允許的。你需要拿出別的東西。

還有什麼?

好了,你可以寫你自己的基本轉換,或許是這樣的:

public static string Convert(ulong number) 
{ 
    var validCharacters = "[email protected]#$%^&()_-"; 
    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的多個字符,較小的輸出將是。隨意添加更多,只要它們在您的文件系統中是合法的字符。

+0

謝謝,這很完美!我不得不修改有效的字符 - NTFS不區分大小寫。此外,將字符串轉換回'UInt'很容易,因此我可以輕鬆地將創建的文件映射到匹配的記錄。 – Leon

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; 
} 
+0

請注意,如果這是用於文件名,base-64編碼將使用'/ '字符,這在文件名中是不允許的。 – vcsjones

3

什麼是你允許的字符集?如果您可以識別7132個可安全使用的不同Unicode字符,則可以將一個64位數字編碼爲五個Unicode字符。另一方面,並​​非所有的文件系統都支持這些字符。如果您可以識別139個合法字符,則可以將數據壓縮爲九個字符的字符串。有了85,你可以使用十個字符的字符串。

相關問題