图书馆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的数据元素编码方案》

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/472775.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

算法沉淀——贪心算法四(leetcode真题剖析)

算法沉淀——贪心算法四 01.最长回文串02.增减字符串匹配03.分发饼干04.最优除法 01.最长回文串 题目链接&#xff1a;https://leetcode.cn/problems/longest-palindrome/ 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的回文串 。 …

【软件测试】如何设计自动化测试脚本

企业中如何设计自动化测试脚本呢&#xff1f;今天我们就来为大家分享一些干货。 一、线性设计 线性脚本设计方式是以脚本的方式体现测试用例&#xff0c;是一种非结构化的编码方式&#xff0c;多数采用录制回放的方式&#xff0c;测试工程师通过录制回访的访问对被测系统进行…

在ComfyUI中,IP-Adapter的一大堆模型应该怎么放?

&#x1f381;背景介绍 IP-Adapter有一大堆的模型&#xff0c;那么这个模型在ComfyUI中&#xff0c;这些模型到底应该怎么放呢&#xff1f;这篇文章简单介绍一下。 首先&#xff0c;大家需要到huggingface上找到对应的模型&#xff0c;把所有的模型先下载下来。 huggingface…

vue2 项目认识 vue2 各个文件夹作用 vue工程文件作用 main.js是什么 package.json是什么

1. node_modules : 项目依赖文件夹&#xff0c;相当于java类库。依赖包 2. public 文件夹: 一般放置一些静态资源&#xff08;图片&#xff09;&#xff0c;注意&#xff1a; 放在public文件夹内的文件&#xff0c;webpack打包时候&#xff0c;会原封不动打包到dist文件夹中 …

隐私计算实训营学习二:隐私计算开源如何助力数据要素流通

文章目录 一、数据要素流转与数据内外循环二、数据外循环中的信任焦虑三、数据要素流通对隐私计算的期望四、隐私计算开源助力数据要素流通 一、数据要素流转与数据内外循环 数据要素流转过程(从数据采集加工->到数据价值释放)&#xff1a; 链路主要包括采集、存储、加工、…

Pandas-排序函数sort_values()

Pandas-排序函数sort_values() pandas中的sort_values()函数原理类似于SQL中的order by&#xff0c;可以将数据集依照某个字段中的数据进行排序&#xff0c;该函数即可根据指定列数据也可根据指定行的数据排序。 pandas中的sort_values()函数原理类似于SQL中的order by&#xf…

RR级别为什么不能完全解决幻读案例分析 | 什么是MCVV

0. 知识前要&#xff1a;1. 举个栗子&#xff1a;1.1. 栗子一&#xff1a;两次快照读之间存在更新语句&#xff0c;更新其他事务已经更新过的数据1.1.1. 执行过程分析&#xff1a;1.1.2. MVCC分析&#xff1a; 1.2. 栗子二&#xff1a;两次快照读之间存在更新语句&#xff0c;更…

LightDB24.1 存储过程支持inner和outer对变量的引用

背景 Oracle oracle plsql支持如下场景&#xff1a; 在for循环中&#xff0c;将select查询的结果给一个record类型&#xff0c;这一操作也被称为隐式游标操作。record类型中一个字段用来接收查询结果中的一个select查询语句&#xff08;update,delete,insert在这个语法中都会…

CentOS安装zsh与ohmyzsh

文章目录 安装 zsh安装 ohmyzsh安装插件.zshrc 配置终端效果 安装 zsh yum install -y git curl # 安装zsh yum install -y zsh # 查看已经安装shell cat /etc/shells # 切换shell chsh -s /bin/zsh安装 ohmyzsh 国内镜像 sh -c "$(curl -fsSL https://gitee.com/pocmo…

算法·动态规划Dynamic Programming

很多人听到动态规划或者什么dp数组了&#xff0c;或者是做到一道关于动态规划的题目时&#xff0c;就会有一种他很难且不好解决的恐惧心理&#xff0c;但是如果我们从基础的题目开始深入挖掘动规思想&#xff0c;在后边遇到动态规划的难题时就迎难而解了。  其实不然&#xff…

数据结构与算法3-选择排序

文章目录 1. 认识选择排序2. 图示2.1 图示12.2 图示2 3. 代码 1. 认识选择排序 双层for循环&#xff0c;每次选出最小的数放到i位置&#xff0c;时间复杂度O( n 2 n^2 n2)&#xff0c;空间复杂度O(1);从未排序的序列中找到最小&#xff08;或最大&#xff09;的元素&#xff0…

【CNN轻量化】ParameterNet: Parameters Are All You Need 参数就是你所需要的

论文链接&#xff1a;http://arxiv.org/abs/2306.14525 代码链接&#xff1a;https://github.com/huawei-noah/Efficient-AI-Backbones 一、摘要 现有的低FLOPs模型&#xff08;轻量化模型&#xff09;无法从大规模预训练中受益。本文旨在增加大规模视觉预训练模型中的参数数量…

程序员的最佳副业居然是炒股

前言 之前的文章 《程序员的最佳副业居然是这个》讲述了个人的副业选择&#xff0c;和各种做过的副业。最后选择了炒股。那么究竟是否能够在股市里赚到利润呢&#xff1f;以我个人最近的交易记录来看&#xff0c;答案是肯定的。 一个半月赚取了 2898 程序员投资的优势 程序…

netty基础_12.用 Netty 自己实现简单的RPC

用 Netty 自己实现简单的RPC RPC 基本介绍我们的RPC 调用流程图己实现 Dubbo RPC&#xff08;基于 Netty&#xff09;需求说明设计说明代码封装的RPCNettyServerNettyServerHandlerNettyClientHandlerNettyClient 接口服务端(provider)HelloServiceImplServerBootstrap 客户端(…

概率基础——逻辑回归多分类法

概率基础——逻辑回归多分类法 逻辑回归是一种经典的分类算法&#xff0c;通常用于解决二分类问题。然而&#xff0c;在实际应用中&#xff0c;我们经常会遇到多分类任务。本文将简单介绍逻辑回归的理论、多分类方法以及优缺点&#xff0c;并提供一个Python实现的示例。 逻辑…

【MySQL】图形化界面工具DataGrip安装&配置&使用

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

npm出现内部错误,重新设置镜像

问题&#xff1a; 报错解释&#xff1a; 这个错误表明你尝试从一个指定的npm镜像源的响应时失败了。可能的原因包括网络问题、镜像源不可用、DNS解析问题或者镜像源的确已经下线或更改。 1.重新设置镜像源 设置淘宝镜像源&#xff1a; npm config set registry https://re…

网络面试——http 和 https 的区别

区别&#xff1a; 1. HTTP 是超文本传输协议&#xff0c;信息是明文传输&#xff0c;HTTPS 是具有安全性的 SSL 加密传输协议。HTTPS 是由 SSL HTTP 协议构建的可进行加密传输、身份认证的网络协议&#xff0c;比 HTTP 协议安全 2. 端口号&#xff1a;http 使用 80 端口&#…

ros小问题之差速轮式机器人轮子不显示(rviz gazebo)

在rviz及gazebo练习差速轮式机器人时&#xff0c;很奇怪&#xff0c;只有个机器人的底板及底部的两个万向轮&#xff0c;如下图&#xff0c; 后来查看相关.xacro文件&#xff0c;里面是引用包含了轮子的xacro文件&#xff0c;只需传入不同的参数即可调用生成不同位置的轮子&…

代码学习第24天----回溯算法

随想录日记part24 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.03.10 主要内容&#xff1a;回溯算法在代码学习中尤其重要&#xff0c;所以今天继续加深对其的理解&#xff1a;1&#xff1a;递增子序列 &#xff1b;2.全排列 &#xff1b;3.全排列II 491.递…