VFP探讨之空值和可变长类型在DBF表文件中的存储(二):普通数据和空值的存储形态
本次讨论只针对几种常用的数据类型:字符型(C)、可变长字符型(V)、逻辑型(L)、日期型(D)、日期时间型(T)、整型(I)。其中,用整型代表所有VFP直接支持的各种数值型。在聊完常用数据的存储形态后会加上一种特殊的值—.NULL.的介绍。字符型:在有值的时候,存储的是该值中各个字符的ASCII码。不足长度的部分,会在后面填充空格的ASCII码十六进制值20。比如:某个字段叫FF1,定义成C(3),当前记录上该字段的值是“AB”,在DBF文件中将存储为:41、42、20。解释一下这些数字:字母“A”的ASCII码是65;字母“B”的ASCII码是66;空格的ASCII码是32。这三个数字对应的十六进制数值分别是:41、42、20,这就是DBF文件中的底层数据了。当没有对它赋值时,所有位置上都用空格的ASCII码填充;
可变长字符型:它在字段值填满设计宽度时的存储方式与字符型完全相同,没填满时就有区别了。普通字符型在未填满时,剩下的字节全部用空格的ASCII码值填满;而可变长字符型也这样处理,但最后一个字节会保留给标志。标志是什么呢?标志是一个数值,它指示了本条记录中该字段已经存在的有效字符数量。比如:将FF2定义成V(3),某条记录中该字段存储了一个字符“A”,那么在DBF文件中将存储为:41、20、01。前两个数值分别是字母“A”和空格的十六进制ASCII码,最后一个数指的是有效字符数量。因为这条记录在该字段中只存入了一个字母,所以该值就是1。假设现在存入两个字母“AB”,DBF文件中将存储为:41、42、02。可以看到,最后一个字节本应属于填充不足宽度的空格,现在为了有标志,这个字节就让给了标志;当没有对它赋值时,前面全部用空格的ASCII码填充,最后一个字节填充00;当可变长字符型只设计了1位宽度,且没有赋值时,该字节只存放标志00,不填充空格;
逻辑型:逻辑型在DBF表文件中实际是按单字节字符型存储的,也就是说逻辑型字段在表文件中只存储大写字母“F”、“T”或空格的ASCII码值。字母“F”的十六进制ASCII码值是46H,字母“T”的十六进制ASCII码值是54H。所以,对于逻辑型字段,DBF表文件中只可能有三个值:46、54,或20。当没有对它赋值时,用空格的十六进制ASCII码值保存,也就是20;
日期型:日期型在DBF表文件中实际是按8字节字符型存储的,格式是YYYYMMDD,不保存中间的分隔符。比如:{2013-03-02},存储的是:32、30、31、33、30、33、30、32,这些数值是字符“0”~“3”对应的十六进制ASCII码。当没有对它赋值时,以8个空格的十六进制ASCII码保存,也就是连续存储8个20H;
日期时间型:日期时间型看上去与日期型差不多,只不过多了点时间数据。但同样只有8字节空间的它存储数据的方式却与日期型大相径庭,它存储的是一个8字节的数值,而不是日期时间数字字符的ASCII码。当没有对它赋值时,日期时间型字段对应的8个字节全部填充0,即:00、00、00、00、00、00、00、00;
整型:对于各数值型来说,存储在DBF表文件中的数据就是其本身的值,而不是各位数字字符对应的ASCII码。比如:数值16,在表中存储的就是00、00、00、10;数值27,存储的就是00、00、00、1B。因为整型固定是4字节,所以,不足4字节的高位用0填充。
之所以用整型作为数值型的代表来讨论,是因为它的规则比较简单,没有小数位。象Number、Float、Double、Currency等数值型由于含小数位,转换成二进制时与整型有所区别,没有那么直观,这里就不讨论了。
说完了普通数据的存储方式,就要聊到.NULL.空值了,以上介绍到的数据类型都支持.NULL.值,前提是一定要在CREATE TABLE命令中为每个需要.NULL.值的字段加一个关键字“NULL”。比如:CREATE TABLE T1 (FF1 C(2), FF2 N(3) NULL),这条命令在新建一个含两字段的表文件同时,也为其中的FF2字段授予了用.NULL.值的许可。
接着就来介绍一下上面各类数据是如何存储.NULL.值的:
字符型、日期型:全部宽度都用十六进制的20(空格)填充;
可变长字符型:除了最后一个字节为00外,其余字节全部都用十六进制的20(空格)填充。若宽度只有一位,则只保存标志00;
逻辑型:保存字母“F”的十六进制ASCII码值46;
日期时间型、各类数值型:所有字节全部都用00填充。
看到这,也许有人马上就会问了:那与不赋值有什么区别?FoxPro在显示数据时,如何判断要显示初始值,还是.NULL.?确实,.NULL.值仅从数据保存的情况来看,除了逻辑型以外,其它都与初始值是完全一样的,仅凭数据区两者无法区分。于是,FoxPro就采用了一种跟踪技术,来区分该值是初始值还是.NULL.值。另外,可变长字符型也会填充空格来补充宽度,最后一个字节虽然保存的是代表有效字符长度的数值,但如何知道这些空格是否算有效字符,最后一个字节中的数值到底代表了有效字符的长度,还是某个字符的ASCII码值呢?对此,FoxPro同样采用了跟踪技术来区分。
[ 本帖最后由 taifu945 于 2014-3-27 10:31 编辑 ]