短消息發送7Bit AscII編碼符號的問題
在以前寫的一個通過GSM模塊發送與接收短消息的業務系統已經運行很久了。前兩天檢查接收內容時發現有接收的內容中有亂碼。與發送者聯繫了,瞭解他發送的是一些字母中間有下劃線。因爲接收純字母已經做過測試了。我自己編輯了一條短消息“_”發上去,發現收到的也是亂碼,再發別的AscII字母,完全正常。再發看來問題出在短消息對符號的解碼上。
仔細檢查了一遍解碼程序,沒有發現問題。然後又在網上找了一段別人的解碼代碼,來進行測試,居然發現解碼後的符號也是亂碼。打開數據庫將原始接收的Byte字符串找出來,看到接收到的內容是“11”,十進制爲17,是不可見字符,而“_”的AscII碼是95。又將“_”附近的幾個字符試了一下,居然值都與AscII碼值不相符。
只好Google了,搜了一下“7 bit ”,找到了一個文件”The 7 bit default alphabet”,打開一看,暈,居然有個GSM 03.38規定了127個7 Bit字符,與標準的ISO-8859-1不相符。
只好重新寫一個對字符映射表了。本來想用一個數組或Hashtable來做映射,但是有幾個字符居然點用兩個Byte。犧牲點內存與CPU算了,在內存裏建了個數據表,將映射表做到DataTable裏了,然後用DataView的RowFilter來查找。可慢了一點,但用起來方便。
源碼如下:
public class Gsm7BitEncoding
{
DataTable dt7BitAlphabet = new DataTable();
DataView dv;
private static Gsm7BitEncoding _gsm7bit = new Gsm7BitEncoding();
public static Gsm7BitEncoding GetInstance()
{
return _gsm7bit;
}
public Gsm7BitEncoding()
{
//添加列
DataColumn dc=new DataColumn("I_Pre",typeof(byte));
dc.DefaultValue=0;
dt7BitAlphabet.Columns.Add(dc);
dc = new DataColumn("I_GsmChar", typeof(byte));
dc.DefaultValue = 0;
dt7BitAlphabet.Columns.Add(dc);
dc = new DataColumn("I_AscIIChar", typeof(byte));
dc.DefaultValue = 0;
dt7BitAlphabet.Columns.Add(dc);
#region 添加數據行
dt7BitAlphabet.Rows.Add(new object[] { 0,0 , 64 });
dt7BitAlphabet.Rows.Add(new object[] { 0,1 , 163 });
dt7BitAlphabet.Rows.Add(new object[] { 0,2 , 36 });
dt7BitAlphabet.Rows.Add(new object[] { 0,3 , 165 });
dt7BitAlphabet.Rows.Add(new object[] { 0,4 , 232 });
dt7BitAlphabet.Rows.Add(new object[] { 0,5 , 233 });
dt7BitAlphabet.Rows.Add(new object[] { 0,6 , 249 });
dt7BitAlphabet.Rows.Add(new object[] { 0,7 , 236 });
dt7BitAlphabet.Rows.Add(new object[] { 0,8 , 242 });
dt7BitAlphabet.Rows.Add(new object[] { 0, 9, 199 });
dt7BitAlphabet.Rows.Add(new object[] { 0,10 , 10 });
dt7BitAlphabet.Rows.Add(new object[] { 0,11 , 216 });
dt7BitAlphabet.Rows.Add(new object[] { 0,12 , 248 });
dt7BitAlphabet.Rows.Add(new object[] { 0,13 , 13 });
dt7BitAlphabet.Rows.Add(new object[] { 0,14 , 197 });
dt7BitAlphabet.Rows.Add(new object[] { 0,15 , 229 });
dt7BitAlphabet.Rows.Add(new object[] { 0,16 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,17 , 95 });
dt7BitAlphabet.Rows.Add(new object[] { 0,18 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,19 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,20 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,21 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,22 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,23 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,24 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,25 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,26 , 0 });
dt7BitAlphabet.Rows.Add(new object[] { 0,27 , 0 });
dt7BitAlphabet.Rows.Add(new object[] {27,10 , 12 });
dt7BitAlphabet.Rows.Add(new object[] {27,20 , 94 });
dt7BitAlphabet.Rows.Add(new object[] {27,40 , 123 });
dt7BitAlphabet.Rows.Add(new object[] {27,41 , 125 });
dt7BitAlphabet.Rows.Add(new object[] {27,47 , 92 });
dt7BitAlphabet.Rows.Add(new object[] {27,60 , 91 });
dt7BitAlphabet.Rows.Add(new object[] {27,61 , 126 });
dt7BitAlphabet.Rows.Add(new object[] {27,62 , 93 });
dt7BitAlphabet.Rows.Add(new object[] {27,64 , 124 });
dt7BitAlphabet.Rows.Add(new object[] {27,101 , 164 });
dt7BitAlphabet.Rows.Add(new object[] { 0,28 , 198 });
dt7BitAlphabet.Rows.Add(new object[] { 0,29 , 230 });
dt7BitAlphabet.Rows.Add(new object[] { 0,30 , 223 });
dt7BitAlphabet.Rows.Add(new object[] { 0,31 , 201 });
dt7BitAlphabet.Rows.Add(new object[] { 0,32 , 32 });
dt7BitAlphabet.Rows.Add(new object[] { 0,33 , 33 });
dt7BitAlphabet.Rows.Add(new object[] { 0,34 , 34 });
dt7BitAlphabet.Rows.Add(new object[] { 0,35 , 35 });
dt7BitAlphabet.Rows.Add(new object[] { 0,36 , 164 });
dt7BitAlphabet.Rows.Add(new object[] { 0,37 , 37 });
dt7BitAlphabet.Rows.Add(new object[] { 0,38 , 38 });
dt7BitAlphabet.Rows.Add(new object[] { 0,39 , 39 });
dt7BitAlphabet.Rows.Add(new object[] { 0,40 , 40 });
dt7BitAlphabet.Rows.Add(new object[] { 0,41 , 41 });
dt7BitAlphabet.Rows.Add(new object[] { 0,42 , 42 });
dt7BitAlphabet.Rows.Add(new object[] { 0,43 , 43 });
dt7BitAlphabet.Rows.Add(new object[] { 0,44 , 44 });
dt7BitAlphabet.Rows.Add(new object[] { 0,45 , 45 });
dt7BitAlphabet.Rows.Add(new object[] { 0,46 , 46 });
dt7BitAlphabet.Rows.Add(new object[] { 0,47 , 47 });
dt7BitAlphabet.Rows.Add(new object[] { 0,48 , 48 });
dt7BitAlphabet.Rows.Add(new object[] { 0,49 , 49 });
dt7BitAlphabet.Rows.Add(new object[] { 0,50 , 50 });
dt7BitAlphabet.Rows.Add(new object[] { 0,51 , 51 });
dt7BitAlphabet.Rows.Add(new object[] { 0,52 , 52 });
dt7BitAlphabet.Rows.Add(new object[] { 0,53 , 53 });
dt7BitAlphabet.Rows.Add(new object[] { 0,54 , 54 });
dt7BitAlphabet.Rows.Add(new object[] { 0,55 , 55 });
dt7BitAlphabet.Rows.Add(new object[] { 0,56 , 56 });
dt7BitAlphabet.Rows.Add(new object[] { 0,57 , 57 });
dt7BitAlphabet.Rows.Add(new object[] { 0,58 , 58 });
dt7BitAlphabet.Rows.Add(new object[] { 0,59 , 59 });
dt7BitAlphabet.Rows.Add(new object[] { 0,60 , 60 });
dt7BitAlphabet.Rows.Add(new object[] { 0,61 , 61 });
dt7BitAlphabet.Rows.Add(new object[] { 0,62 , 62 });
dt7BitAlphabet.Rows.Add(new object[] { 0,63 , 63 });
dt7BitAlphabet.Rows.Add(new object[] { 0,64 , 161 });
dt7BitAlphabet.Rows.Add(new object[] { 0,65 , 65 });
dt7BitAlphabet.Rows.Add(new object[] { 0,66 , 66 });
dt7BitAlphabet.Rows.Add(new object[] { 0,67 , 67 });
dt7BitAlphabet.Rows.Add(new object[] { 0,68 , 68 });
dt7BitAlphabet.Rows.Add(new object[] { 0,69 , 69 });
dt7BitAlphabet.Rows.Add(new object[] { 0,70 , 70 });
dt7BitAlphabet.Rows.Add(new object[] { 0,71 , 71 });
dt7BitAlphabet.Rows.Add(new object[] { 0,72 , 72 });
dt7BitAlphabet.Rows.Add(new object[] { 0,73 , 73 });
dt7BitAlphabet.Rows.Add(new object[] { 0,74 , 74 });
dt7BitAlphabet.Rows.Add(new object[] { 0,75 , 75 });
dt7BitAlphabet.Rows.Add(new object[] { 0,76 , 76 });
dt7BitAlphabet.Rows.Add(new object[] { 0,77 , 77 });
dt7BitAlphabet.Rows.Add(new object[] { 0,78 , 78 });
dt7BitAlphabet.Rows.Add(new object[] { 0,79 , 79 });
dt7BitAlphabet.Rows.Add(new object[] { 0,80 , 80 });
dt7BitAlphabet.Rows.Add(new object[] { 0,81 , 81 });
dt7BitAlphabet.Rows.Add(new object[] { 0,82 , 82 });
dt7BitAlphabet.Rows.Add(new object[] { 0,83 , 83 });
dt7BitAlphabet.Rows.Add(new object[] { 0,84 , 84 });
dt7BitAlphabet.Rows.Add(new object[] { 0,85 , 85 });
dt7BitAlphabet.Rows.Add(new object[] { 0,86 , 86 });
dt7BitAlphabet.Rows.Add(new object[] { 0,87 , 87 });
dt7BitAlphabet.Rows.Add(new object[] { 0,88 , 88 });
dt7BitAlphabet.Rows.Add(new object[] { 0,89 , 89 });
dt7BitAlphabet.Rows.Add(new object[] { 0,90 , 90 });
dt7BitAlphabet.Rows.Add(new object[] { 0,91 , 196 });
dt7BitAlphabet.Rows.Add(new object[] { 0,92 , 214 });
dt7BitAlphabet.Rows.Add(new object[] { 0,93 , 209 });
dt7BitAlphabet.Rows.Add(new object[] { 0,94 , 220 });
dt7BitAlphabet.Rows.Add(new object[] { 0,95 , 167 });
dt7BitAlphabet.Rows.Add(new object[] { 0,96 , 191 });
dt7BitAlphabet.Rows.Add(new object[] { 0,97 , 97 });
dt7BitAlphabet.Rows.Add(new object[] { 0,98 , 98 });
dt7BitAlphabet.Rows.Add(new object[] { 0,99 , 99 });
dt7BitAlphabet.Rows.Add(new object[] { 0,100 , 100 });
dt7BitAlphabet.Rows.Add(new object[] { 0,101 , 101 });
dt7BitAlphabet.Rows.Add(new object[] { 0,102 , 102 });
dt7BitAlphabet.Rows.Add(new object[] { 0,103 , 103 });
dt7BitAlphabet.Rows.Add(new object[] { 0,104 , 104 });
dt7BitAlphabet.Rows.Add(new object[] { 0,105 , 105 });
dt7BitAlphabet.Rows.Add(new object[] { 0,106 , 106 });
dt7BitAlphabet.Rows.Add(new object[] { 0,107 , 107 });
dt7BitAlphabet.Rows.Add(new object[] { 0,108 , 108 });
dt7BitAlphabet.Rows.Add(new object[] { 0,109 , 109 });
dt7BitAlphabet.Rows.Add(new object[] { 0,110 , 110 });
dt7BitAlphabet.Rows.Add(new object[] { 0,111 , 111 });
dt7BitAlphabet.Rows.Add(new object[] { 0,112 , 112 });
dt7BitAlphabet.Rows.Add(new object[] { 0,113 , 113 });
dt7BitAlphabet.Rows.Add(new object[] { 0,114 , 114 });
dt7BitAlphabet.Rows.Add(new object[] { 0,115 , 115 });
dt7BitAlphabet.Rows.Add(new object[] { 0,116 , 116 });
dt7BitAlphabet.Rows.Add(new object[] { 0,117 , 117 });
dt7BitAlphabet.Rows.Add(new object[] { 0,118 , 118 });
dt7BitAlphabet.Rows.Add(new object[] { 0,119 , 119 });
dt7BitAlphabet.Rows.Add(new object[] { 0,120 , 120 });
dt7BitAlphabet.Rows.Add(new object[] { 0,121 , 121 });
dt7BitAlphabet.Rows.Add(new object[] { 0,122 , 122 });
dt7BitAlphabet.Rows.Add(new object[] { 0,123 , 228 });
dt7BitAlphabet.Rows.Add(new object[] { 0,124,124 });
dt7BitAlphabet.Rows.Add(new object[] { 0,125,125 });
dt7BitAlphabet.Rows.Add(new object[] { 0,126,126 });
#endregion
dv = dt7BitAlphabet.DefaultView;
}
/// <summary>
/// 獲取AscII字符串的Gsm7Bit字符編碼的長度
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public int GetByteCount(string s)
{
byte[] gsmBytes = GetBytes(s);
return gsmBytes.Length;
}
/// <summary>
/// 將AscII字符串轉換爲Gsm7Bit字符數據
/// </summary>
/// <param name="s"></param>
/// <returns></returns>
public byte[] GetBytes(string s)
{
byte[] ascBts;
List<byte> gsmBts=new List<byte>();
ascBts = ASCIIEncoding.ASCII.GetBytes(s);
for (int i = 0; i < ascBts.Length; i++)
{
dv.RowFilter = "I_AscIIChar=" + ascBts[i].ToString();
if (dv.Count>0)
{
byte pre = (byte)dv[0][0];
byte gsmchar = (byte)dv[0][1];
if (pre==27)
{
gsmBts.Add(27);
}
gsmBts.Add(gsmchar);
}
}
return gsmBts.ToArray();
}
/// <summary>
/// 從GSM7Bit字符數據轉換爲AscII字符串
/// </summary>
/// <param name="gsmBytes"></param>
/// <returns></returns>
public string GetString(byte[] gsmBytes)
{
StringBuilder sb = new StringBuilder();
string condition = "";
for (int i = 0; i < gsmBytes.Length; i++)
{
if (gsmBytes[i] == 27)
{
condition = " I_Pre=27 and ";
i++;
condition += " I_GsmChar=" + gsmBytes[i].ToString();
}
else
{
condition = "I_Pre=0 and I_GsmChar=" + gsmBytes[i].ToString();
}
dv.RowFilter = condition;
if (dv.Count>0)
{
System.Diagnostics.Debug.Assert((byte)dv[0][2] != 0);
sb.Append((char)(byte)dv[0][2]);
}
}
return sb.ToString();
}
}