借助linxuanchen的一篇文檔《C#實現整型數據字任意編碼任意進制的轉換和逆轉換》,實現了使用62進制字符串壓縮16進制字符串的功能。主要是在原作者的基礎上做了一些轉換處理,總結思路如下:
1.16進制字符串(0-9A-F)轉換成Int64的整數,如:(hex16)DAFDE = (hex10)896734
2. 將Int64整數轉換為62進制數(0~9a-zA-Z):3LlA。(linxuanchen的代碼已經實現)
需要注意的幾個問題:
1.Int64最大的數值為Int64.MaxValue,該常數的值為 9,223,372,036,854,775,807;即十六進制的 0x7FFFFFFFFFFFFFFF。所以實際做字符串壓縮的時候,需要對16進制字符串長度進行處理,最多一次壓縮15個字符,避免溢出。
2.輸出的62進制字符串之間需要用分割符,否則無法解碼。
直接代碼如下:
using System; using System.Collections.Generic; //using System.Linq; using System.Text; // @ http://www.cnblogs.com/linxuanchen/archive/2012/02/02/2336099.html // @ shadu {AT} foxmail.com namespace HexCover { public class MyString { /// <summary> /// 以MaxLength長度分割strHex16字符串 /// </summary> /// <param name="strHex16"></param> /// <param name="MaxLength"></param> /// <returns></returns> public static List<string> SplitHex16StingWithLength(string strHex16, int MaxLength) { string tmpStr = ""; List<string> StringList = new List<string>(); int count = strHex16.Length / MaxLength; if (strHex16.Length % MaxLength != 0) { for (int i = 0; i <= count; i++) { if ((strHex16.Length - i * MaxLength) > MaxLength) { tmpStr = strHex16.Substring(i * MaxLength, MaxLength); StringList.Add(tmpStr); } else { tmpStr = strHex16.Substring(i * MaxLength, (strHex16.Length % MaxLength)); StringList.Add(tmpStr); } } } else { for (int i = 0; i < count; i++) { tmpStr = strHex16.Substring(i * MaxLength, MaxLength); StringList.Add(tmpStr); } } return StringList; } } public class Number { public string Characters { get; set; } public int Length { get { if (Characters != null) return Characters.Length; else return 0; } } public Number() { Characters = "0123456789"; } public Number(string characters) { Characters = characters; } /// <summary> /// 數字轉換為指定的進制形式字符串 /// </summary> /// <param name="number"></param> /// <returns></returns> public string ToString(long number) { List<string> result = new List<string>(); long t = number; while (t > 0) { var mod = t % Length; t = Math.Abs(t / Length); var character = Characters[Convert.ToInt32(mod)].ToString(); result.Insert(0, character); } return string.Join("", result.ToArray()); } /// <summary> /// 指定字符串轉換為指定進制的數字形式 /// </summary> /// <param name="str"></param> /// <returns></returns> public long FromString(string str) { long result = 0; int j = 0; char[] arr = str.ToCharArray(); Array.Reverse(arr); //return new string(arr); foreach (char ch in new string(arr)) //foreach (var ch in new string(str.ToCharArray().Reverse().ToArray())) { //Characters.Contains( if (Characters.Contains(ch.ToString())) { result += Characters.IndexOf(ch) * ((long)Math.Pow(Length, j)); j++; } } return result; } } class Program { static void Print(long number, Number adapter) { Console.WriteLine("輸入數字:{0}", number); Console.WriteLine("規則:{0}\t\t進制:{1}進制", adapter.Characters, adapter.Length); var numtostr = adapter.ToString(number); Console.WriteLine("轉換結果:{0}", numtostr); var strtonum = adapter.FromString(numtostr); Console.WriteLine("逆向轉換結果:{0}", strtonum); Console.WriteLine(); Console.WriteLine("============ 無聊的分割線 ============"); Console.WriteLine(); } static void Main(string[] args) { //傳統的2進制 Number n1 = new Number("01"); //傳統的8進制 Number n2 = new Number("01234567"); //傳統的16進制 Number n3 = new Number("0123456789ABCDEF"); //自定義編碼的N進制,這個可以用來做驗證碼? Number n4 = new Number("爹媽說名字太長躲在樹後面會被部落發現"); //山寨一個短網址 Number n5 = new Number("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); Print(65535, n1); Print(65535, n2); Print(65535, n3); Print(65535, n4); Print(72057594037927934, n5); Console.ReadKey(); //==== Added by Laien @ 2012-09-25 string strHex = "FFFFFFFFFFFFFFF3131CDAFDE"; string tmpStr = "" ; List<string> strList = MyString.SplitHex16StingWithLength(strHex, 15); foreach (string s in strList) tmpStr += "-" + n5.ToString(Convert.ToInt64(s, 16)); Console.WriteLine("轉換前16進制字符串:{0}", strHex); Console.WriteLine("轉換後62字符串:{0} (-是分隔符)", tmpStr); Console.ReadKey(); } } }運行結果如下