当前位置: 首页 > news >正文

图书馆RFID(射频识别)数据模型压缩/解压缩算法实现小工具

1. 前言

最近闲来无聊,看了一下《图书馆射频识别数据模型第1部分:数据元素的设置及应用规则》以及《图书馆射频识别数据模型第2部分:基于ISO/IEC 15962的数据元素编码方案》,决定根据上面的编码方法实现一下该算法,于是写了一个小工具,本文将围绕这个小工具介绍一下其用法。

2. 详细说明

本程序分别实现了数据的压缩和解压缩两种算法,程序界面如下:

在这里插入图片描述

2.1 开发环境

开发工具:Microsoft Visual Studio Community 2022 (64 位) - Current 版本 17.7.6

目标框架:.Net Framework 4.6.2

开发语言:C#

运行环境:Window 10 x86/x64

2.2 数据压缩

馆代码(馆标识):使用馆际互借时用于标识图书馆的唯一编码,格式为:2位国家代码-字母和数字,如:CH-sztsg001
在这里插入图片描述

馆藏地代码:图书馆中用于标识图书所在物理位置的编码,一般由字母和数字组成,如图书馆一楼:tsg001
在这里插入图片描述

应用类别:资料类型以及在图书馆内的用途,参照《图书馆射频识别数据模型第1部分:数据元素的设置及应用规则》中的附录C,这里设置为0x12
在这里插入图片描述

条码号:一般由数字和字母组成,如:TM000000012121
在这里插入图片描述

在这里插入图片描述

输入以上信息后,点击压缩,程序会根据条码的数据类型选择相应的压缩算法进行数据压缩,并输出压缩后的结果。压缩算法可参照《图书馆射频识别数据模型第2部分:基于ISO/IEC 15962的数据元素编码方案》中关于数据编码的部分内容。

2.3 数据解压缩

将压缩后的数据输入至文本框中,点击加压缩即可,程序会自动解析数据,并将结果呈现至馆代码、馆藏地点、应用类别、条码号中。

在这里插入图片描述

3. 代码

3.1 压缩算法

 /// <summary>/// 数据压缩/// </summary>/// <param name="dataType">数据类型(如:条码号 DataTyep.Barcode)</param>/// <param name="data">数据内容</param>/// <param name="userDefineCompressFormat">是否使用自定义压缩模式</param>/// <param name="defaultFormat">自定义压缩模式</param>/// <returns></returns>private static byte[] DataCompress(string data, bool userDefineCompressFormat = false, CompressModel defaultFormat = CompressModel.Number){try{if (data == null || data == ""){return null;}CompressModel format = defaultFormat;if (userDefineCompressFormat){format = defaultFormat;//压缩类型}else{format = GetDataCompressFormat(data);//压缩类型}byte[] btData = null;switch (format){case CompressModel.ISIL:btData = GetConverData0(data);break;case CompressModel.IntNumber:btData = GetConverData1(data);break;case CompressModel.Number:btData = GetConverData2(data);break;case CompressModel.CP_5Bit:btData = GetConverData3(data);break;case CompressModel.CP_6Bit:btData = GetConverData4(data);break;case CompressModel.CP_7Bit:btData = GetConverData5(data);break;case CompressModel.CP_8bit:btData = GetConverData6(data);break;default:btData = Encoding.UTF8.GetBytes(data);break;}if (btData == null){return null;}return btData;}catch (Exception ex){}return null;}/// <summary>/// 获取压缩后的数据/// </summary>/// <param name="orgDataDic"></param>/// <returns></returns>public static byte[] GetCompressData(Dictionary<DataType, string> orgDataDic){try{//每个数据集均由前导字节、编码数据长度、被压缩数据3部分组成Dictionary<DataType, RfidData> cmpDataDic = new Dictionary<DataType, RfidData>();int nDataTotalLen = 0;foreach (var key in orgDataDic.Keys){RfidData data = new RfidData();//馆代码采用固定的ISIL方式编码if (key == DataType.LibraryCode){data.compressFormat = CompressModel.ISIL;}//直接使用8位编码else if (key == DataType.UseType || key == DataType.LocationCode || key == DataType.ONIXMediaFormat){data.compressFormat = CompressModel.CP_8bit;}else{data.compressFormat = GetDataCompressFormat(orgDataDic[key]);}data.strData = orgDataDic[key];if (string.IsNullOrEmpty(data.strData)){continue;}//如果数据大于最大的整数,则采用数字压缩if (data.compressFormat == CompressModel.IntNumber && data.strData.Length >= 18){data.compressFormat = CompressModel.Number;}byte[] btData = DataCompress(orgDataDic[key], true, data.compressFormat);byte nAppLen = 0;byte btFirstByte = 0;bool bFlag = CheckFirstByteData(data.compressFormat, key, btData, out btFirstByte, out nAppLen);//如果为条码号则需要进行填充判断if (key == DataType.BarCode && bFlag){data.byteData = new byte[btData.Length + 3 + nAppLen];//前导符(1byte) + 偏移量(1byte) + 压缩数据长度(1byte) + 填充数据长度(nAppLen)data.byteData[0] = btFirstByte;data.byteData[1] = nAppLen;data.byteData[2] = (byte)btData.Length;Array.Copy(btData, 0, data.byteData, 3, btData.Length);}else{data.byteData = new byte[btData.Length + 2];//前导符(1byte) + 压缩数据长度(1byte)data.byteData[0] = GetFirstByteData(data.compressFormat, key);data.byteData[1] = (byte)btData.Length;Array.Copy(btData, 0, data.byteData, 2, btData.Length);}nDataTotalLen += data.byteData.Length;//数据总长度cmpDataDic.Add(key, data);}return GetFullCompressData(ref cmpDataDic, nDataTotalLen);}catch (Exception ex){                }return null;}       

注:以上仅为部分代码。

3.2 解压缩算法

/// <summary>
/// 解压一个数据块
/// </summary>
/// <param name="btDecData">待解压的数据</param>
/// <param name="nDecType">数据压缩方式</param>
/// <param name="nDataType">数据类型</param>
/// <param name="nDataLen">数据长度</param>
/// <returns></returns>
private static RfidData DataDeCompress(byte[] btDecData, int nDecType, int nDataType)
{try{RfidData data = new RfidData();string strDecData = string.Empty;switch (nDecType){case (int)CompressModel.ISIL:if ((DataType)nDataType == DataType.LibraryCode){strDecData = GetExplodeDate0(btDecData);}else{strDecData = GetExplodeDate6(btDecData);}break;case (int)CompressModel.IntNumber:strDecData = GetExplodeDate1(btDecData);break;case (int)CompressModel.Number:strDecData = GetExplodeDate2(btDecData);break;case (int)CompressModel.CP_5Bit://五位码strDecData = GetExplodeDate3(btDecData);break;case (int)CompressModel.CP_6Bit:strDecData = GetExplodeDate4(btDecData);break;case (int)CompressModel.CP_7Bit:strDecData = GetExplodeDate5(btDecData);break;case (int)CompressModel.CP_8bit:strDecData = GetExplodeDate6(btDecData);break;}DataType dataType = (DataType)nDataType;data.byteData = btDecData;data.compressFormat = (CompressModel)nDecType;data.strData = strDecData;return data;}catch (Exception ex){}return null;
}/// <summary>
/// 解压缩
/// </summary>
/// <param name="strData">16进制(大写)被压缩后的数据</param>
/// <returns></returns>
public static Dictionary<DataType, RfidData> DataDeCompress(string strData)
{try{if (string.IsNullOrEmpty(strData)){return null;}Dictionary<DataType, RfidData> dataDic = new Dictionary<DataType, RfidData>();int nIdx = 0;byte[] btData = StringToByte(strData);do{//取第一个字节和第二个字节byte btFirstData = btData[nIdx];byte btDataLen = 0;nIdx += 1;int nAppLen = 0;//填充数据长度int nDecType = 0;//压缩类型int nDataType = 0;//数据类型byte[] btDecData;//压缩后的数据//判断数据是否有填充和偏移bool bAppFlag = CheckDataAppend(btFirstData, out nDecType, out nDataType);if (nDataType == 0)//有问题的数据块直接算是有效数据终止{break;}if (bAppFlag){nAppLen = btData[nIdx];nIdx += 1;//跳过填充字节btDataLen = btData[nIdx];//标示数据长度nIdx += 1;//跳过数据长度字节//压缩后的数据btDecData = new byte[btDataLen];Array.Copy(btData, nIdx, btDecData, 0, btDataLen);nIdx = nIdx + btDataLen + nAppLen;}else{btDataLen = btData[nIdx];//标示数据长度nIdx += 1;//跳过数据长度字节if (nIdx + btDataLen >= btData.Length){break;}//压缩后的数据btDecData = new byte[btDataLen];Array.Copy(btData, nIdx, btDecData, 0, btDataLen);nIdx += btDataLen;}DataType dataType = (DataType)nDataType;RfidData data = DataDeCompress(btDecData, nDecType, nDataType);if (nDataType > 0 && nDataType < (int)DataType.NotUseFlag){if (!dataDic.ContainsKey(dataType)){dataDic.Add(dataType, data);}}}while (nIdx < btData.Length);return dataDic;}catch (Exception ex){}return null;
}

注:以上仅为部分代码。

4. 总结

程序主要包括两部分的功能:压缩与解压缩,将压缩后的数据作为输入数据可执行解压缩操作,也可用于将使用了支持标准的图书馆射频识别数据模型算法加密的数据进行解压缩,文章中提及的算法代码均为压缩或解压缩代码中的一部分。

4.1 参考资料1

《图书馆射频识别数据模型第1部分:数据元素的设置及应用规则》
在这里插入图片描述

4.2 参考资料2

《图书馆射频识别数据模型第2部分:基于ISO/IEC 15962的数据元素编码方案》

在这里插入图片描述

相关文章:

图书馆RFID(射频识别)数据模型压缩/解压缩算法实现小工具

1. 前言 最近闲来无聊&#xff0c;看了一下《图书馆射频识别数据模型第1部分&#xff1a;数据元素的设置及应用规则》以及《图书馆射频识别数据模型第2部分&#xff1a;基于ISO/IEC 15962的数据元素编码方案》&#xff0c;决定根据上面的编码方法实现一下该算法&#xff0c;于…...

【Java Web基础】一些网页设计基础(三)

文章目录 1. 导航栏样式进一步调整2. 入驻企业信息展示栏2.1 Title设置2.2 具体信息添加 3. 轮播图4. 注册登录按钮及其他信息5. 一些五颜六色的、丰富视觉效果的中间件…… 1. 导航栏样式进一步调整 这种导航栏&#xff0c;选中的时候字体变蓝色&#xff0c;可能还是不够美观&…...

2 使用GPU理解并行计算

2.1 简介 本章旨在对并行程序设计的基本概念及其与GPU技术的联系做一个宽泛的介绍。本章主要面向具有串行程序设计经验&#xff0c;但对并行处理概念缺乏了解的读者。我们将用GPU的基本知识来讲解并行程序设计的基本概念。 2.2 传统的串行代码 绝大多数程序员是在串行程序占据…...

Android什么情况下会出现内存泄漏以及怎么解决?

1.什么情况下会出现内存泄漏? (1)单例模式下为什么会造成内存泄漏? 因为单例的生命周期和应用的生命周期是一致的,如果往单例模式里面传了一个生命周期比较短的对象,比如Activity,就会导致Activity不能释放,导致内存泄漏。我们可以传context.getAppliactionContext,而…...

kafka集群介绍及搭建

介绍 kafka是一个高性能、低延迟、分布式的消息传递系统&#xff0c;特点在于实时处理数据。集群由多个成员节点broker组成&#xff0c;每个节点都可以独立处理消息传递和存储任务。 路由策略 发布消息由key、value组成&#xff0c;真正的消息是value&#xff0c;key是标识路…...

2024/03/19(网络编程·day5)

一、思维导图 二、selec函数实现TCP并发服务器 #include<myhead.h>#define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.117.116" //服务器IP int main(int argc, const char *argv[]) {//1、创建一个套接字int sfd -1;sfd socket(AF_INET,SOC…...

​LeetCode解法汇总1969. 数组元素的最小非零乘积

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个正整数 p 。你有一个下标从 1 开…...

学习vue3第九节(新加指令 v-pre/v-once/v-memo/v-cloak )

1、v-pre 作用&#xff1a;防止编译器解析某个特定的元素及其内容&#xff0c;即v-pre 会跳过当前元素以及其子元素的vue语法解析&#xff0c;并将其保持原样输出&#xff1b; 用于&#xff1a;vue 中一些没有指令和插值表达式的节点的元素&#xff0c;使用 v-pre 可以提高 Vu…...

二开飞机机器人群发,实现自动给多个频道发送消息

频道1 频道2 二开代码部分&#xff1a; const CChatIdListprocess.env.CHANNEL_CHAT_ID_LIST; var channelChatIdArray CChatIdList.split(,);channelChatIdArray.forEach(function(item) {console.log(item); // 这里可以替换为您需要对数组中每个值进行的操作bot.sendM…...

AI如何支持慈善组织

为各种有意义的事业提供支持&#xff0c;无论是努力寻找治愈疾病的方法、研发使生活更轻松的技术&#xff0c;还是为有需要的人提供服务&#xff0c;都是无比崇高的使命。提供捐款或是投入时间支持的捐助者和志愿者往往对他们选择支持的事业的目标、服务和资源分配存有诸多疑虑…...

Git如何清除账户凭证

场景&#xff1a;一般发生在Git用户变更的情况 1.git base 操作 Git会使用凭证助手 credential.helper来储存账户凭证&#xff0c;通过以下命令移除&#xff1a; git config --system --unset credential.helper 除了system系统级外&#xff0c;还有 global、local范围。 查…...

【YUNBEE云贝-PostgreSQL】FDW应用

注: 本文为云贝教育 刘峰 原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎和未经注明出处的转载。 前言 Wrapper&#xff08;FDW&#xff09;是一项关键特性&#xff0c;它赋予数据库用户直接通过SQL语句访问存储于外部数据源的能…...

Spring MVC文件上传配置

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 文件上传 Spring MVC文件上传基于Servlet 3.0实现&#xff1b;示例代码如下&#xff1a; Overrideprotected void customizeRegistration(ServletRegistration.Dynamic reg…...

JavaScript高级(十八)---进程和线程,宏任务和微任务

进程和线程 进程&#xff08;process&#xff09;&#xff1a;计算机已经运行的程序&#xff0c;是操作系统管理程序的一种方式&#xff0c;我们可以认为&#xff0c;启动一个应用程序&#xff0c;就会默认启动一个进程&#xff08;也可能是多个进程&#xff09;。 线程&…...

How to install mongodb on redhat 7.7

下载rpm: mongodb-enterprise-server-6.0.3-1.el7.x86_64.rpmmongodb-org-server-6.0.4-1.el7.x86_64.rpmmongodb-mms-6.0.9.100.20230201T2148Z.x86_64.rpm rpm -ivh mongodb-org-server-6.0.4-1.el7.x86_64.rpm rpm -ivh mongodb-mms-6.0.9.100.20230201T2148Z.x86_64.rpm …...

关于继承是怎么样的?那当然是很好理解之

本文描述了关于继承的大部分知识&#xff0c;但是并不全&#xff0c;每篇博客之间的知识都有互串&#xff0c;所以需要把几篇文章合起来看&#xff0c;学会融会贯通&#xff01; 温馨提示&#xff1a;使用PC端观看&#xff0c;效果更佳&#xff01; 目录 1.继承是什么 2.什…...

高可用系统有哪些设计原则

1.降级 主动降级&#xff1a;开关推送 被动降级&#xff1a;超时降级 异常降级 失败率 熔断保护 多级降级2.限流 nginx的limit模块 gateway redisLua 业务层限流 本地限流 gua 分布式限流 sentinel 3.弹性计算 弹性伸缩—K8Sdocker 主链路压力过大的时候可以将非主链路的机器给…...

LeetCode-回文数

LeetCode-回文数 解体思路&#xff1a; ①第一种&#xff1a;转换成字符串&#xff0c;使用字符串的现有api方法进行反转 ②第二种&#xff1a;直接使用循环除余乘10方法&#xff0c;进行反转 涉及知识点&#xff1a; 循环判断&#xff0c;StringBuffer&#xff0c;int类型…...

50. 【Linux教程】源码安装软件

本小节介绍如何使用软件的源码包安装软件&#xff0c;以安装 nginx 源码包为例。 1.下载软件源码包 使用如下命令下载 nginx 源码包&#xff1a; wget http://nginx.org/download/nginx-1.18.0.tar.gz执行结果如下图所示&#xff1a; 2.解压源码包 下载好了压缩包之后&#…...

《操作系统实践-基于Linux应用与内核编程》第10章--实验 Qt聊天程序

前言: 内容参考《操作系统实践-基于Linux应用与内核编程》一书的示例代码和教材内容&#xff0c;所做的读书笔记。本文记录再这里按照书中示例做一遍代码编程实践加深对操作系统的理解。 引用: 《操作系统实践-基于Linux应用与内核编程》 作者&#xff1a;房胜、李旭健、黄…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用

中达瑞和自2005年成立以来&#xff0c;一直在光谱成像领域深度钻研和发展&#xff0c;始终致力于研发高性能、高可靠性的光谱成像相机&#xff0c;为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...