当前位置: 首页 > 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的数据元素编码方案》

在这里插入图片描述

http://www.lryc.cn/news/321931.html

相关文章:

  • 【Java Web基础】一些网页设计基础(三)
  • 2 使用GPU理解并行计算
  • Android什么情况下会出现内存泄漏以及怎么解决?
  • kafka集群介绍及搭建
  • 2024/03/19(网络编程·day5)
  • ​LeetCode解法汇总1969. 数组元素的最小非零乘积
  • 学习vue3第九节(新加指令 v-pre/v-once/v-memo/v-cloak )
  • 二开飞机机器人群发,实现自动给多个频道发送消息
  • AI如何支持慈善组织
  • Git如何清除账户凭证
  • 【YUNBEE云贝-PostgreSQL】FDW应用
  • Spring MVC文件上传配置
  • JavaScript高级(十八)---进程和线程,宏任务和微任务
  • How to install mongodb on redhat 7.7
  • 关于继承是怎么样的?那当然是很好理解之
  • 高可用系统有哪些设计原则
  • LeetCode-回文数
  • 50. 【Linux教程】源码安装软件
  • 《操作系统实践-基于Linux应用与内核编程》第10章--实验 Qt聊天程序
  • 探究Kafka主题删除失败的根本原因
  • JavaSE(上)-Day7
  • 记录一下在Pycharm中虚拟环境的创建
  • Python从入门到精通秘籍九
  • 善于利用window挂在全局变量
  • 《C缺陷和陷阱》-笔记(5)
  • 【数字图像处理matlab系列】保存图像
  • 八股文三(Spring、Spring Cloud Alibaba)
  • 一文带你详解天池工业数据集
  • 08 龙芯平台openstack部署搭建-neutron-controller部署
  • JAVA 100道题(6)