嵌入式多级目录简单数据库实现架构 笔者:荆潇影 E~mail:huazxy@126.com
前言: 嵌入式设备的数据库实现一直是个难点,目前比较好的嵌入式数据库费用不菲,如果在利用现成的资源构建一个简单实用的数据库,这是所有嵌入式软件工程师需要仔细考虑的问题.本文以手机上的一个简单多级目录数据库系统的实现,介绍一种简单易于维护的嵌入式多级目录简单数据库软件架构.抛砖引玉,欢迎大家指正!
正文:
1.1项目需求 最近手头产品部分功能,需要将sohu健康网的健康自测系统,做到手机上并 通过Gprs网络实现数据动态更新.具体可参照 http://health.sohu.com/s2007/7772/s250797093
1.2项目分析 实现多级目录的简单数据库,支持网络动态更新,方便界面调用显示.
(1) 一级目录 所有的症状测试类别,需要可以动态更新. (2) 二级目录 每一大类下有不同数目的症状,需要可以动态更新. (3) 三级目录 每个具体症状下面有不同数目的测试问题,需要可以动态更新 (4) 四级目录 每个问题下有不同数目的超链接,方便设备上网,需要可以动态更新
1.3功能分析
1.3.1 Hash Table
嵌入式设备上一般实现数据的查找存储,我们首先想到的是Hash table,利用Hash table查找的话,实际上是通过对"关键字"Hash时,将字符串转换成数字索引值HashValue,然后根 据HashValue获取索引Index.
在构建表的过程中,需要先在内存中空出一大块区域来存储索引Index,按照一定的运算法则计算得到存储数据的地址,最后在这个地址写入需要存储的数据.
搜索的话则先获取得到HashValue然后跳转到固定地址获取索引Index,然后按照运算得到要搜索的数据的地址,取得要搜索的地址.
Hash 算法思想: Hash Table的做法是将KeyWord转化成数字索引Index. (注:本文提到的Hash Table不考虑节点上实现链表的情况,仅仅将其作为一个 线性表).
Hash Table来实现查找缺点:
(1)可能出现两个不同的KeyWord经过算法换算得到HashValue是一样,出现重复概率.
(2)有一大部分内存区用来存储数字索引Index,浪费了内存空间(或文件空间).而且表越大 浪费的空间越大.
1.3.2 新的方法
我们已确切知道一点,构建简单数据库的根本在于"KeyWord---->数字索引Index"的转换.
无论Hash Table,或者复杂的数据MySQl肯定要有这样一个由字符串转换成索引Index的过程.不然一切操作无从谈起.
在这个基础上我们来构造项目所需求的数据库:
(1)制作一级目录的数据库: 数据结构如下: typedef struct { int index;//索引 char ClsName[];//类别名字符串 Char ClsSubTotal;//每一个类别下面症状的数目 }ClsDetail;
typedef struct { Int totalCls;//总的类别数目 ClsDetail gTotalCls[];//总的类别数据 }TotalCls; *********************************************************************
为了实现数据动态更新,有效办法是通过网络下载数据文件.但在这个问题之前,一般需要程序员本身制作数据库文件.常见的是我们自己写一些工具,解析文本数据源生成二进制文件. 那么按照一级目录的要求我们一般会这样去制作文本数据源文件:
上面第1分割符|数字表示Index(类别名索引),第1到第2个分割符的字符串表示症状测试类别名,最后的字符串表示此类测试下有多少个具体症状,最后以回车符结束.
这样我们可以按行解析文本文件数据,解析一行便将相应的数据,插入到二进制文件的相应位置,再增加数据索引值(DBIndex++).这样就将DBIndex和存储数据项联系起来,从而勿需存储DBIndex.
比如要搜索第Index个大类的数据,我只要搜索数据库中DBIndex(DBIndex = Index-1)项的数据项就OK了,比如第一个大类,我只需要搜索DBIndex为0的数据项,即从文件开始读取sizeof(ClsDetail)字节的数据就好.
这样我们可以制作得到DB0文件,此文件主要存储症状类别名及每个类别下面的症状数目. (2)制作二级目录的数据库: 数据结构如下: typedef struct { int index;//索引 char htName[];//症状名字符串 char htDetail[];//症状详细描叙字符 Char SubTotal;//每一个症状下面的问题数目 }HtDetail;
typedef struct { Int totalNum;//总的症状数目 HtDetail gTotalHtDetail[];//总的症状数据 }TotalDetail; 制作数据库的过程同(1),只是数据结构发生了变化,相应的数据项当然也要变化. 这样我们可以制作得到DB1文件,此文件主要存储症状名及每个症状下面的问题数目.
(3)制作三级目录的数据库: 数据结构如下: typedef struct { int index;//索引 char QstDetail[];//问题具体描叙字符串 Char SubTotal;//每一个症状下面的超链接数目 }HtQst;
typedef struct { Int totalNum;//总的问题数目 HtQst gTotalHtQst[];//总的问题数据 }TotalHtQst 制作数据库的过程同(1),只是数据结构发生了变化,相应的数据项当然也要变化. 这样我们可以制作得到DB2文件,此文件主要存储问题数据及每个问题下面的超链接数目.
(4)制作四级目录的数据库: 数据结构如下: typedef struct { int index;//索引 char pURL[];//问题具体描叙字符串 }HtProLink;
typedef struct { Int totalNum;//总的问题数目 HtProLink gTotalHtPlk[];//总的问题数据 }TotalHtQst 制作数据库的过程同(1),只是数据结构发生了变化,相应的数据项当然也要变化. 这样我们可以制作得到DB3文件,此文件主要存储的超链接URL数据.
注: 当然有的朋友会问为什么不全部制作成一个数据文件DB,这也可以,只不过我个人这样不符合模块化的设计思想就分开制作了.另外还有个问题,因为整个数据结构定义的是采用固定长度的数组,存在存储资源浪费,当然也可以弄成链表、队列等动态数据结构来存储.
1.4 利用数据库实现GUI界面显示
整体界面框架示意如下:
由上面示意图可见,只要数据结构设计合理,数据库构建合理,我们只需要5个界面就能够把sohu整个健康自测的网页搬到嵌入式设备上来(我这边是手机,相信其他的设备也可以).
用一个具体的例子走下整个界面功能流程: (1)进入主界面,获取所有的症状测试类别名及相应下一级界面症状数目. 搜索函数接口: search_DB0(int index),利用列表框的列表项来做为Index进入搜索数据.这样可以遍历获取所有的类别名及其具体类别下的症状数目.
(2)进入第一大类测试,显示其下面所有的症状名列表. 搜索函数接口: Search_DB1(int clsIndex,int Index),ClsIndex为类别索引值,Index为此类别下具体第几个症状. 比如我们搜索第二大类第10个症状: Search_DB1(2,10).因为我们的数据库是按循序写文件的,我们先需要将类别1下面的总的症状数目N1获取,然后N1 + 10即为我们在数据库文件中的真实数据索引值DBIndex。 (3)进入第10个症状,显示其症状描叙字符及资费提示,并获取症状自测的问题数目.
(4)进入问题自测,搜索每个问题的数据和诊断结果,并获取具体问题的超链接数目.
搜索函数接口: Search_DB2(int clsIndex,int HtNameIndex,int index). ClsIndex为类别名索引值,HtNameIndex为症状名索引值,index为具体第几个问题.
(5)回答问题,是与否进入诊断结果界面.
注: 假如不存在超链接直接显示诊断结果,存在超链接解析诊断结果获取超链接,搜索数据库并取得WAP链接URL.
搜索函数接口: Search_DB3(int clsIndex,int HtNameIndex,int Qstindex,int index). ClsIndex为类别名索引值,HtNameIndex为症状名索引值,int Qstindex为自测问题索引值,index为第几个超链接.. ================================================================== 这样我们将一个相对复杂的问题给一步步分析清楚简化,具体编码将不再困难.
1.5实现数据动态更新 由于整个数据库架构相对灵活,我们只需要提供一定格式的数据源文本文件利用程序工具解析就能够生成简单的数据库文件。这样手机可以通过网络下载数据库文件以达到动态更新的效果.
1.6实现症状名的检索 我们还可以在主界面列表框加入一项症状检索,一进入此界面手写输入相应的症状名,然后在DB1里面遍历数据,并将取得的数据的症状名与输入的症状名进行比较,如果相同则进入症状描叙和资费提示界面,接下来的界面与上面相同.
1.7 具体程序 (忽略). 1.8 小结 我们从分析到具体实现构建了一个简单的多级目录的数据库的软件架构.基本上可以满足嵌入式设备大多数情况下的应用.目前由于项目的特殊性,数据库仅仅支持搜索数据功能.当然也可以采取高级一点的数据结构,比如队列,进行数据库插入,删除功能的完善.当然对于一些智能设备采取hash table构建数据库也是不错的选择. 相关链接:https://bbs.21ic.com/upfiles/img/20082/200822065678.pdf |