粘贴一段 hex,同一份字节并排解出 ASCII 和 EBCDIC(CP500)两列,一眼看出手上的报文是哪种编码。
0x / \x 前缀都会自动清掉;hex 字符个数是奇数时会明确报错,不会静默截断。十六进制本身没有含义,含义来自你用哪张码表去读。字节 F1 按 ASCII 读超出可打印区间,只能显示成 .;按 EBCDIC(CP500)读却是数字 1。所以上面的 dump 给了两列——同一行字节,左边一列按 ASCII 解,右边一列按 EBCDIC 解,哪边读出人话,答案就在哪边。
几个最实用的判据,扫一眼 hex 就能下结论:
| 内容 | ASCII | EBCDIC(CP500) |
|---|---|---|
| 数字 0–9 | 0x30–0x39 | 0xF0–0xF9 |
| 空格 | 0x20 | 0x40 |
| 大写 A–Z | 0x41–0x5A 连续 | 0xC1–0xC9、0xD1–0xD9、0xE2–0xE9 三段 |
| 小写 a–z | 0x61–0x7A 连续 | 0x81–0x89、0x91–0x99、0xA2–0xA9 三段 |
报文里最多的就是数字和空格,所以经验法则非常好使:满屏 F0–F9 夹着大片 0x40,基本就是 EBCDIC;满屏 0x3? 夹着 0x20,就是 ASCII。还有个反向信号——ASCII 文本的高位(bit 8)恒为 0,字节都落在 0x00–0x7F;一份数据里大量出现 0x80 以上的字节,它要么不是 ASCII,要么根本不是文本。
Mastercard IPM(T112)这类清算文件按 EBCDIC 编码,原因很直接:卡组清算平台是大型机(mainframe)时代建起来的,IBM 大机的原生字符集就是 EBCDIC,码表沿用至今。授权链路上的在线报文各家规范不一(ASCII、BCD、EBCDIC 都有),但批量清算文件这一侧,EBCDIC 是常态。拿到一份清算文件先别急着按 ASCII 解——先扔进上面的查看器看 EBCDIC 列,多半立刻就能读出 PAN、金额和商户名。逐条解 IPM 记录用 Mastercard IPM 文件解析。
还有一种情况:两列都是点,但字节看着又很「规整」。这多半是 BCD(压缩十进制)——每个字节的高低两个 nibble 各存一位十进制数字,0x01 0x10 存的就是 0110。它不是字符编码,没有对应的可打印字符,所以 ASCII 列和 EBCDIC 列都读不出来;判别特征是每个 nibble 都不超过 9,字节值全落在 0x00–0x99 且两个 nibble 都是 0–9。同样 4 位数字,ASCII 要 4 字节、BCD 只要 2 字节,这就是很多规范用它存 MTI、金额、日期的原因。BCD 值和十进制、十六进制之间怎么换算,用进制与 BCD 转换器。
拿 8 个字节 F1 F9 F8 F7 40 C9 D7 D4 逐个过一遍:
| 字节 | 按 ASCII | 按 EBCDIC(CP500) |
|---|---|---|
F1 F9 F8 F7 | 都超出 0x7E,四个 . | 0xF1–0xF7 落在数字区 → 1 9 8 7 |
40 | @(0x40 在 ASCII 里是 @) | 空格 |
C9 D7 D4 | 都超出 0x7E,三个 . | C9=I、D7=P、D4=M |
ASCII 列读出来是 ....@...,EBCDIC 列读出来是 1987 IPM——一边是乱码一边是人话,判定结束。反过来,同样的文本用 ASCII 存是 31 39 38 37 20 49 50 4D:这串扔进查看器,读出 1987 IPM 的就换成了 ASCII 列。把这两串各贴进上面试一次,两列的分工立刻就有体感了。