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

news2024/11/22 17:00:12

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.coloradmin.cn/o/1532097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyTorch 深度学习(GPT 重译)(五)

十二、通过指标和增强改进训练 本章涵盖 定义和计算精确率、召回率以及真/假阳性/阴性 使用 F1 分数与其他质量指标 平衡和增强数据以减少过拟合 使用 TensorBoard 绘制质量指标图 上一章的结束让我们陷入了困境。虽然我们能够将深度学习项目的机制放置好&#xff0c;但实…

聚类算法之层次聚类(Hierarchical Clustering)

注意&#xff1a;本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 &#xff08;[www.aideeplearning.cn]&#xff09; 层次聚类是一种非常独特和强大的聚类方法&#xff0c;与众多其他的聚类技术相比&#xff0c;它不仅为数据集提供了一个划分&#xff0c;还给出了…

3d模型文件导入时没颜色---模大狮模型网

导入3D模型文件时没有颜色显示通常是由于软件在显示模型时未正确解释颜色信息。这可能是由于模型文件本身没有包含颜色信息&#xff0c;或者是软件在导入过程中未正确处理颜色数据所致。 以下是一些可能的解决方法&#xff1a; 检查3D模型文件&#xff1a;首先&#xff0c;确保…

网络简略总结

目录 一、三次握手 四次挥手 1、三次握手:为了建立长链接进行交互即建立一个会话,使用http/https协议 2、四次挥手是一个断开连接释放服务器资源的过程 3、如果已经建立了连接,但是客户端突然出现故障了怎么办? 4、谁可以中断连接?客户端还是服务端还是都可以? 5、…

Linux环境开发工具之vim

前言 上一期我们已经介绍了软件包管理器yum&#xff0c; 已经可以在linux上查找、安装、卸载软件了&#xff0c;本期我们来介绍一下文本编辑器vim。 本期内容介绍 什么是vim vim的常见的模式以及切换 vim命令模式常见的操作 vim底行模式常见的操作 解决普通用户无法执行sudo问…

5G智能网关助力工业铸造设备监测升级

随着物联网技术的迅猛发展和工业4.0浪潮的推进&#xff0c;传统工业正面临着严峻的转型升级压力。在这一背景下&#xff0c;铸造行业——这一典型的传统重工业领域&#xff0c;也必须积极探索借助5G、物联网、边缘计算等技术提升生产经营效率的新路径。 本文就基于佰马合作伙伴…

【晴问算法】提高篇—动态规划专题—最大连续子序列和

题目描述 输入描述 输出描述 输出一个整数&#xff0c;表示最大连续子序列和。 样例1 输入 6 -2 11 -4 13 -5 -2 输出 20 解释 连续子序列和的最大值为&#xff1a; #include<bits/stdc.h> using namespace std; const int MAXN 100; int dp[MAXN];//dp[i]表示以a[i]元…

酷开科技聚焦大屏端数据研究,构建酷开系统深度挖掘大屏商业价值

中国所有的彩色大屏中&#xff0c;智能电视规模已经过半&#xff0c;OTT平台的数据价值越发引起人们关注。作为OTT行业的头部代表&#xff0c;酷开科技一直聚焦大屏端数据研究&#xff0c;目前已经形成一套基于大屏指数的智慧营销体系&#xff0c;让OTT大屏的数字营销化水平实现…

无人机/飞控--ArduPilot、PX4学习记录(2)

这是一篇碎碎念&#xff0c;零零碎碎的记录了环境配置过程&#xff0c;仅供本人记录学习历程和参考。(记录的挺乱的&#xff0c;但是文章链接里的博客写的是真好) 本章主要完成的目标&#xff1a; 安装PX4 并 成功运行出3D无人机界面。 参考文章&#xff1a; 搭建PX4环境&…

【LeetCode-114.二叉树展开为链表】

题目详情&#xff1a; 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序…

水果软件FL Studio 21 for mac 21.2.3.3586破解版的最新版本2024介绍安装

音乐是人类最美好的语言&#xff0c;它能够跨越国界、文化和语言&#xff0c;将人们紧密地联系在一起。在当今数字化时代&#xff0c;音乐创作已经不再是专业人士的专利&#xff0c;越来越多的音乐爱好者开始尝试自己动手制作音乐。而FL Studio21中文版编曲软件正是这样一个为你…

软件架构对于项目质量的影响

时间&#xff1a;2024年03月20日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频地址&#xff1a; 软件架构对于项目质量的影响在线收听-喜马拉雅 前言 大家好&#xff0c;欢迎来到小蒋聊技术&#xff0c;小蒋准备和大家一…

优先级队列(堆)(2)

目录 一. PriorityQueue的特性 二. PriorityQueue常用接口介绍 1. 优先级队列的构造 2. 转成大根堆存储方法: 3. 插入/删除/获取优先级最高的元素 三. Top-k问题 一. PriorityQueue的特性 Java 集合框架中提供了 PriorityQueue 和 PriorityBlockingQueue 两种类型的优先…

PowerShell 无法保留窗口和字体设置

那么&#xff0c;首先&#xff0c;得亮一下版本&#xff0c;默认软件&#xff1a; PS C:\Windows> $PSVersionTableName Value ---- ----- PSVersion 5.1.19041.4170 PSEdition …

Win11初始化系统遇一文解决

这个是目录 一、设置内的初始化无法使用时&#xff0c;使用以下工具二、将桌面移动到D盘三、解决win11桌面右键创建只有一个带盾牌的文件夹问题四、win11 系统停止更新五、office安装1、使用的是 Office Tool plus2、使用WPS 六、D盘有感叹号七、打开组策略编辑器(gpedit.msc)失…

安卓转鸿蒙能有多适配?简直了……

到现在为止&#xff0c;想必很多开发者都或多或少 了解过鸿蒙。许多企业也都已经加入了鸿蒙业务&#xff0c;半推半就的开始学习鸿蒙开发。那么鸿蒙到底好不好搞呢&#xff1f; 首先可以肯定的一点&#xff0c;对于做安卓的来说鸿蒙非常搞&#xff0c;究竟有多好搞呢&#xff…

SQL语句之SELECT语句

一般格式 SELECT DISTINCT/ALL 目标列表达式 //要显示的属性列 FROM 表名/视图名 //查询的对象 WHERE 条件表达式 //查询条件 GROUP BY 列名 HAVING 条件表达式 //查询结果分组 ORDER BY 列名 次序; //最终查询结果排序 文章目录 一、基本查询 1、SELECT 目标列表达…

系统设计实例(一)百万级别用户系统

二、百万级别用户系统 原则&#xff1a; 尽可能地缓存数据采用无状态Web层支持多个数据中心在 CDN 中托管静态资源通过分片扩展数据层将层级拆分为独立的服务 负载均衡器 负载均衡器会将传入的流量均匀分配给在负载均衡集合中定义的Web服务器&#xff0c;用户直接连接负载均…

数据结构与算法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…

Windows server Database 2025 安装 i225/i226 网卡驱动

windows这比坏得很&#xff0c;intel消费级网卡不准在服务器系统上安装。你要说他是异构不支持&#xff1f;他就纯粹恶心人。 之前已经安装过一次&#xff0c;但是今天database预览版一更新&#xff0c;又给我把网卡驱动杀了&#xff0c;气死&#xff0c;写一篇教程。 1.去官网…