GSM 03.38 規定短信默認使用 7 位編碼,將 8 位 ASCII 字符「壓縮」裝填,提高容量 (160 字符/條 vs 140 字節)。
按位流連續讀取,每 7 位輸出一字節。示例 "1234" (ASCII: 0x31 0x32 0x33 0x34) → 0x31 0xD9 0x8C 0x06。
// 位流視圖
ASCII: 00110001 00110010 00110011 00110100
7-bit: 0011000 11101100 11000110 00000110 (分組)
Hex: 31 D9 8C 06
AnsiString EncodeEnglish(AnsiString InputStr) {
AnsiString ret;
int n = 0; // 當前位偏移 0-6
for (int i = 1; i <= InputStr.Length(); i++) {
unsigned char cur = InputStr[i];
unsigned char next = (i < InputStr.Length()) ? InputStr[i+1] : 0;
unsigned char val = (cur >> n) | ((next << (7-n)) & 0xFF);
if (n == 6) { // 第7個字符特殊:只取高1位,下一字符將從頭開始
val = cur >> 6;
i++; // 跳過下一字符(已部分消費)
}
ret += IntToHex(val, 2);
n = (n + 1) % 7;
}
return ret;
}
逆向操作:根據位偏移從兩個連續 7-bit 字節中提取 8-bit ASCII。代碼使用查表 ReturnHex 獲取掩碼。
中文不適用 7-bit 壓縮,直接使用 UCS2 (Big-Endian),即每個字符 2 字節,對應 GSM 03.38 中的「數據編碼方案」標識為 0x08 (UCS2)。
AnsiString EncodeChinese(AnsiString InputStr) {
WideString ws = InputStr; // VCL 自動按系統代碼頁(CP936)轉寬字符
AnsiString ret;
for (int i = 1; i <= ws.Length(); i++) {
ret += IntToHex((unsigned short)ws[i], 4); // 高位在前
}
return ret;
}
AnsiString DecodeChinese(AnsiString InputStr) {
wchar_t buf[300];
for (int i = 0; i < InputStr.Length(); i += 4) {
buf[i/4] = StrToInt("0x" + InputStr.SubString(i+1, 4));
}
buf[InputStr.Length()/4] = 0;
return WideCharToString(buf); // VCL 轉回 AnsiString
}