更新 IDCardData 结构体字段类型为 uint8,并重构解码函数以支持 UCS-2/UTF-16LE 解码

This commit is contained in:
yuchenglong
2025-11-21 16:15:16 +08:00
parent 137bf13ae5
commit 29e1cd4560

View File

@@ -5,35 +5,49 @@ const iconv = require("iconv-lite");
// 定义结构体
const IDCardData = koffi.struct("IDCardData", {
Name: koffi.array("char", 32),
Sex: koffi.array("char", 6),
Nation: koffi.array("char", 20),
Born: koffi.array("char", 18),
Address: koffi.array("char", 72),
IDCardNo: koffi.array("char", 38),
GrantDept: koffi.array("char", 32),
UserLifeBegin: koffi.array("char", 18),
UserLifeEnd: koffi.array("char", 18),
reserved: koffi.array("char", 38),
PhotoFileName: koffi.array("char", 255),
Name: koffi.array("uint8", 32),
Sex: koffi.array("uint8", 6),
Nation: koffi.array("uint8", 20),
Born: koffi.array("uint8", 18),
Address: koffi.array("uint8", 72),
IDCardNo: koffi.array("uint8", 38),
GrantDept: koffi.array("uint8", 32),
UserLifeBegin: koffi.array("uint8", 18),
UserLifeEnd: koffi.array("uint8", 18),
reserved: koffi.array("uint8", 38),
PhotoFileName: koffi.array("uint8", 255),
});
let lib = null;
let running = false;
// 解码 GBK 字符串
function decodeGBK(buffer) {
// 找到第一个 null 字节 (0x00) 的位置
// 解码字符串 (尝试 UCS-2/UTF-16LE)
function decodeString(buffer) {
// 这里的 buffer 是 uint8 数组,先转为 Buffer
const buf = Buffer.from(buffer);
// 很多读卡器 DLL 返回的是 UCS-2 (UTF-16LE)
// 也有可能是 GBK。我们可以通过检查字节特征来判断或者优先尝试 UCS-2
// UCS-2 的特征是每两个字节一个字符,对于 ASCII 字符,高字节通常是 0x00
// 尝试作为 UTF-16LE 解码
// 找到双 null 结尾 (0x00 0x00)
let nullIndex = -1;
for (let i = 0; i < buffer.length; i++) {
if (buffer[i] === 0) {
for (let i = 0; i < buf.length - 1; i += 2) {
if (buf[i] === 0 && buf[i + 1] === 0) {
nullIndex = i;
break;
}
}
// 如果找到了 null截取前面的部分否则使用整个 buffer
const validBuffer = nullIndex !== -1 ? buffer.slice(0, nullIndex) : buffer;
return iconv.decode(validBuffer, "gbk").trim();
const validBuf16 = nullIndex !== -1 ? buf.slice(0, nullIndex) : buf;
const str16 = iconv.decode(validBuf16, "utf16le").trim();
// 如果解码出来的字符串看起来是乱码(包含很多 )或者为空但 buffer 不为空,可能需要尝试 GBK
// 但通常 Syn_IDCardRead.dll 返回的是 UCS-2
// 让我们先打印一下原始 hex 以便调试
// parentPort.postMessage({ type: 'log', payload: `Hex: ${buf.slice(0, 10).toString('hex')}` });
return str16;
}
// 加载 DLL
@@ -188,16 +202,16 @@ async function startListen() {
if (ret === 0 && data) {
const payload = {
name: decodeGBK(Buffer.from(data.Name)),
sex: decodeGBK(Buffer.from(data.Sex)),
nation: decodeGBK(Buffer.from(data.Nation)),
born: decodeGBK(Buffer.from(data.Born)),
address: decodeGBK(Buffer.from(data.Address)),
id_card_no: decodeGBK(Buffer.from(data.IDCardNo)),
grant_dept: decodeGBK(Buffer.from(data.GrantDept)),
life_begin: decodeGBK(Buffer.from(data.UserLifeBegin)),
life_end: decodeGBK(Buffer.from(data.UserLifeEnd)),
photo_path: decodeGBK(Buffer.from(data.PhotoFileName)),
name: decodeString(data.Name),
sex: decodeString(data.Sex),
nation: decodeString(data.Nation),
born: decodeString(data.Born),
address: decodeString(data.Address),
id_card_no: decodeString(data.IDCardNo),
grant_dept: decodeString(data.GrantDept),
life_begin: decodeString(data.UserLifeBegin),
life_end: decodeString(data.UserLifeEnd),
photo_path: decodeString(data.PhotoFileName),
};
parentPort.postMessage({