編碼系列--Base24編碼

0、寫在前面
Windows和Office的序列號就是在最終換算之後,通過Base24編碼轉換成爲可顯示字符串的。寫這個系列的目的就是做類似的東東。
 
1、編碼原理
在Base32的那篇文章中已經比較詳細的說明了,這裏只指出與原理相比較,Base24是一個非常奇怪的方案,因爲用4個bits作爲分碼段,只能用到16個,另外8個編碼字符用不到,而採用5個bits作爲分碼段,又少8個字符。這就是之前寫了個Base32的原因。
後來想明白了這個問題,還是4個bits一組,然後在通過另外一種方式把24個字符都用上不就行了,我採用的是比較愚蠢的方式,按照位置取8的餘數,再加上編碼值換算即可。總之樣子上已經沒啥區別了。
先申明,我並不知道MS採用的Base24的具體的方式是什麼,因爲和我描述的不同,因爲據說它是將114bit編碼成爲200個bits(25個Bytes),我說的方法顯然做不到。目前就到這個地步吧,有空再想想。
 
2、源代碼
只把Encoding和Decoding的兩個函數貼出來,其他的都雷同。
  public new static String Encode(Byte[] abData)
  {
   Int32 dwLoop = 0,dwCharIndex = 0,dwCharCount = 0,dwRem = 0;
   Char[] acPart = null;
   StringBuilder sbOutput = null;
 
   if (abData == null || m_acBaseMap == null || m_acBaseMap.Length < m_dwMapLength)
    return null;
 
   try
   {
    dwCharCount = abData.Length * 2;
    sbOutput = new StringBuilder(dwCharCount);
    acPart = new Char[2];
   }
   catch (Exception e)
   {
    Trace.WriteLine("CLsBase24.Encode: Initialize buffer failed! " + e.Message);
   }
   if (acPart == null || sbOutput == null)
    return null;
 
   for(dwLoop = 0;dwLoop < abData.Length;dwLoop++)
   {
    Array.Clear(acPart,0,acPart.Length);
    // ONE byte will split to TWO characters
    Math.DivRem(dwLoop,9,out dwRem);
    dwCharIndex = (abData[dwLoop] >> 4) + dwRem;
    acPart[0] = m_acBaseMap[dwCharIndex];
    dwCharIndex = (abData[dwLoop] & 0x0F) + dwRem;
    acPart[1] = m_acBaseMap[dwCharIndex];
    
    sbOutput.Append(acPart,0,acPart.Length);
   }
 
   return sbOutput.ToString();
  }
 
  public new static Byte[] Decode(String sData)
  {
   Int32 dwLoop = 0,dwLength = 0,dwRem = 0;
   Int32[] dwCharIndex = null;
   Byte[] abOutput = null;
   Char[] acInput = null;
 
   if (sData == null || sData == String.Empty)
    return null;
 
   acInput = sData.ToCharArray();
   if (acInput == null)
    return null;
 
   try
   {
    dwLength = acInput.Length / 2;
    abOutput = new Byte[dwLength];
    dwCharIndex = new Int32[2];
   }
   catch (Exception e)
   {
    Trace.WriteLine("CLsBase24.Decode: Initialize buffer failed! " + e.Message);
   }
   if (acInput == null)
    return null;
 
   dwLength = 0;
   for (dwLoop = 0;dwLoop < acInput.Length;dwLoop += 2)
   {
    Array.Clear(dwCharIndex,0,dwCharIndex.Length);
    // TWO character can merage ONE byte
    Math.DivRem(dwLoop / 2,9,out dwRem);
    switch (acInput.Length - dwLoop)
    {
     case 1:
      dwCharIndex[0] = GetCharIndex(acInput[dwLoop]) - dwRem;
      abOutput[dwLength] = (Byte) (dwCharIndex[0] << 4);
      break;
 
     default:
      dwCharIndex[0] = GetCharIndex(acInput[dwLoop]) - dwRem;
      dwCharIndex[1] = GetCharIndex(acInput[dwLoop + 1]) - dwRem;
      abOutput[dwLength] = (Byte) ((dwCharIndex[0] << 4) + dwCharIndex[1]);
      break;
 
    }
    dwLength++;
   }
 
   return abOutput;
  }
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章