使用LibUsbDotNet读取通用USB RFID读卡器,如何获取卡面RFID编号?
解决USB RFID读卡器字节数组转卡片编号的问题
既然你已经发现读卡器是通过模拟HID键盘输入来输出编号的,那我们直接解析LibUsbDotNet拿到的字节数组(也就是HID键盘报告)就行,不用绕键盘记录器的路子了。
核心思路:解析HID键盘报告格式
USB键盘的标准HID报告通常是8字节的结构:
- 第0字节:修饰键位掩码(比如Shift、Ctrl这些,一般读卡器用不到)
- 第1字节:保留位(固定为0)
- 第2-7字节:按键扫描码(最多同时发送6个按键,没按键的位置是0)
读卡器会把卡片编号的每个字符,依次转换成对应的键盘扫描码发送出来,我们只需要把这些扫描码映射回字符,拼接起来就是卡片表面的编号。
具体实现步骤
建立扫描码到字符的映射表
针对数字和常见的RFID编号字符(比如0-9),先定义标准美式键盘的扫描码映射(不同地区键盘布局可能略有差异,可根据实际调整):private static Dictionary<byte, char> KeyScanCodeMap = new Dictionary<byte, char> { {0x0B, '0'}, {0x02, '1'}, {0x03, '2'}, {0x04, '3'}, {0x05, '4'}, {0x06, '5'}, {0x07, '6'}, {0x08, '7'}, {0x09, '8'}, {0x0A, '9'}, {0x28, '\r'} // 部分读卡器最后会发送回车,后续需要过滤 };解析LibUsb读取到的字节数组
假设你用LibUsbDotNet读取到的字节数组是byte[] readBuffer,我们遍历有效扫描码位并转换为字符:public string ConvertRfidBytesToCardNumber(byte[] readBuffer) { StringBuilder cardNumber = new StringBuilder(); // 跳过前2字节(修饰键+保留位),遍历第2到第7字节的扫描码 for (int i = 2; i < readBuffer.Length; i++) { byte scanCode = readBuffer[i]; if (scanCode == 0) continue; // 跳过空按键位置 if (KeyScanCodeMap.TryGetValue(scanCode, out char c)) { if (c != '\r') // 过滤回车符,只保留编号内容 cardNumber.Append(c); } } return cardNumber.ToString(); }集成到原有读取逻辑
在你原来用LibUsbDotNet读取数据的代码中,把拿到的readBuffer传入上面的方法,就能直接得到和键盘记录器一致的卡片编号了。
额外注意事项
- 如果你的读卡器支持字母编号,需要补充对应扫描码映射,若涉及大写字母还需结合第0字节的修饰键位判断是否需要转大写。
- 部分读卡器的HID报告长度可能略有不同,若解析失败可先打印
readBuffer的所有字节值,调整遍历的起始位置和范围。 - 少数读卡器会发送按键按下+抬起的两次报告,这时候需要过滤掉重复的扫描码,只保留首次出现的有效按键。
内容的提问来源于stack exchange,提问作者OJ Raqueño
相关产品推荐
相关产品推荐

