.net文件中定义类型的压缩方法和装置转让专利

申请号 : CN200910244163.3

文献号 : CN101794220B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 陆舟于华章

申请人 : 飞天诚信科技股份有限公司

摘要 :

本发明提供了一种.net文件中定义类型的压缩方法和装置,属于计算机应用领域。所述压缩方法包括:获取.net文件中使用的定义类型包含的信息,根据所述定义类型包含的信息获取所述定义类型的指定信息和计数信息,对所述指定信息进行压缩,将压缩后的指定信息和所述计数信息作为所述定义类型的压缩结果进行存储。所述装置包括:定义类型信息获取模块、压缩模块和压缩结果存储模块。本发明采用对.net文件中的定义类型进行压缩,有效地降低了.net文件占用的存储容量,进而使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行。

权利要求 :

1.一种.net文件中定义类型的压缩方法,其特征在于,所述方法包括:获取.net文件中使用的定义类型包含的信息;其中,获取所述.net文件中使用的所述定义类型包含的信息的步骤包括:读取所述.net文件中的定义类型所在的元数据表;从所述定义类型所在的元数据表中获取所述.net文件中使用的定义类型包含的信息;

根据所述定义类型包含的信息获取所述定义类型的指定信息和计数信息;

对所述指定信息进行压缩;

将压缩后的指定信息和所述计数信息作为所述定义类型的压缩结果进行存储。

2.根据权利要求1所述的方法,其特征在于,所述定义类型包含的信息包括:所述定义类型的标识、所述定义类型的名称的偏移量、所述定义类型中的方法的偏移量;

相应地,所述指定信息包括:所述定义类型的标识和所述定义类型的名称;

所述计数信息包括:所述定义类型的方法重载信息和所述定义类型中包含的方法计数。

3.根据权利要求2所述的方法,其特征在于,所述定义类型的标识分为类型标识、访问标识和描述性标识;

相应地,所述对所述指定信息进行压缩的步骤包括:对所述类型标识、访问标识和描述性标识进行或运算,将得到的数据作为所述定义类型的标识的压缩结果;

对所述定义类型的名称进行哈希运算,从运算结果中提取约定的字节作为所述定义类型的名称的压缩结果。

4.根据权利要求2所述的方法,其特征在于,所述定义类型包含的信息还包括:所述定义类型中的字段的偏移量;

相应地,所述指定信息还包括:所述定义类型中的字段对应的信息;

所述计数信息还包括:所述定义类型的字段计数。

5.根据权利要求4所述的方法,其特征在于,所述定义类型中的字段对应的信息包括:字段的名称、字段的标识和字段的类型;

其中,所述字段的标识分为访问标识和描述性标识;

相应地,所述对所述指定信息进行压缩的步骤包括:对所述字段的名称进行哈希运算,从运算结果中提取约定的字节作为所述字段的名称的压缩结果;

对所述字段的标识中的访问标识和描述性标识进行或运算,将得到的结果作为所述字段的标识的压缩结果;

将所述字段的类型对应的类型压缩后的偏移量作为所述字段的类型的压缩结果。

6.根据权利要求1所述的方法,其特征在于,所述定义类型包含的信息包括:所述定义类型所继承的父类的偏移量;

相应地,所述方法还包括:

判断所述定义类型所继承的父类是否已压缩,如果是,获取所述父类的偏移量;否则,对所述父类进行压缩,并为压缩后的所述父类分配偏移量;

相应地,所述定义类型的压缩结果中还包括压缩后的所述父类的偏移量。

7.根据权利要求1所述的方法,其特征在于,所述方法还包括:判断所述定义类型是否有继承的接口;如果有,获取所述定义类型继承的接口压缩后的偏移量和继承的接口的个数;

相应地,所述定义类型的压缩结果中还包括所述继承的接口压缩后的偏移量和继承的接口的个数。

8.根据权利要求1所述的方法,其特征在于,所述方法还包括:判断所述定义类型是否是嵌套类型,如果是,获取所述定义类型所在的类型压缩后的偏移量;

相应地,所述定义类型的压缩结果中还包括所述嵌套类型所在的类型压缩后的偏移量。

9.一种.net文件中定义类型的压缩装置,其特征在于,所述装置包括:定义类型信息获取模块,用于获取.net文件中使用的定义类型包含的信息;根据所述定义类型包含的信息获取所述定义类型的指定信息和计数信息;其中,获取所述.net文件中使用的所述定义类型包含的信息的步骤包括:读取所述.net文件中的定义类型所在的元数据表,从所述定义类型所在的元数据表中获取所述.net文件中使用的定义类型包含的信息;

压缩模块,用于对所述定义类型信息获取模块获取的指定信息进行压缩;

压缩结果存储模块,用于将所述压缩模块压缩后的指定信息和所述定义类型信息获取模块获取的计数信息作为所述定义类型的压缩结果进行存储。

10.根据权利要求9所述的装置,其特征在于,所述定义类型信息获取模块中的定义类型包含的信息包括:所述定义类型的标识、所述定义类型的名称的偏移量、所述定义类型中的方法的偏移量;

相应地,所述指定信息包括:所述定义类型的标识和所述定义类型的名称;

所述计数信息包括:所述定义类型的方法重载信息和所述定义类型中包含的方法计数。

11.根据权利要求9所述的装置,其特征在于,所述定义类型信息获取模块中的定义类型包含的信息包括:所述定义类型所继承的父类的偏移量;

相应地,所述装置还包括:

第一判断模块,用于判断所述定义类型信息获取模块中的定义类型所继承的父类是否已压缩;

父类偏移量获取模块,用于当所述第一判断模块判断的结果是所述父类已压缩,获取所述父类的偏移量;所述父类没有压缩,对所述父类进行压缩,并为压缩后的所述父类分配偏移量;

相应地,所述压缩结果存储模块中存储的定义类型的压缩结果中还包括压缩后的所述父类的偏移量。

12.根据权利要求9所述的装置,其特征在于,所述装置还包括:第二判断模块,用于判断所述定义类型信息获取模块中的定义类型是否有继承的接口;

接口信息获取模块,用于当所述第二判断模块判断的结果是所述定义类型有继承的接口,获取所述定义类型继承的接口压缩后的偏移量和继承的接口的个数;

相应地,所述定义类型的压缩结果中还包括所述定义类型继承的接口压缩后的偏移量和继承的接口的个数。

13.根据权利要求9所述的装置,其特征在于,所述装置还包括:第三判断模块,用于判断所述定义类型信息获取模块中的定义类型是否是嵌套类型;

偏移量获取模块,用于当所述第三判断模块判断的结果是所述定义类型是嵌套类型时,获取所述定义类型所在的类型压缩后的偏移量;

相应地,所述压缩结果存储模块中存储的定义类型的压缩结果中还包括所述定义类型所在的类型压缩后的偏移量。

14.根据权利要求9-13任一所述的装置,其特征在于,所述定义类型包含的信息还包括:所述定义类型中的字段的偏移量;

相应地,所述指定信息还包括:所述定义类型中的字段对应的信息;

所述计数信息还包括:所述定义类型的字段计数。

说明书 :

.net文件中定义类型的压缩方法和装置

技术领域

[0001] 本发明涉及计算机应用领域,具体而言,涉及一种.net文件中定义类型的压缩方法和装置。

背景技术

[0002] .Net是微软的新一代技术平台,是全新的基于互联网的跨语言软件开发平台,顺应了当今软件工业分布式计算、面向组件、企业级应用、软件服务化和以Web为中心等大趋势。.Net并非开发语言,但是在.Net开发平台上可以支持多种开发语言,如C#语言、C++、Visual Basic、Jscript等。
[0003] 智能卡是一种大小和普通名片相仿的塑料卡片,内含一块直径1cm左右的硅芯片,具有存储信息和进行复杂运算的功能。它被广泛地应用于电话卡、金融卡、身份识别卡以及移动电话、付费电视等领域。其中,智能卡的芯片上集成了微处理器、存储器以及输入/输出单元等,使得智能卡被认为是世界上最小的电子计算机。并且在智能卡上拥有一整套性能较强的安全保密控制机制,安全控制程序被固化在只读存储器中,因而具有无法复制密码等可靠的安全保证。智能卡与普通磁卡相比,还具有信息存储容量大,可利用微处理器来增加卡片功能等优点。
[0004] .Net卡是一种含有可以运行.Net程序的.Net卡虚拟机的微处理器智能卡。所谓虚拟机,是指可以把它想象成一台用软件来模拟的机器,在这台机器里有处理器、内存、寄存器等各种硬件,模拟运行各种指令,在这台机器上运行的软件对运行环境没有特殊要求,所以虚拟机对在它上运行的程序来说是透明的。例如,x86虚拟机模拟的是x86指令程序的运行环境,c51虚拟机模拟的是c51指令程序的运行环境。
[0005] .net程序包括命名空间、引用类型、定义类型、定义方法、引用方法、IL(Intermediate Language,中间语言)代码等。
[0006] 但是目前的智能卡由于体积和存储芯片的限制,其存储空间仍然有限,随着软件的发展,部分功能大的程序占用存储空间较大,对于很多的.net程序并不能进行存储和运行。
[0007] 综上所述,相关技术中的.net程序压缩效果较差,不能很好地在小容量的存储介质(例如:智能卡)上存储和运行,且针对该问题目前尚未提出有效的解决方案。

发明内容

[0008] 本发明旨在提供一种.net文件中定义类型的压缩方法和装置,能够解决.ne t程序压缩效果较差,不能很好地在小容量的存储介质(例如:智能卡)上存储和运行等问题。
[0009] 在本发明的实施例中,提供了一种.net文件中定义类型的压缩方法,所述方法包括:
[0010] 获取.net文件中使用的定义类型包含的信息;
[0011] 根据所述定义类型包含的信息获取所述定义类型的指定信息和计数信息;
[0012] 对所述指定信息进行压缩;
[0013] 将压缩后的指定信息和所述计数信息作为所述定义类型的压缩结果进行存储。
[0014] 本发明实施例还提供了一种.net文件中定义类型的压缩装置,所述装置包括:
[0015] 定义类型信息获取模块,用于获取.net文件中使用的定义类型包含的信息;根据所述定义类型包含的信息获取所述定义类型的指定信息和计数信息;
[0016] 压缩模块,用于对所述定义类型信息获取模块获取的指定信息进行压缩;
[0017] 压缩结果存储模块,用于将所述压缩模块压缩后的指定信息和所述定义类型信息获取模块获取的计数信息作为所述定义类型的压缩结果进行存储。
[0018] 本实施例采用对.net文件中的定义类型的各个部分进行压缩,并将各部分的压缩结果按照预先确定的格式存储,克服了.net文件占用的存储容量大的问题,进而使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。

附图说明

[0019] 此处所说明的附图用来提供对本发明的进一步理解,构成本申请的一部分,本发明的示意性实施例及其说明用于解释本发明,并不构成对本发明的不当限定。在附图中:
[0020] 图1示出了实施例1提供的.net文件中定义类型的压缩装置;
[0021] 图2示出了实施例2提供的.net文件中定义类型的压缩装置;
[0022] 图3示出了实施例3提供的.net文件中定义类型的压缩装置;
[0023] 图4示出了实施例4提供的.net文件中定义类型的压缩装置;
[0024] 图5示出了实施例5提供的.net文件中定义类型的压缩装置;
[0025] 图6示出了实施例6提供的.net文件中定义类型的压缩方法流程图;
[0026] 图7示出了实施例7提供的.net文件的结构示意图;
[0027] 图8示出了实施例7提供的.net文件中定义类型的压缩方法流程图。

具体实施方式

[0028] 下面将参考附图并结合实施例,来详细说明本发明。
[0029] 实施例1
[0030] 参见图1,本实施例提供了一种.net文件中定义类型的压缩装置,该装置包括:
[0031] 定义类型信息获取模块102,用于获取.net文件中使用的定义类型包含的信息;根据该定义类型包含的信息获取该定义类型的指定信息和计数信息;
[0032] 压缩模块104,用于对定义类型信息获取模块102获取的指定信息进行压缩;
[0033] 压缩结果存储模块106,用于将压缩模块104压缩后的指定信息和定义类型信息获取模块102获取的计数信息作为该定义类型的压缩结果进行存储。
[0034] 其中,定义类型信息获取模块102的具体实现可以是:先读取.net文件中的定义类型所在的元数据表,即元数据表TypeDef;再从元数据表TypeDef中获取.net文件中使用的定义类型包含的信息。
[0035] 本实施例中该定义类型包含的信息包括:该定义类型的标识、该定义类型的名称的偏移量、该定义类型中的方法的偏移量;
[0036] 当该定义类型中使用了字段时,该定义类型包含的信息中还可以包括该定义类型中的字段的偏移量;这些信息都可以通过读取元数据表TypeDef中的数据得到,在元数据表TypeDef中,每行数据表示一个定义类型,每行数据共14个字节,这14个字节记录的信息为:
[0037] 前4个字节为Flags(定义类型标识),5、6字节为定义类型名称在“#Strings”流中的偏移量,7、8字节为该定义类型所属的命名空间名称在.net文件里“#Strings”流中的偏移量,9、10字节为该定义类型的所继承的父类的偏移量,11、12字节为该定义类型包含的字段在元数据表Field表中的偏移量,13、14字节为该定义类型所包含的方法在元数据表Method表中的偏移量。
[0038] 根据本实施例中该定义类型包含的信息,上述指定信息包括:该定义类型的标识、该定义类型的名称,还可以包括该定义类型中的字段对应的信息;其中,该定义类型的名称可以根据上述该定义类型的名称的偏移量在.net文件对应的数据流中查找到,该定义类型的字段对应的信息也可以通过上述字段的偏移量在元数据表Field表中查找到;
[0039] 计数信息包括:该定义类型的方法重载信息、该定义类型中包含的方法计数和字段计数等。
[0040] 本实施例的压缩模块104对指定信息进行压缩时,可以根据压缩的具体对象选择压缩方法,例如:
[0041] 对定义类型的标识进行压缩时,可以先将定义类型的标识分为类型标识、访问标识和描述性标识;然后,将类型标识、访问标识和描述性标识进行或运算,得到的数据作为该定义类型的标识的压缩结果;
[0042] 对定义类型的名称进行压缩时,可以对定义类型的名称进行哈希运算,从运算结果中提取约定的字节作为该定义类型的名称的压缩结果;
[0043] 对定义类型中的字段对应的信息(字段的名称、字段的标识和字段的类型)进行压缩时,根据字段对应的信息内容分为以下三种情况:
[0044] 1)对上述字段的名称进行哈希运算,从运算结果中提取约定的字节作为该字段的名称的压缩结果;
[0045] 2)将上述字段的标识分为访问标识和描述性标识,对上述字段的标识中的访问标识和描述性标识进行或运算,得到的结果作为该字段的标识的压缩结果;
[0046] 3)将上述字段的类型在压缩后的类型中的偏移量作为该字段的类型的压缩结果。
[0047] 由上述内容可知,压缩后的定义类型中包括:定义类型名称的压缩结果、类型标识的压缩结果、类型中所包含的字段计数、方法计数、方法重载信息、类型中的字段对应的信息等。这些信息可以按照预先确定的格式排列,也可以任意排列。
[0048] 本实施例通过对.net文件中的定义类型的各个部分进行压缩,并将各部分的压缩结果按照预先确定的格式存储,可以有效地降低.net文件占用的存储空间,使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。
[0049] 实施例2
[0050] 参见图2,本实施例提供了一种.net文件中定义类型的压缩装置,该装置包括:
[0051] 定义类型信息获取模块102,用于获取.net文件中使用的定义类型包含的信息;根据该定义类型包含的信息获取该定义类型的指定信息和计数信息;
[0052] 其中,定义类型信息获取模块102的具体实现与实施例1相同,这里不再赘述,本实施例中该定义类型包含的信息包括:该定义类型的标识、该定义类型的名称的偏移量、该定义类型中的方法的偏移量和定义类型所继承的父类的偏移量;该定义类型包含的信息中还可以包括该定义类型中的字段的偏移量;
[0053] 指定信息包括:该定义类型的标识、该定义类型的名称,还可以包括该定义类型中的字段对应的信息;计数信息包括:该定义类型的方法重载信息、该定义类型中包含的方法计数和字段计数等。
[0054] 压缩模块104,用于对定义类型信息获取模块102获取的指定信息进行压缩;
[0055] 第一判断模块105,用于判断定义类型信息获取模块102中的定义类型所继承的父类是否已压缩;
[0056] 父类偏移量获取模块107,用于当第一判断模块105判断的结果是继承的父类已压缩,获取继承的父类的偏移量;如果继承的父类没有压缩,对继承的父类进行压缩,并为压缩后的父类分配偏移量;
[0057] 压缩结果存储模块106,用于将压缩模块104压缩后的指定信息、定义类型信息获取模块102获取的计数信息和父类偏移量获取模块107获取的继承的父类偏移量作为该定义类型的压缩结果进行存储。
[0058] 本实施例中的压缩模块104对指定信息进行压缩时的具体实现方法可以和实施例1中的方法相同,这里不再详述。
[0059] 本实施例中当前定义类型所继承的父类的类型可能为引用类型,该引用类型存储于元数据表TypeRef中,此时,可以从该元数据表TypeRef中直接查到所继承的父类的偏移量;或者,当前定义类型所继承的父类的类型可能也为定义类型,此时,需要先判断所继承的父类是否压缩,如果没有压缩,则先压缩再分配一个偏移量,如果已经压缩,则直接获取其偏移量。
[0060] 由上述内容可知,本实施例压缩后的定义类型中包括:定义类型名称的压缩结果、类型标识的压缩结果、类型中所包含的字段计数、类型中方法重载信息、继承的父类偏移量、类型中字段的信息等。这些信息可以按照预先确定的格式排列,也可以任意排列。
[0061] 本实施例通过对.net文件中的定义类型的各个部分进行压缩,并将各部分的压缩结果按照预先确定的格式存储,可以有效地降低.net文件占用的存储空间,使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。
[0062] 实施例3
[0063] 参见图3,本实施例提供了一种.net文件中定义类型的压缩装置,该装置包括:定义类型信息获取模块102、压缩模块104、第二判断模块108、接口信息获取模块109和压缩结果存储模块106;其中,定义类型信息获取模块102和压缩模块104的功能和实施例1、实施例2中对应模块的功能相同,这里不再赘述;
[0064] 第二判断模块108,用于判断定义类型信息获取模块102中的定义类型是否有继承的接口;
[0065] 接口信息获取模块109,用于当第二判断模块108判断的结果是该定义类型有继承的接口,获取该定义类型继承的接口压缩后的偏移量和继承的接口的个数;
[0066] 压缩结果存储模块106,用于将压缩模块104压缩后的指定信息、定义类型信息获取模块102获取的计数信息、接口信息获取模块109获取的继承的接口的偏移量和继承的接口的个数作为该定义类型的压缩结果进行存储。
[0067] 由上述内容可知,本实施例压缩后的定义类型中包括:定义类型名称的压缩结果、类型标识的压缩结果、类型所继承的接口计数、类型中所包含的字段计数、类型中方法重载信息、类型所继承的接口压缩后的偏移、类型中字段的信息等。这些信息可以按照预先确定的格式排列,也可以任意排列。
[0068] 本实施例通过对.net文件中的定义类型的各个部分进行压缩,并将各部分的压缩结果按照预先确定的格式存储,可以有效地降低.net文件占用的存储空间,使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。
[0069] 实施例4
[0070] 参见图4,本实施例提供了一种.net文件中定义类型的压缩装置,该装置包括:定义类型信息获取模块102、压缩模块104、第三判断模块110、偏移量获取模块111和压缩结果存储模块106;其中,定义类型信息获取模块102和压缩模块104的功能和实施例1、实施例2中对应模块的功能相同,这里不再赘述;
[0071] 第三判断模块110,用于判断定义类型信息获取模块102中的定义类型是否是嵌套类型;
[0072] 偏移量获取模块111,用于当第三判断模块110判断的结果为该定义类型是嵌套类型时,获取该嵌套类型所在的类型压缩后的偏移量;
[0073] 压缩结果存储模块106,用于将压缩模块104压缩后的指定信息、定义类型信息获取模块102获取的计数信息、偏移量获取模块111获取的该定义类型所在的类型压缩后的偏移量作为该定义类型的压缩结果进行存储。
[0074] 由上述内容可知,本实施例压缩后的定义类型中包括:定义类型名称的压缩结果、类型标识的压缩结果、类型中所包含的字段计数、类型中方法重载信息、嵌套类型所在的类型的偏移量、类型中字段的信息等。这些信息可以按照预先确定的格式排列,也可以任意排列。
[0075] 本实施例通过对.net文件中的定义类型的各个部分进行压缩,并将各部分的压缩结果按照预先确定的格式存储,可以有效地降低.net文件占用的存储空间,使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。
[0076] 实施例5
[0077] 参见图5,本实施例提供了一种.net文件中定义类型的压缩装置,该装置包括实施例1-4中的各个模块,其中,定义类型信息获取模块102、压缩模块104、第一判断模块105、父类偏移量获取模块107、第二判断模块108、接口信息获取模块109、第三判断模块
110、偏移量获取模块111的功能与上述实施例中对应模块的功能相同,这里不再详述;
[0078] 压缩结果存储模块106,用于将压缩模块104压缩后的指定信息、定义类型信息获取模块102获取的计数信息、父类偏移量获取模块107获取的继承的父类压缩后的偏移量、接口信息获取模块109获取的继承的接口压缩后的偏移量和继承的接口的个数、偏移量获取模块111获取该定义类型所在的类型压缩后的偏移量作为该定义类型的压缩结果进行存储。
[0079] 由上述内容可知,本实施例压缩后的定义类型中包括:定义类型名称的压缩结果、类型标识的压缩结果、类型中所包含的字段计数、类型中方法重载信息、继承的父类偏移量、继承的接口的偏移量、继承的接口的个数、定义类型所在的类型压缩后的偏移量、类型中字段的信息等。这些信息可以按照预先确定的格式排列,也可以任意排列。
[0080] 本实施例通过对.net文件中的定义类型的各个部分进行压缩,并将各部分的压缩结果按照预先确定的格式存储,可以有效地降低.net文件占用的存储空间,使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。
[0081] 实施例6
[0082] 参见图6,本实施例提供了一种.net文件中定义类型的压缩方法,该方法以通过实施例1通过的压缩装置实现为例进行说明,该方法包括:
[0083] 步骤S202:定义类型信息获取模块102获取.net文件中使用的定义类型包含的信息;
[0084] 步骤S204:定义类型信息获取模块102根据该定义类型包含的信息获取该定义类型的指定信息和计数信息;
[0085] 步骤S206:压缩模块104对上述指定信息进行压缩;
[0086] 步骤S208:压缩结果存储模块106将压缩后的指定信息和计数信息作为该定义类型的压缩结果进行存储。
[0087] 其中,定义类型信息获取模块102获取的定义类型包含的信息是通过如下方式得到的:
[0088] 先读取.net文件中的定义类型元数据表,即元数据表TypeDef;再从元数据表TypeDef中获取.net文件中使用的定义类型包含的信息。
[0089] 本实施例中该定义类型包含的信息包括:该定义类型的标识、该定义类型的名称的偏移量、该定义类型中的方法的偏移量;
[0090] 当该定义类型中使用了字段时,该定义类型包含的信息中还可以包括该定义类型中的字段的偏移量;这些信息都可以通过读取元数据表TypeDef中的数据得到,在元数据表TypeDef中,每行数据表示一个定义类型,每行数据共14个字节,这14个字节记录的信息为:
[0091] 前4个字节为Flags(定义类型标识),5、6字节为定义类型名称在“#Strings”流中的偏移量,7、8字节为该定义类型所属的命名空间名称在.net文件里“#Strings”流中的偏移量,9、10字节为该定义类型的所继承的父类的偏移量,11、12字节为该定义类型包含的字段的偏移量,13、14字节为该定义类型所包含的方法的偏移量。
[0092] 上述指定信息和计数信息与实施例1中对应的信息相同,这里不再详述。
[0093] 优选地,本实施例中将定义类型的标识分为类型标识、访问标识和描述性标识;
[0094] 相应地,步骤S206中的压缩模块104对上述指定信息进行压缩的步骤包括:
[0095] 对所述类型标识、访问标识和描述性标识进行或运算,将得到的数据作为定义类型的标识的压缩结果;对所述定义类型的名称进行哈希运算,从运算结果中提取约定的字节作为定义类型的名称的压缩结果。
[0096] 当该.net文件中的当前定义类型中包含字段时,该定义类型包含的信息还包括:该定义类型中的字段的偏移量;
[0097] 相应地,上述指定信息还包括:该定义类型中的字段对应的信息;计数信息还包括:该定义类型的字段计数。
[0098] 优选地,本实施例中的字段对应的信息包括:字段的名称、字段的标识和字段的类型;其中,所述字段的标识分为访问标识和描述性标识;
[0099] 相应地,步骤S206中的压缩模块104对上述指定信息进行压缩的步骤包括:
[0100] 对该字段的名称进行哈希运算,从运算结果中提取约定的字节作为该字段的名称的压缩结果;对该字段的标识中的访问标识和描述性标识进行或运算,得到的结果作为该字段的标识的压缩结果;将该字段的类型在压缩后的类型中的偏移量作为该字段的类型的压缩结果。
[0101] 优选地,定义类型包含的信息包括:该定义类型所继承的父类的偏移量;相应地,上述方法还包括:
[0102] 判断该定义类型所继承的父类是否已压缩,如果是,获取所继承的父类的偏移量;否则,对所继承的父类进行压缩并为压缩后的所继承的父类分配偏移量;相应地,上述定义类型的压缩结果中还包括压缩后的所述父类的偏移量。
[0103] 优选地,上述方法还包括:
[0104] 判断该定义类型是否有继承的接口;如果有,获取该定义类型所继承的接口压缩后的偏移量和继承的接口的个数;相应地,该定义类型的压缩结果中还包括上述继承的接口压缩后的偏移量和继承的接口的个数。
[0105] 优选地,上述方法还包括:
[0106] 判断该定义类型是否是嵌套类型,如果是,获取该定义类型所在的类型压缩后的偏移量;相应地,该定义类型的压缩结果中还包括上述定义类型所在的类型压缩后的偏移量。
[0107] 通过上述方法,对每个定义类型压缩后的数据进行组织,其格式为:定义类型名称的hash值(定义类型名称的压缩结果)、类型标识的压缩结果、类型所继承的接口计数、类型父类的偏移量、类型中所包含的字段计数、类型中方法重载信息、定义类型所在类型压缩后的偏移量、类型所继承接口压缩后的偏移量、类型中字段对应的信息等;
[0108] 其中,类型所继承的接口压缩后的偏移量、类型中字段对应的信息可以有多条,当有多条时,依次排列当前定义类型所继承的接口偏移量、字段对应的信息;另外,定义类型所在类型压缩后的偏移量、类型所继承接口压缩后的偏移量、类型中字段对应的信息这三者中可能部分存在或都不存在,此时,该定义类型中不写入这些信息。
[0109] 本实施例通过对.net文件中的定义类型的各个部分进行压缩,并将各部分的压缩结果按照预先确定的格式存储,可以有效地降低.net文件占用的存储空间,使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。
[0110] 实施例7
[0111] 本实施例提供了一种.net文件中定义类型的压缩方法,该压缩方法以一个具体应用实例为例进行说明,在此应用实例中,涉及到.net文件中的引用类型的压缩及存储的部分,本实例中引用类型的压缩结果为已知的内容,可以直接使用。
[0112] 本实施例以将下面的代码编译后的文件为例,说明.net文件中定义类型的压缩方法。部分代码如下:
[0113] namespace MyCompany.MyOnCardApp
[0114] {
[0115] public class MyService:MarshalByRefObject
[0116] {
[0117] public String MySampleMethod()
[0118] {
[0119] String strHello=″Hello World!″;
[0120] return strHello+callCount.ToString();
[0121] }
[0122] }
[0123] public class ClassA
[0124] {
[0125] public class ClassC:ClassB,IA,IB
[0126] {
[0127] static String strField;
[0128] Int32 iField;
[0129] public ClassC(String str 1,int i)[0130] {
[0131] strField=str1;
[0132] iField=i;
[0133] }
[0134] public String TestC()
[0135] {
[0136] return null;
[0137] }
[0138] }
[0139] private struct StructB
[0140] { }
[0141] }
[0142] public class ClassB
[0143] { }
[0144] public interface IA
[0145] { }
[0146] public interface IB
[0147] { }
[0148] }
[0149] 对上述代码使用.net平台编译后得到helloworld.exe文件,并以二进制的形式存储在硬盘上,该二进制文件为.net文件,.net文件可以运行在Windows环境下并且符合PE(Portable Executable,可移植可执行)文件格式,PE格式是Windows的可执行文件的格式,Windows中的.exe文件、.dll文件都是PE格式。参见图7,为.net文件的结构示意图,该文件包括Dos头、PE特征以及元数据(MetaData),元数据中包括元数据头(MetaData Header)、元数据表(MetaData Tables)等。
[0150] 参见图8,本实施例提供的.net文件中定义类型的压缩方法包括:
[0151] 步骤S301:定位.net文件中的元数据表(Metadata Tables)的起始地址,并获取现存表位向量;其中,元数据表为.net文件的一部分,定位元数据表的过程如下:
[0152] 1)定位.net文件Dos头,得到Dos头标识0x5a4d;
[0153] 2)从Dos头标识后开始跳过第一约定个字节,读出PE特征的偏移地址,得到PE特征的偏移地址0x00000080;在本实施例中,第一约定个字节为0x003a个字节;
[0154] 3)根据PE特征偏移地址0x00000080定位PE特征,定位得到PE特征0x00004550;
[0155] 4)从PE特征后开始,偏移第二约定个字节后读取四个字节,在本实施例中,以32位机为例进行说明,第二约定个字节为从PE特征处向后偏移0x0074字节后,读出的数据为0x00000010,此值说明该二进制文件中存在0x10个目录,且包含.net数据;
[0156] 其中,.net文件的元数据头地址写在上述第0x0F个目录中;
[0157] 若是在64位机中,则第二约定个字节为0x0084个字节;
[0158] 5)从上述数据0x00000010开始,向后偏移第三约定个字节读取八个字节数据,在本实施例中,优选地,第三约定个字节为0x0070个字节,在此八个字节数据中,前四个字节为0x00002008,为.net文件中.net数据头的相对虚拟地址,后四个字节为0x00000048,为.net数据头的长度;
[0159] 6)根据.net文件中.net数据头的相对虚拟地址0x00002008得到线性地址0x00000208并读取.net数据头得到如下数据:
[0160] 48000000 02000500 0C220000 9C0A0000
[0161] 09000000 01000006 00000000 00000000
[0162] 50200000 80000000 00000000 00000000
[0163] 00000000 00000000 00000000 00000000
[0164] 00000000 00000000
[0165] 需要说明的是,上述数据采用小端的存储方式,例如,上述数据前4个字节0x48000000转换成大端的存储方式为0x0000048,表示该数据的长度;
[0166] 其中,根据.net元数据头的长度0x00000048读取72个字节的数据。
[0167] 在本实施例中,线性地址为.net数据在.net文件中的地址,相对虚拟地址为相对于PE载入点的内存偏移,线性地址和相对虚拟地址的转换关系为:线性地址=相对虚拟地址-节相对虚拟地址+节的文件偏移,在本实施例中,读取.net文件中.net数据目录的节的相对虚拟地址为0x00002000,节的文件偏移为0x00000200,则线性地址=0x00002008-0x00002000+0x00000200=0x00000208;
[0168] 7)由.net数据头开始向后偏移第四约定个字节后,在本实施例中第四约定个字节为从.net数据头开始向后偏移8个字节后,读取共8个字节数据,在这8个字节中,前四个字节为0x0000220c,为元数据头(MetaData Header)的相对虚拟地址,后四个字节为0x00000a9c,为元数据的长度;
[0169] 8)根据元数据头的相对虚拟地址0x0000220c得到线性地址0x0000040c,根据线性地址和元数据长度读取元数据内容;
[0170] 9)由元数据头向后读取,当读取到标志“#~”(0x237E)时,读取标志“#~”之前的八个字节,其中前四个字节为“#~”流数据相对元数据头的偏移,后四个字节为“#~”流的长度;通过“#~”流的相对偏移得到“#~”流的数据区域,在“#~”流中第五约定个字节开始读取长度为8个字节的数据,得到现存表的位向量(MaskValid)在本实施例中,现存表的位向量值为0x0000020920021f57,其二进制形式为:
[0171] 100000100100100000000000100001111101010111
[0172] 在本实施例中,第五约定个字节为“#~”流中起始位开始算起第9个字节;
[0173] 从低位开始读取现存表的位向量,每一位代表一个元数据表,若该表存在,则相应位上的值为1,否则为0;
[0174] 例如,从低位开始,第1位代表元数据表Module是否存在,如果是1,则证明存在元数据表Module,如果是0,证明不存在,在本实施例中,存在元数据表Module,并且第2位为1,表示元数据表TypeRef存在,第3位为1,表示元数据表TypeDef存在;
[0175] 步骤S302:定位元数据表TypeDef(定义类型);
[0176] 根据步骤S301中读取出的现存表的位向量,从低位到高位依次记录了.net文件中对应的元数据表是否存在,其中,第3位代表元数据表TypeDef是否存在,如果第3位为1,则元数据表TypeDef存在,如果第3位为0,则元数据表TypeDef不存在,在本实施例中,元数据表TypeDef存在;
[0177] 在现存表位向量0x0000020920021f57之后的第9个字节开始,以四个字节为一个单位对应的记录了.net文件中存在的元数据表中所包含的数据行数,跳过在TypeDef前面的两个元数据表数据行数信息,在数据0x0000020920021f57后的第17个字节处开始读取4个字节,得到数据0x0000000a,此数据表示元数据表TypeDef中有10个数据行;
[0178] 在表示数据行数的数据后,依次存储了每个元数据表的具体内容,为元数据表区域;读取元数据表TypeDef中内容的过程如下:
[0179] 根据步骤S301中读取的现存表的位向量可知,在本发明实施例中元数据表TypeDef前存在元数据表Module和元数据表TypeRef,其中元数据表Module有1个数据行、10个字节,元数据表TypeRef有31个数据行、186个字节,跳过表示元数据表中所包含的数据行个数的60个字节数据后,再跳过元数据表Module和元数据表TypeRef后读取元数据表TypeDef的10个数据行、每个数据行有14个字节,具体数据如下:
[0180] 0x0000000001000000000001000100
[0181] 0x0100100019002200050001000100
[0182] 0x0100100038002200090002000300
[0183] 0x0100100042002200050007000600
[0184] 0x0100100049002200050007000700
[0185] 0xA100000050002200000007000800
[0186] 0xA100000053002200000007000800
[0187] 0x0200100056000000140007000800
[0188] 0x030110005D0000000D0009000A00
[0189] 0x00000000C8030000050009000A00
[0190] 在元数据表TypeDef中,每个数据行中的数据代表一个定义类型,每个数据行的前4个字节为Flags(定义类型标识),5、6字节为定义类型名称在.net文件里“#Strings”流中的相对偏移,7、8字节为该定义类型所属的命名空间名称在“#Strings”流中的相对偏移,9、10字节为该定义类型的所继承的父类的信息,11、12字节为该定义类型包含的第一个字段在元数据表Field中的数据行号,13、14字节为该定义类型所包含的第一个方法在元数据表Method中的数据行号。
[0191] 在本实施例中,每一个元数据表中每一个数据行中数据的长度是固定的,根据现存表位向量及元数据表行数通过上述定位元数据表的方法可计算出其它元数据表在.net文件中的偏移地址。
[0192] 步骤S303:根据该元数据表TypeDef中的数据读取定义类型的标识和名称,并分别对定义类型的标识和名称进行压缩;
[0193] 首先,根据读取到元数据表TypeDef中的数据,读取定义类型的标识并进行压缩;
[0194] 从元数据表TypeDef中读取四个字节的定义类型的标识,根据该定义类型的标识可知该定义类型的各项标识属性;
[0195] 本实施例将定义类型的标识分为3部分:类型标识、访问标识、描述性标识,并重新定义了各项标识属性的值,如类型标识包括:预定义类型0x00、值类型0x01、枚举类型0x02、数组类型0x03、类类型0x04、接口类型0x05、非托管指针类型0x06等;访问标识包括:非公共访问类型NotPublic(0x00)、公共访问类型Public(0x10)、如果为嵌套类型的话还有:访问修饰标识公共嵌套类型NestedPublic(0x20)、私有嵌套类型NestedPrivate(0x30)、家族嵌套类型NestedFamily(0x40)、程序集嵌套类型NestedAssembly(0x50)、程序集与家族嵌套类型NestedFamANDAssem(0x60)、程序集或家族嵌套类型NestedFamORAssem(0x70);描述性标识用于描述当前类型中字段的一些属性,如存在不可序列化的字段0x08,否则为0x00;
[0196] 本实施例对定义类型的标识进行压缩的方法具体为:将类型标识、访问标识及描述性标识进行或运算,得到的1个字节的数据即为定义类型的标识压缩结果。
[0197] 例如,在步骤S302中读取出的元数据表TypeDef的第8个数据行的定义类型ClassC,根据前4个字节的定义类型标识0x00100002可知,其类型标识为类0x04、访问修饰标识为NestedPublic(0x20)、描述性标识为0x00,将以上属性的值进或运算0x04|0x20|0x00得到0x24,将0x24作为定义类型ClassC的标识压缩结果。
[0198] 然后,根据读取到的元数据表TypeDef中的数据,读取定义类型名称并进行压缩;即根据定义类型名称在“#Strings”流中的相对偏移读取出该定义类型的名称;
[0199] 例如,读取出的元数据表TypeDef中第二个数据行数据中,第5、6个字节中的值为0x0019,定位到.net文件的“#Strings”流后跳过0x0019个字节后开始读取数据,读到0x00后结束,得到0x4D79536572766572,该数据即元数据表TypeDef中当前定义类型的名称MyServer;
[0200] 对读取出的定义类型名称进行哈希(hash)运算,从hash运算结果中取第六约定个字节作为定义类型压缩后的结果,在本发明实施例中第六约定字节为hash值的前两个字节。采用的hash算法可以是MD5、SHA-1、SHA-2等。
[0201] 例如,在本发明实施例中采用MD5算法对MyServer进行hash运算,得到:0x0CBEFBC1EF0639BA18485104440F399C,取第六约定个字节0x0CBE作为元数据表TypeDef中当前定义类型MyServer名称的压缩结果。
[0202] 另外,如果根据当前类型的标识判断出当前类型为嵌套类型,则再读取出当前类型所在类型的名称,对当前类型所在类型的名称与当前类型的名称组合进行hash运算,从hash运算结果中取第六约定个字节作为该当前类型的压缩结果;组合的方法可以是使用连接符将二者拼接到一起,或直接对这两个类型进行拼接,或两个类型的名称进行相加、相减、异或等数学运算。
[0203] 例如,以本实施例中所给的代码为例:类型ClassC嵌套在类型ClassA中,因此对ClassC进行压缩时,先将ClassA的类型名称与ClassC的类型名称进行拼接,在本实施例中使用连接符“+”进行拼接,对ClassA+ClassC进行hash运算,然后取hash值的前两个字节作为ClassC的类型名称压缩结果,这样可以避免定义类型名称的压缩结果出现重复的情况;
[0204] 其中,读取出ClassA的名称为0x0042,ClassC的名称为0x0056,对ClassA+ClassC使用MD5算法进行hash运算,得到:0x9B8DE23910B330AD80BDB76E7AC19092,取前两个字节0x9B8D作为元数据表TypeDef中当前定义类型ClassC名称的压缩结果。
[0205] 其中,本实施例在元数据中定位“#Strings”流的位置的方法为:在步骤S301中的获得元数据头的地址0x0000040c后,从元数据头开始向后读取,当发现标记“#Strings”(0x23537472696E6773)后,读取“#Strings”之前的8个字节数据,得到数据0x0004000080040000,其中高位4个字节转换成大端的表示方式为0x00000400,表示“#Strings”流相对于元数据头的偏移,低位4个字节转换成大端的表示方式为0x00000480,表示“#Strings”流的长度,,低4个字节;从元数据头的地址0x0000040c,向后偏移0x00000400个字节得到“#Strings”流的数据区域。
[0206] 步骤S304:获取当前定义类型中的方法重载信息,以及获取当前定义类型中所包含的方法的方法计数和字段计数;
[0207] 本实施例中方法计数的获取方法如下:
[0208] 读取元数据表TypeDef中当前定义类型所在数据行的13、14字节中的数据,该数据为定义类型所包含第一个方法在元数据表Method中的数据行号,然后再读取当前定义类型的下一个定义类型所包含第一个方法在元数据表Method中的数据行号,下一个定义类型所包含的第一个方法的数据行号减去当前定义类型所包含的第一个方法的数据行号,所得到的结果即为当前类型中所包含的所有方法计数。元数据表TypeDef中最后一个数据行所包含的所有方法计数的获取方法为:元数据表Method中的数据行数减去最后一个定义类型数据行所包含的第一个方法的数据行号,得到的结果即为元数据表TypeDef中最后一个数据行所包含的所有方法计数。
[0209] 本实施例中读取到的元数据表TypeDef中定义类型ClassC所包含的第一个方法在元数据表Method中的数据行号为0x0008,定义类型ClassC的下一个数据行中定义类型StructB所包含的第一个方法在元数据表Method中的数据行号为0x000A,由0x000A-0x0008可知,定义类型ClassC中包含的方法数是0x0002个。
[0210] 定义类型的方法重载信息用于描述当前类型中是否存在方法是虚方法、且需要开辟新的存储槽,如果存在,则将该方法重载信息加1,其中,每个定义类型方法重载信息的初值为0。
[0211] 首先,定位元数据表Method(方法);具体的方法类似步骤S302中定位元数据表TypeDef的过程,简单描述如下:
[0212] 根据步骤S301中读取出的现存表的位向量,从低位到高位依次记录了.net文件中对应的元数据表是否存在,其中,第7位代表元数据表Method是否存在,在本实施例中,第7位的数据为1,元数据表Method存在;
[0213] 在现存表位向量0x0000020920021f57之后的第9个字节开始,以四个字节为一个单位对应的记录了.net文件中存在的元数据表中所包含的数据行个数,根据现存表位向量可知在元数据表Method之前还存在其它4个元数据表,跳过在Method前面的4个元数据表,在数据0x0000020920021f57后的第25个字节处开始读取4个字节,得到数据0x00000009,此数据表示元数据表Method中有9个数据行;
[0214] 读取得到元数据表Method的内容:根据现存表的位向量以及其后表示元数据表行数的数据可知,在本实施例中元数据表Method之前存在元数据表Module有10个字节、元数据表TypeRef有186个字节、元数据表TypeDef有140个字节和元数据表Field有54个字节,跳过前面的3个元数据表后,读取元数据表Method的9个数据行、共126个字节。
[0215] 然后,根据当前定义类型所包含第一个方法在元数据表Method中的数据行号从元数据表Method中读取相应数据行的数据,元数据表Method中每一个数据行的第7、8个字节是方法标识,根据该方法标识判断当前类型中的方法是否是虚方法、且需要开辟新的存储槽,如果是,则方法重载信息加1;若当前定义类型的方法计数大于1,则继续在元数据表Method中读取下一个数据行,根据上述方法执行操作。直至将当前定义类型所包含的方法全部读取并判断完毕;
[0216] 具体地,判断当前类型中的方法是否是虚方法、且需要开辟新的存储槽的方法为:读取当前类型中方法的标识,将该标识与0x0100进行与运算,若运算的结果为0x0100则可以判断出当前类型中的方法是虚方法、且需要开辟新的存储槽。
[0217] 获取当前定义类型中所包含的字段计数与获取当前类型中所包含方法计数的方法类似,简单描述如下:
[0218] 读取元数据表TypeDef中当前定义类型所在行的第11、12字节存储的数据,得到当前定义类型所包含的第一个字段在元数据表Field中的数据行号,然后读取下一数据行中的第11、12字节所存储的当前定义类型的下一个定义类型包含的第一个字段在元数据表Field中的数据行号,后者的数据行号减去前者的数据行号所得到的结果即为当前类型中所包含的字段计数。
[0219] 本实施例中读取到的元数据表TypeDef中定义类型ClassC所包含的第一个字段在元数据表Field中的数据行号为0x0007,定义类型ClassC的下一个定义类型StructB所包含的第一个字段数据行号为0x0009,由0x0009-0x0007可知,当前定义类型ClassC中所包含的字段个数是0x0002个,即定义类型ClassC的字段计数为0x0002。
[0220] 步骤S305:获取当前定义类型中的字段对应的信息并压缩。
[0221] 根据现存表位向量在元数据表Field中读取相应的字段的数据,并根据所获取的当前定义类型所包含字段计数和字段序号,读取元数据表Field的方法与步骤S302类似;元数据表Field中每个数据行的长度为6个字节;其中第1、2个字节存储的是元数据表Field中该数据行中字段的Flags(字段标识),第3、4个字节存储的是字段的name(字段名),第5、6个字节存储的是字段的Signature信息。
[0222] 对当前定义类型中的字段对应的信息进行压缩的过程如下:
[0223] 1)获取字段名并对其进行压缩
[0224] 对读取到的字段的name(字段名)进行hash运算,取hash值中第七约定个字节作为该字段name(字段名)的压缩结果,在本实施例中第七约定个字节为hash值的前两个字节;
[0225] 在本实施例中ClassC中包含两个字段,name(字段名)分别为strField和iField,以对字段strField的字段名“strField”进行压缩为例,压缩后得到的hash值为:0x846461722F82E1CAB3D95632E8424089,取hash值的前两个字节0x8464作为该字段名“strField”的压缩结果。
[0226] 2)对字段的标识进行压缩
[0227] 根据在元数据表Field中读取到的字段的Flags(字段标识),根据该字段的Flags可以判断出该字段的标识信息,本实施例中将字段的标识信息分为两类:访问标识和描述性标识;对该字段的访问标识和描述性标识的值进行或运算,得到该字段Flags的压缩结果;
[0228] 其中,访问标识包括:
[0229] 私有范围类型 PrivateScope=0x00
[0230] 私有类型 Private=0x01
[0231] 家族与程序集类型 FamANDAssem=0x02
[0232] 程序集类型 Assembly=0x03
[0233] 家族类型 Family=0x04
[0234] 家族或程序集类型 FamORAssem=0x05
[0235] 公共类型 Public=0x06
[0236] 描述性标识有:
[0237] 静态类型 Static=0x10
[0238] 初始化 InitOnly=0x20
[0239] 不可序列化 NotSerialized=0x80
[0240] 在本实施例中,定义类型ClassC中包含两个字段分别为strField和iField,对strField字段标识进行压缩时分析其Flags(字段标识)可知,该字段的访问标识为Private=0x01,描述性标识为Static=0x10,0x01与0x10进行或运算得到0x11,则strField字段的标识压缩结果为0x11。
[0241] 3)获取字段的类型
[0242] 字段的类型存储在“#Blob”流中,读取元数据表Field中当前行第4个字节的Signature信息,该信息为该字段类型信息在“#Blob”流中的相对偏移地址,根据该相对偏移地址在“#Blob”流中读取相应的数据;其中,读取到的第一字节的数据表示其后的数据长度,第2字节表示数据的类型,若第2字节为0x06,则表示该数据为字段的类型,第3字节数据表示字段类型、或者是在第4字节中包含字段类型信息;根据第3字节所示的字段类型查找元数据表中与之相对应的类型、或者解析第4字节中包含字段类型信息得到该字段在元数据表中对应的类型,并将元数据表中该类型压缩后的偏移作为该字段的类型进行保存。
[0243] 其中,定位“#Blob”流位置的方法与步骤S302中在元数据中定位“#Strings”流的位置的方法类似:在步骤S301中的获得元数据头的地址0x0000040c后,从元数据头开始向后读取,当发现标记“#Blob”(0x23426C6F6)后,读取“#Blob”之前的8个字节数据,得到数据0xD4080000C8010000,其中高4个字节转换成大端的表示方式为0x000008D4,表示“#Blob”流相对于元数据头的偏移,低4个字节转换成大端的表示方式为0x0001C8,表示“#Blob”流的长度,;从元数据头的地址0x0000040c,向后偏移0x000008D4得到“#Blob”流的数据区域。
[0244] 在本实施例中,获取定义类型ClassC中所包含的字段strField的字段类型的方法如下:在元数据表Field中读取strField的第4个字节的数据得到0x000A,然后在“#Blob”流的数据区域中的偏移0x000A处读取数据,读取到第1字节的数据0x02,表示在该数据后需要读取2个字节长度的数据,得到0x060E,其中第2个字节为0x06,表示的是该字节后的数据表示的是字段类型,继续读取第3个字节得到数据0x0E,根据语言规范可知0x0E表示该字段类型为string类型,查找元数据表TypeRef中string类型压缩后的偏移,查找得到的结果为0x03,将0x03作字段strField的字段类型进行保存。
[0245] 本实施例定义类型压缩后的字段对应的信息中包含3个部分:2个字节长度的name(字段名)压缩值、1个字节的Flags(字段标识)压缩值和1个字节的Signature信息压缩值;若当前类型中包含有多个字段,则将每个字段压缩后顺序保存。
[0246] 根据上述所示的方法,ClassC中所包含的字段strField和iField的信息压缩后的结果为:0x84641103F1EC0106。
[0247] 若当前定义类型中不存在定义字段,则压缩后的定义类型中不存在此项。
[0248] 步骤S306:判断当前定义类型是否存在父类,若存在父类且其父类未压缩,则执行步骤303,通过递归的方法压缩当前类的父类;否则执行步骤307;
[0249] 从元数据表TypeDef中当前类型所在数据行的第9、10字节读取数据;
[0250] 若读取到的数据为0x0000,则当前类型没有父类,执行步骤S307;若从元数据表TypeDef中当前类型所在数据行的第9、10字节读取到的数据不是0x0000,则将读取到的以小端存储方式保存的数据转换成大端存储的格式,即转换后是高字节在前、低字节在后的形式,然后将转换后数据的二进制数右移两位,得到当前类型的父类在元数据表TypeRef或TypeDef中的数据行号;移位后得到的数据行号与0x03进行与运算,若运算结果为0,则当前类型的父类在元数据表TypeRef中,执行步骤S307;若运算结果为1,则可知当前类型的父类在元数据表TypeDef中,查找元数据表TypeDef中与该数据行号相对应数据行的类型,如果已经压缩,执行步骤S307,否则,执行步骤S303。
[0251] 步骤S307:获取定义类型所继承的父类的类型压缩后的偏移量;
[0252] 从元数据表TypeDef中当前类型所在数据行的第9、10字节读取数据,若读取到的数据为0x0000,则当前类型没有父类,保存0xFF表示当前类型没有父类型;
[0253] 若从元数据表TypeDef中当前类型所在数据行的第9、10字节读取到的数据不是0x0000,则将读取到的以小端存储方式保存的数据转换成大端存储的格式,即转换后是高字节在前、低字节在后的形式,然后将转换后数据的二进制数右移两位,得到当前类型的父类在元数据表TypeRef或TypeDef中的数据行号;
[0254] 移位后得到的数据行号与0x03进行与运算,若运算结果为0,则当前类型的父类在元数据表TypeRef中,查找元数据表TypeRef中与该数据行号相对应数据行的类型压缩后的偏移,并将其作为当前类型的父类的偏移存储下来;若运算结果为1,则可知当前类型的父类在元数据表TypeDef中,查找元数据表TypeDef中与该数据行号相对应数据行的类型压缩后的偏移,并将其作为当前类型的父类的偏移存储下来。
[0255] 例如,在本实施例中ClassC的父类的获取过程如下:读取元数据表TypeDef中ClassC所在数据行的第9、10字节,得到数据转换为大端存储格式后为0x0014,转换成二进制为:10100,对二进制数10100右移2位得到101即0x05,由于0x05与0x03进行与运算后的结果为0x01,可知ClassC的父类在元数据表TypeDef中第0x05个数据行,然后查找元数据表TypeDef中第0x05个数据行的定义类型压缩后的偏移,并将其作为ClassC父类的偏移存储下来。
[0256] 步骤S308:为当前定义类型分配偏移量;
[0257] 按照以上步骤所述的方法对每个定义类型进行压缩后,获取.net文件中元数据表TypeRef(引用类型)的压缩信息,继续引用类型压缩后的偏移量连续地为定义类型分配偏移量。例如:若.net文件中引用类型压缩后的最后一个类型的偏移量为0x1A,则压缩后定义类型中第一个类型的偏移量为0x1B,压缩后第二个定义类型的偏移为0x1C。
[0258] 步骤S309:判断是否有等待父类偏移量的定义类型在缓存中,若有,则执行步骤S307,否则执行步骤S310;
[0259] 步骤S310:判断是否所有定义类型的数据分析完毕,若是则执行步骤S311,否则,执行步骤S303,继续压缩元数据表TypeDef中其余的定义类型;
[0260] 步骤S311:获取当前定义类型所继承的接口偏移量及继承的接口数;
[0261] 当所有定义类型的数据都经过上述处理之后,可以通过查询元数据表InterfaceImpl中的数据得到每个定义类型所继承的接口偏移量和所继承的接口数;
[0262] 根据现存表位向量定位元数据表InterfaceImpl(接口类),具体读取元数据表的方法与步骤S302类似;读取元数据表InterfaceImpl。
[0263] 在元数据表InterfaceImpl中,每行有4个字节,第1、2字节Class表示继承该接口的类型在元数据表TypeDef中所在的数据行,第3、4字节Interface中的值转换成二进制数右移2位后得到的值为该接口类在元数据表TypeDef中所在的数据行。
[0264] 根据元数据表InterfaceImpl中读取的信息得到元数据表TypeDef中每个定义类型所继承的接口类和所继承的接口数;其中,还获取相应接口类的压缩后的偏移量。
[0265] 若当前定义类型没有继承任何接口,则压缩后的定义类型中接口数为0x00,接口对应的信息不存在。
[0266] 步骤S312:获取嵌套类型所在的类型压缩后的偏移量;
[0267] 根据当前定义类型的标识信息判断当前类型是否是嵌套类型,若是嵌套类型,则获取当前嵌套类型所在的类型的偏移量;若判断出当前类型不是嵌套类型,则压缩后的定义类型中不存在此项。
[0268] 根据在步骤S303中从元数据表TypeDef中读取四个字节的定义类型标识信息判断当前类型是否是嵌套类型,若是嵌套类型则还要读取元数据表NestedClass(嵌套类型)中的信息;根据现存表位向量定位元数据表NestedClass,具体的方法类似步骤S302;读取元数据表NestedClass。
[0269] 在元数据表NestedClass中每行有4个字节,第1、2字节为NestedClass表示当前嵌套类型在元数据表TypeDef中所在的数据行,第3、4字节为EnclosingClass表示当前定义类型所在的类型在元数据表TypeDef中所在的数据行。
[0270] 查找与当前类型所在类型在元数据表TypeDef中所在的数据行,获取当前类型所在类型压缩后的偏移量,并将其作为当前嵌套类型所在的类型;
[0271] 例如,判断元数据表TypeDef中ClassC的标识信息可知,ClassC为嵌套类型;在元数据表NestedClass中查找嵌套类型为ClassC的项,判断在元数据表NestedClass中第1、2字节NestedClass的值在元数据表TypeDef中对应的项是否是ClassC所在的数据行,如果是ClassC,则再取元数据表NestedClass中ClassC对应的EnclosingClass所示的ClassC所在类型在元数据表TypeDef中的数据行,由于该数据行中对应的类型为ClassA,于是可知嵌套类型ClassC所在的类型是ClassA,另对ClassA压缩后的偏移量为0x17,则获取ClassA压缩后的偏移量为0x17。
[0272] 步骤S313:组织并存储压缩后的定义类型数据。
[0273] 对每个定义类型压缩后的数据进行组织,其格式为:定义类型名称的hash值、类型标识的压缩结果、类型所继承的接口计数、类型父类的偏移量、类型中所包含的字段计数、类型中方法重载信息、嵌套类型所在类型的偏移量、类型所在接口的偏移量、类型中字段对应的信息;
[0274] 其中,类型所的接口的偏移、类型中字段对应的信息可以有多条,当有多条时,依次排列当前定义类型中的接口偏移量、字段信息;另外,嵌套类型所在类型的偏移量、类型所继承的接口的偏移量、类型中字段对应的信息这三者中可能部分存在或都不存在,若不存在则压缩结果中不写入这些信息。
[0275] 例如,本实施例提供的代码中,定义类型ClassC压缩后的结果为:0x9B8D240216020200171819F1EC010684641103
[0276] 为了使上述压缩结果看起来更清楚直观,将上述数据以表1的形式存放,参见表1,定义类型ClassC压缩后的结果的解析结构为:
[0277] 表1
[0278]定义类型ClassC压缩部分划分 定义类型ClassC压缩后的值
定义类型名称 9B8D
定义类型标识 24
继承的接口计数 02
继承的父类的偏移量 16
定义类型所包含字段计数 02
定义类型中方法计数 02
方法重载信息 00
嵌套类型所在类型的偏移量 17
继承的接口偏移量 18,19
定义字段对应的信息 F1EC 01 06,8464 11 03
[0279] 将.net文件中每一个定义类型压缩完成后,按照压缩后分配的偏移量顺序地存储。
[0280] 本实施例中所要进行压缩处理的数据是在.net架构下编写的代码编译后变成的二进制数据,通过本实施例提供的方法,定义类型的压缩率最大可以达到30%,进而可以有效地降低.net文件占用的存储空间,使.net文件可以在小容量存储介质(例如:智能卡)上存储并运行,进而增强了小容量存储介质(例如:智能卡)的功能。
[0281] 以上实施例提供的压缩方法或压缩装置有效地降低了.net文件占用的存储空间,利于.net文件在各种设备上使用,同时还较大地节省了系统的资源,提高了资源利用率。
[0282] 显然,本领域的技术人员应该明白,上述的本发明的各模块或各步骤可以用通用的计算装置来实现,它们可以集中在单个的计算装置上,或者分布在多个计算装置所组成的网络上,可选地,它们可以用计算装置可执行的程序代码来实现,从而可以将它们存储在存储装置中由计算装置来执行,或者将它们分别制作成各个集成电路模块,或者将它们中的多个模块或步骤制作成单个集成电路模块来实现。这样,本发明不限制于任何特定的硬件和软件结合。
[0283] 以上所述仅为本发明的优选实施例而已,并不用于限制本发明,对于本领域的技术人员来说,本发明可以有各种更改和变化。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。