版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
太原理工大学毕业设计(论文)用纸绪论1.1课题研究的目的及意义随着信息时代的到来,手机,电脑等新生代的通信设备成了通信领域的主力军。并且随着手机和电脑的普及,最终成为通信的主导工具。根据国家统计局的统计,至2010年7月,中国的网名数量超过4.2亿,手机网民数量达到2.77亿。这将意味着我国有超过4.2亿的人民正在享受电子时代所带来的方便和快捷。对于大多数网民而言,手机,电脑已经成为他们生活中不可或缺的一部分,让他们花更多的时间和金钱去购买和使用非电子版的日历,这显然是不实际的。桌面日历系统的诞生也是必然的。本软件所要设计的是一款集传统日历功能和日志功能于一身的个性化的桌面日历系统。同时增加提醒,记事,备忘,存储,密码设置等常用功能,真正意义上实现便捷,有效,实时的查找信息,了解信息。1.2桌面日历的发展状况日历软件真正的诞生源于WINDOWS系统的开发。日历软件是WINDOWS系统的自带软件,主要是方便用户了解时间而附加上去的。但是,作为WINDOWS系统开发者的主要力量——西方人,以他们的对事物的了解方式所做出来的软件并非被所有中国的网民所认同。对深受中国文化深深影响的中国网民来说,使用这种日历软件并没有带来什么方便,因为在中国人的日常生活中还有一部日历——农历。一些有预见的软件公司找到了商机,开发了诸多的只面向中国网民的桌面日历备忘管理软件。伴随着科学技术的日新月异,桌面日历备忘管理软件得到了长足的发展,并正在不断地更新、完善,同时,出现的问题也愈加明显。由于软件公司在利益的趋势与业内强大的竞争的压迫下,软件公司为所开发的软件能够获得更多的用户使用,在所开发的桌面日历备忘管理软件中捆绑了大量的其他功能软件,例如股市信息、网络电视、游戏等,使得一个本该短小简单的软件变成了一个捆绑了大量功能的“变形金刚”。就我熟悉的八戒桌面工具,其中包含了各种硬件的监测信息、计算器、证券信息、基金信息、网络广播、网络电视、电子字典、各种版本的天气预报等49个功能部件,其功能之强大与齐全让人望尘莫及。实际上,大多数的网民根本就不需要这么多的功能软件。即使有部分网民需要使用这些软件,也必然会选择使用更加专业的软件,而不会用这些看似强大,但又不专业的功能软件。当网民们只想使用一个纯粹的桌面日历备忘录软件时,确又不得不使用那些“变形金刚”,这是多么苦恼的事情。所以开发一款纯粹的桌面日历备忘管理软件存在其开发的价值的。2相关理论基础2.1C#2.1.1C#简介C#读作CSharp。最初它有个更酷的名字,叫做COOL。微软从1998年12月开始了COOL项目,直到2000年2月,COOL被正式更名为C#。在1998年,Delphi语言的设计者Hejlsberg带领着Microsoft公司的开发团队,开始了第一个版本C#语言的设计。在2000年9月,国际信息和通信系统标准化组织为C#语言定义了一个Microsoft公司建议的标准。最终C#语言在2001年得以正式发布。在过去的二十年里,C和C++已经成为在商业软件的开发领域中使用最广泛的语言。它们为程序员提供了十分灵活的操作,不过同时也牺牲了一定的效率。许多程序员都试图寻找一种新的语言。希望能在功能与效率之间找到一个更为理想的通过权衡点。对于C/C++用户来说,最理想的解决方案无疑是在快速开发的同时又可以调用底层平台的所有功能。C#是由微软开发的一种全新的、面向对象的编程语言。作为VisualStudio中的一部分推出。既保持了C++中熟悉的语法,并且还包含了大量的高效代码和面向对象特性。C#使得C++程序员可以高效的开发程序,而绝不损失C/C++原有的强大的功能。因为这种继承关系,C#与C/C++具有极大的相似性,熟悉类似语言的开发者可以很快的转向C#。C#语言将在保持C/C++灵活性的基础上为程序员带来更高效的RAD开发方GUI界面。它不仅能用于WEB服务程序的开发,并且还能开发强大的系统级程序。微软称C#是由C和C++派生而来的一种“简单、流行、面向对象、类型安全”的程序设计语言C#意在综合VisualBasic的高效率和C++的强大功能。事实上,C#将是完全依靠Windows的最完美产物。那些困绕JavaSDK,MFC和SET的数据库已成为过去。你想放入C#的任何东西,(无论何种语言)只要在Windows的.NET子系统下建立和包装后都可以使用Windows的运行库。C#是一种安全的、稳定的、简单的、优雅的,由C和C++衍生出来的面向对象的编程语言。它在继承C和C++强大功能的同时去掉了一些它们的复杂特性(例如没有宏以及不允许多重继承)。C#综合了VB简单的可视化操作和C++的高运行效率,以其强大的操作能力、优雅的语法风格、创新的语言特性和便捷的面向组件编程的支持成为.NET开发的首选语言。C#是面向对象的编程语言。它使得程序员可以快速地编写各种基于MICROSOFT.NET平台的应用程序,MICROSOFT.NET提供了一系列的工具和服务来最大程度地开发利用计算与通讯领域。正是由于C#面向对象的卓越设计,使它成为构建各类组件的理想之选——无论是高级的商业对象还是系统级的应用程序。使用简单的C#语言结构,这些组件可以方便的转化为XML网络服务,从而使它们可以由任何语言在任何操作系统上通过INTERNET进行调用。C#使得C++程序员可以高效的开发程序,且因可调用由C/C++编写的本机原生函数,因此绝不损失C/C++原有的强大的功能。因为这种继承关系,C#与C/C++具有极大的相似性,熟悉类似语言的开发者可以很快的转向C#。2.1.2C#的优点C#在带来对应用程序的快速开发能力的同时,并没有牺牲C与C++程序员所关心的各种特性。它忠实地继承了C和C++的优点。如果你对C或C++有所了解,你会发现它是那样的熟悉。即使你是一位新手,C#也不会给你带来任何其它的麻烦,快速应用程序开发(RapidApplicationDevelopment,RAD)的思想与简洁的语法将会使你迅速成为一名熟练的开发人员。C#是专门为.NET应用而开发出的语言。这从根本上保证了C#与.NET框架的完美结合。在.NET运行库的支持下,.NET框架的各种优点在C#中表现得淋漓尽致。概括来讲,C#的优点有:第一,简洁的语法。在缺省的情况下,C#的代码在.NET框架提供的“可操纵”环境下运行,不允许直接地内存操作。它所带来的最大的特色是没有了指针。与此相关的是,那些在C++中被疯狂使用的操作符(例如:“::”、“->”和“.,”)已经不再出现。C#只支持一个“.”,对于我们来说,现在需要理解的一切仅仅是名字的嵌套而已。C#用真正的关键字换掉了那些把活动模板库(ActiveTemplateLibrary,ALT)和COM搞得乱糟糟的伪关键字,如OLE_COLOR、BOOL、VARIANT_BOOL、DISPID_XXXXX等等。每种C#操作符在.NET类库中都有了新名字。第二,精心的面向对象设计。C#具有面向对象的语言所应有的一切特性:封装、继承与多态性,这并不出奇。然而,通过精心地面向对象设计,从高级商业对象到系统级应用,C#建造广泛组件的绝对选择。在C#的类型系统中,每种类型都可以看作一个对象。C#提供了一个叫做装箱(boxing)与拆箱(unboxing)的机制来完成这种操作,而不给使用者带来麻烦。C#只允许单继承,即一个类不会有多个基类,从而避免了类型定义的混乱。在后面的学习中你很快会发现,C#中没有了全局函数,没有了全局变量,也没有了全局常数。一切的一切,都必须封装在一个类之中。你的代码将具有更好的可读性,并且减少了发生命名冲突的可能。整个C#的类模型是建立在.NET虚拟对象系统(VisualObjectSystem,VOS)的基础之上,其对象模型是.NET基础架构的一部分,而不再是其本身的组成部分。C#具备了良好的开发环境。结合自身强大的面向对象功能,C#使得开发人员的生产效率得到极大的提高。对于公司而言,软件开发周期的缩短将能使它们更好应付网络经济的竞争。在功能与效率的杠杆上人们终于找到了支点。第三,完整的安全性和错误处理。语言的安全性与错误处理能力,是衡量一种语言是否优秀的重要依据。任何人都会犯错误,即使是最熟练的程序员也不例外:忘记变量的初始化,对不属于自己管理范围的内存空间进行修改,。这些错误常常产生难以预见的后果。一旦这样的软件被投入使用,寻找与改正这些简单错误的代价将会是让人无法承受的。C#的先进设计思想可以消除软件开发中的许多常见错误,并提供了包括类型安全在内的完整的安全性能。为了减少开发中的错误,C#会帮助开发者通过更少的代码完成相同的功能,这不但减轻了编程人员的工作量,同时更有效地避免了错误的发生。第四,灵活性和安全性。在简化语法的同时,C#并没有失去灵活性。尽管它不是一种无限制语言,比如:它不能用来开发硬件驱动程序,在默认的状态下没有指针等等,但是,在学习过程中你将发现,它仍然是那样的灵巧。如果需要,C#允许你将某些类或者类的某些方法声明为非安全的。这样一来,你将能够使用指针、结构和静态数组,并且调用这些非安全代码不会带来任何其它的问题。此外,它还提供了一个另外的东西(这样的称呼多少有些不敬)来模拟指针的功能--delegates,代表。再举一个例子:C#不支持类的多继承,但是通过对接口的继承,你将获得这一功能。正是由于其灵活性,C#允许与C风格的需要传递指针型参数的API进行交互操作,DLL的任何入口点都可以在程序中进行访问。C#遵守.NET公用语言规范(CommonLanguageSpecification,CLS),从而保证了C#组件与其它语言组件间的互操作性。元数据(Metadata)概念的引入既保证了兼容性,又实现了类型安全。2.1.3C#的缺点首先,在大量的现有Windows平台上,C#的程序还不能运行,因为C#程序需要.NET运行库为基础,而.NET运行库将作为新一代的Windows(Whistler)的一部分发行,或以ServicePack的形式提交给WindowsMe和Windows2000用户。所以在近期,C#会主要在服务器上得到应用。其次,C#能够使用的组件和库还只有.NET运行库等很少的选择,没有丰富的第三方软件库可用,这需要有一个过程同时各软件开发商的支持也很重要。第三,JAVA的成功因素里有一些是反微软阵营的吹捧,虽然“只写一次,到处运行”只是一句口号,但毕竟已经是一种成熟的技术。而C#的鼓吹者目前只有名声不佳的微软,且只能运行在Windows上。实际上这两种语言都不是不可替代的,理智的说,对软件开发商而言,什么工具用的最熟,那就是最好的工具。尤其对C++的使用者C#没有带来任何新东西,因为.NET运行库在C++中也可以使用,没有要换的绝对的理由。作为微软的产品,它不能帮助竞争者其它操作系统。作为微软的产品,它必须追求稳定、严谨,而不要出现任何错误。C#团队实力确实非常强大,导致C#不会出现任何一个低级错误,就连if(a=false)这样的代码都会出现一个警告。C#的语法、底层库也无时不刻在印证一个理念:我们做的是产品,我们必须保证产品根据我们所期望的工作,而不允许出现任何错误。这是一个优点,也是一个缺点。当我们的需求和产品设计者所期望的一致时,事情会变的非常轻松。但如果需求和期望不同时,麻烦事情会接踵而至。举个例子,当我们希望switch能够贯穿case时,就会出现麻烦产品设计者不允许用户直接这么做虽然他有合适的理由,也提供了实现这个功能的替代方法,但用户必须按他说的做。如果这种情况发生在其它产品设计者未考虑到的需求时,那么这个麻烦将会更大。比如当我们想要重载>>来模拟C++代码时,就会发现这是一个不可能的任务。很多人都有这种感受,直接使用IDE自带的功能开发,做起来非常轻松。但一旦有一种自主的想法时,就很难实现比如修改软件主题。在C#中,文档注释需求书写xml,但是文档注释却是不能继承的用户必须手动为每个函数和重载添加注释。C#的很多常用的工具类因为其使用的局限性(如菜鸟用了就会出错)而不被公开。典型的例子如下:publicstringGetValue(intindex){if(index<0)thrownewArgumentOutOfromRangeException();if(index>this.Count)thrownewArgumentOutOfromRangeException();returnGetValueInternal(index);}internalstringGetValueInternal(intindex){//...}C#把用户当成傻子GetValue会传递一个非法的index,然后自己则使用更高效的GetValueInternal。C#系统库的设计通过对index检测,来确保抛出的是一个符合意义的异常。那用户怎么办?如果在项目中,不检测index是否合法,则显得不严谨,代码质量低(不检查index,会导致index错误时将出现IndexOfRangeException,而不是ArgumentOutOfRangeException,这会让第三方用户迷惑:到底应该捕获哪个异常)。而检测则是在浪费代码量,一个函数尚且如此,一个项目可见一斑。此外,用户经常需要使用一个类来实现功能,但其实这个类在系统库中是存在的,但由于它只是一个内部使用的功能模块所以不是public。这时用户只好另起炉灶。这也不难解释为了明明有Buffer.Copy这个方法,系统内部却只会调用Buffer.CopyInternal(不是public的)而不是Buffer.Copy,而Buffer.CopyInternal却是用户真正所需要的函数。总体看,C#不适合做项目。它是一个很大的坑,因为它会通过各种方式消耗用户的时间。特别是追求完美的人,想要紧跟微软的节奏创造完美,那简直是在拿时间开玩笑。而对于仅仅想做完项目的人,也会越做越烦:明明简单的事情要搞这么复杂。即使如此,C#终究也只是一个语言,一个工具。客观评价一个工具的好坏没有实际意义,关键看用户能否熟练使用,并且扬长避短。没有最好的语言,但有最适合自己的语言。2.1.4C#的与语言结构类:在C#中类的声明与C++和Java很相似。但是,不象C++,C#结构体与类是不支持继承。但是,与Java相同的是,一个结构体可以实现接口(interface)。Java的关键字import已经被替换成using,它起到了同样的作用。类可以是抽象的和不可继承的:一个被申明成abstract的类不能被实例化,它只能被用做一个基类,C#关键字lock就像Java关键字final,它申明一个类不是抽象的,但是它也不能被用做另一个类的基类界面:就象在Java中一样,一个界面是一组方法集合的抽象定义。当一个类或结构体实现一个界面的时候,它必须实现这个界面中定义的所有方法。一个单一的类可以实现几个界面,也许以后会出现一些微妙的差别,但是这个特点看起来与Java相比没有变化。在Java中,一个接口是一组方法集合的抽象定义.当一个类或结构体实现一个接口的时候,它必须实现这个接口中定义的所有方法.一个单一的类可以实现几个接口.也许以后会出现一些微妙的差别,但是这个特点看起来与Java相比没有变化。布尔运算:条件表达式的结果是布尔数据类型,布尔数据类型是这种语言中独立的一种数据类型.从布尔类型到其他类型没有直接的转换过程.布尔常量true和false是C#中的关键字.错误处理:如Java中那样,通过抛出和捕捉异常对象来管理错误处理过程.内存管理:由底层.NET框架进行自动内存垃圾回收。布尔运算:条件表达式的结果是布尔数据类型,布尔数据类型是这种语言中独立的一种数据类型,从布尔类型到其他类型没有直接的转换过程,布尔常量true和false是C#中的关键字。错误处理:如Java中那样,通过抛出和捕捉异常对象来管理错误处理过程。内存管理:由底层.NET框架进行自动内存垃圾回收。一个基本的C#类中包含数据成员、属性、构造器和方法。属性可以是静态或实例成员。接口:是其他类型为确保它们支持某些操作而实现的引用类型。接口从不直接创建而且没有实际的表示形式,其他类型必须转换为接口类型。一个接口定义一个协定。实现接口的类或结构必须遵守其协定。接口可以包含方法、属性、索引器和事件作为成员。强类型:C#是一个强类型的语言,它的数值类型有一些可以进行隐式转换,其他的必须显式转换,隐式转换的类型只能是长度短的类型转换成长的类型,int可以转换成long、float、double、decimal,反之必须显式的转换。编译:程序直接编译成标准的二进制可执行形式.但C#的源程序并不是被编译成二进制可执行形式,而是一种中间语言(IL),类似于JAVA字节码。如果前面的HelloWorld程序被保存成一个c#与权威指南教程文本文件并被命名为Hello.cs,它将被编译成命名Hello.exe的可执行程序。C#程序不能直接编译成标准的二进制可执行形式,与
Java
类似,它被编译成为中间代码(MicrosoftIntermediateLanguage),然后通过.NETFramework的虚拟机——被称之为通用语言执行层(CommonLanguageRuntime,CLR)——执行。一个C#的结构体与C++的结构体是相似的,因为它能够包含数据声明和方法.但是,不象C++,C#结构体与类是不同的而且不支持继承.但是,与Java相同的是,一个结构体可以实现接口。预编译:C#中存在预编译指令支持条件编译,警告,错误报告和编译行控制.可用的预编译指令有:#define,#undef,#if,#elif,#else,#endif,#warning,#error,#line。没有了#include伪指令,无法再用#define语句对符号赋值,所以就不存在源代码替换的概念--这些符号只能用在#if和#elif伪指令里.在#line伪指令里的数字(和可选的名字)能够修改行号还有#warning和#error输出结果的文件名。操作符重载:一些操作符能够被重载,而另一些则不能.特别的是,没有一个赋值运算符能够被重载.能够被重载的单目操作符是:+-!~++--truefalse能够被重载的二元运算符是:+、-、*、/、%、&、|、^、<<、>>、==、!=、>、<、>=、<=。类型:C#中的类型一共分为两类,一类是值类型(ValueType),一类是引用类型(ReferenceType)。值类型和引用类型是以它们在计算机内存中是如何被分配的来划分的。值类型包括结构和枚举,引用类型包括类、接口、委托等。还有一种特殊的值类型,称为简单类型(SimpleType),比如byte,int等,这些简单类型实际上是FCL类库类型的别名,比如声明一个int类型,实际上是声明一个System.Int32结构类型。因此,在Int32类型中定义的操作,都可以应用在int类型上,比如“123.Equals(2)”。所有的值类型都隐式地继承自System.ValueType类型(注意System.ValueType本身是一个类类型),System.ValueType和所有的引用类型都继承自System.Object基类。不能显式地让结构继承一个类,因为C#不支持多重继承,而结构已经隐式继承自ValueType。NOTE:堆栈(stack)是一种后进先出的数据结构,在内存中,变量会被分配在堆栈上来进行操作。堆(heap)是用于为类型实例(对象)分配空间的内存区域,在堆上创建一个对象,会将对象的地址传给堆栈上的变量(反过来叫变量指向此对象,或者变量引用此对象)。中间代码:微软在用户选择何时MSIL应该编译成机器码的时候是留了很大的余地.微软公司很小心的声称MSIL不是解释性的,而是被编译成了机器码.它也明白许多--如果不是大多数的话--程序员认为Java程序要不可避免的比C编写的任何东西都要慢.而这种实现方式决定了基于MSIL的程序(指的是用C#,VisualBasic,"ManagedC++"--C++的一个符合CLS的版本--等语言编写的程序)将在性能上超过"解释性的"Java代码.当然,这一点还需要得到事实证明,因为C#和其他生成MSIL的编译器还没有发布.但是JavaJIT编译器的普遍存在使得Java和C#在性能上相对相同.象"C#是编译语言而Java是解释性的,"之类的声明只是商业技巧.Java的中间代码和MSIL都是中间的汇编形式的语言,它们在运行时或其它的时候被编译成机器代码。基本数据类型:C#拥有比C/C++或者Java更广泛的数据类型.这些类型是bool、byte、ubyte、short、ushort、int、uint、long、ulong、float、double和decimal,像Java一样,所有这些类型都有一个固定的大小.又像C和C++一样,每个数据类型都有有符号和无符号两种类型.与Java相同的是,一个字符变量包含的是一个16位的Unicode字符,C#新的数据类型是decimal数据类型,对于货币数据,它能存放28位10进制数字。两个基本类:一个名叫object的类是所有其他类的基类。而一个名叫string的类也象object一样是这个语言的一部分.作为语言的一部分存在意味着编译器有可能使用它,无论何时在程序中写入一句带引号的字符串,编译器会创建一个string对象来保存它。参数传递:方法可以被声明接受可变数目的参数.缺省的参数传递方法是对基本数据类型进行值传递。ref关键字可以用来强迫一个变量通过引用传递,这使得一个变量可以接受一个返回值。out关键字也能声明引用传递过程,与ref不同的地方是,它指明这个参数并不需要初始值。COM的集成:C#对Windows程序最大的卖点可能就是它与COM的无缝集成了,COM就是微软的Win32组件技术.实际上,最终有可能在任何.NET语言里编写COM客户和服务器端。C#编写的类可以子类化一个已存在的COM组件;生成的类也能被作为一个COM组件使用,然后又能使用,比方说,JScript语言子类化它从而得到第三个COM组件。这种现象的结果是导致了一个运行环境的产生,在这个环境里的组件是网络服务,可用任何.NET语言子类化。索引下标:一个索引与属性除了不使用属性名来引用类成员而是用一个方括号中的数字来匿名引用(就象用数组下标一样)以外是相似的。代理和反馈:一个代理对象包括了访问一个特定对象的特定方法所需的信息.只要把它当成一个聪明的方法指针就行了。代理对象可以被移动到另一个地方,然后可以通过访问它来对已存在的方法进行类型安全的调用.一个反馈方法是代理的特例.event关键字用在将在事件发生的时候被当成代理调用的方法声明中。2.1.5C#的程序执行C#所开发的程序源代码并不是编译成能够直接在操作系统上执行的二进制本地代码。与Java类似,它被编译成为中间代码,然后通过.NETFramework的虚拟机——被称之为通用语言运行时(CLR)——执行。所有的.Net编程语言都被编译成这种被称为MSIL(MicrosoftIntermediateLanguage)的中间代码。因此虽然最终的程序在表面上仍然与传统意义上的可执行文件都具有“.exe”的后缀名。但是实际上,如果计算机上没有安装.NetFramework,那么这些程序将不能够被执行。在程序执行时,.NetFramework将中间代码翻译成为二进制机器码,从而使它得到正确的运行。最终的二进制代码被存储在一个缓冲区中。所以一旦程序使用了相同的代码,那么将会调用缓冲区中的版本。这样如果一个.Net程序第二次被运行,那么这种翻译不需要进行第二次,速度明显加快。2.1.6C#的历史发展C#是微软公司在2000年6月发布的一种新的编程语言,主要由安德斯·海尔斯伯格(AndersHejlsberg)主持开发,它是第一个面向组件的编程语言,其源码会编译成msil再运行。它借鉴了Delphi的一个特点,与COM(组件对象模型)是直接集成的,并且新增了许多功能及语法糖,而且它是微软公司.NETwindows网络框架的主角。C#读作CSharp。最初它有个更酷的名字,叫做COOL。微软从1998年12月开始了COOL项目,直到2000年2月,COOL被正式更名为C#。在1998年,Delphi语言的设计者Hejlsberg带领着Microsoft公司的开发团队,开始了第一个版本C#语言的设计。在2000年9月,国际信息和通信系统标准化组织为C#语言定义了一个Microsoft公司建议的标准。最终C#语言在2001年得以正式发布。原Broland公司的首席研发设计师安德斯·海尔斯伯格(AndersHejlsberg)在微软开发了VisualJ++1.0,很快的VisualJ++由1.1版本升级到6.0版。SUN公司认为VisualJ++违反了Java开发平台的中立性,对微软提出了诉讼。2000年6月26日微软在奥兰多举行的“职业开发人员技术大会”(PDC2000)上,发表新的语言C#。C#语言取代了VisualJ++,语言本身深受Java、C和C++的影响。C#是兼顾系统开发和应用开发的最佳实用语言,并且很有可能成为编程语言历史上的第一个“全能”型语言。看过这篇简史,不要把C#看成年轻后生了——只要是“马拉多纳”,就早晚当“球王”。C#1.0,纯粹的面向对象。1998年底,微软正在忙于新一代COM的设计工作,COM一直是组件化开发中非常成功的一种技术;但由于它仅提供了二进制层面上的统一,因此无法将类型信息和用于支持基础平台和开发工具的信息放到组件中,Java逐步走向成熟。微软学习Java的做法,将虚拟机的概念引入到了COM领域;同时,微软提出了“元数据”的概念,用于描述组件的类型信息和工具支持信息,并决定将其放入到组件当中。1998年12月,微软启动了一个全新的语言项目——COOL,这是一款专门为CLR设计的纯面向对象的语言,也正是本文的主角——C#的前身。1999年7月份,微软完成了COOL语言的一个内部版本。2000年2月份,微软才正式将COOL语言更名为C#。据说起这个名字是因为C#开发小组的人很讨厌搜索引擎,因此把大部分搜索引擎无法识别的“#”字符作为该语言名字的一部分;还有一种说法是在音乐当中“#”是升调记号,表达了微软希望它在C的基础上更上一层楼的美好愿望——当然这些都只是传说,无从考证。又是历经了一系列的修改,微软终于在2000年7月发布了C#语言的第一个预览版。2.2SQLite介绍2.2.1SQLite简介SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。至今已经有14个年头,SQLite也迎来了一个版本SQLite3已经发布。不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进程,而是连接到程序中成为它的一个主要部分。所以主要的通信协议是在编程语言内的直接API调用。这在消耗总量、延迟时间和整体简单性上有积极的作用。整个数据库(定义、表、索引和数据本身)都在宿主主机上存储在一个单一的文件中。它的简单的设计是通过在开始一个事务的时候锁定整个数据文件而完成的。2.2.2SQLite的特点SQLite是一个轻量级、跨平台的关系型数据库。既然号称关系型数据库,支持SQL92标准大多数标准(比如视图、事务、触发器等)。QLite和C/S模式的数据库软件不同,它是进程内的数据库引擎,因此不存在数据库的客户端和服务器。使用SQLite一般只需要带上它的一个动态库,就可以使用它的全部功能。而且那个动态库的尺寸也挺小,以版本3.6.11为例,Windows下487KB、Linux下347KB。SQLite的另外一个特点是绿色:它的核心引擎本身不依赖第三方的软件,使用它也不需要“安装”。所以在部署的时候能够省去不少麻烦。SQLite在使用前不需要安装设置,不需要进程来启动、停止或配置,不需要管理员去创建新数据库或分配用户权限,在系统崩溃或失电之后自动恢复。大多数SQL数据库引擎是作为一个单独的服务器进程被执行。访问数据库的程序使用某种内部进程通信(典型的是TCP/IP)与服务器通信,完成发送请求到服务器和接收查询结果的工作。SQLite不采用这种工作方式。使用SQLite时,访问数据库的程序直接从磁盘上的数据库文件读写,没有中间的服务器进程。所谓的“单一文件”,就是数据库中所有的信息(比如表、视图、触发器、等)都包含在一个文件内。这个文件可以copy到其它目录或其它机器上,也照用不误。一个SQLite数据库是一个单独的普通磁盘文件,能够被定位在路径层次的任何地方。如果SQLite能读写磁盘文件,则它也能访问数据库。大多数SOL数据库引擎趋向于把数据存为一个大的文件集合,通常这些文件在一个标准的定位中,只有数据库引擎本身能访问它。SQLite虽然很小巧,但是支持的SQL语句不会逊色于其他开源数据库,它支持的SQL包括:ATTACHDATABASE,BEGINTRANSACTION,Comment,COMMITTRANSACTION,COPY,CREATEINDEX,CREATETABLE,CREATETRIGGER,CREATEVIEW,DELETE,DETACHDATABASE,DROPINDEX,DROPTABLE,DROPTRIGGER,DROPVIEW,ENDTRANSACTION,EXPLAIN,Expression,INSERT,ONCONFLICTclause,PRAGMA,REPLACE,ROLLBACKTRANSACTION,SELECT,UPDATE。同时它还支持事务处理功能等等。也有人说它象Microsoft的Access,有时候真的觉得有点象,但是事实上它们区别很大。比如SQLite支持跨平台,操作简单,能够使用很多语言直接创建数据库,而不象Access一样需要Office的支持。如果你是个很小型的应用,或者你想做嵌入式开发,没有合适的数据库系统,那么你可以考虑使用SQLite。它的特性包括1).ACID事务。2).零配置–无需安装和管理配置。3).储存在单一磁盘文件中的一个完整的数据库。4).数据库文件可以在不同字节顺序的机器间自由的共享。5).支持数据库大小至2TB。6).足够小,大致13万行C代码,4.43M。7).比一些流行的数据库在大部分普通数据库操作要快。8).简单,轻松的API。9).包含TCL绑定,同时通过Wrapper支持其他语言的绑定。10).良好注释的源代码,并且有着90%以上的测试覆盖率。11).独立:没有额外依赖。12).源码完全的开源,你可以用于任何用途,包括出售它。13).支持多种开发语言,C,PHP,Perl,Java,C#,Python,Ruby。2.2.3使用.net操作SQLite先下载ADO
.NET2.0ProviderforSQLite。下载binarieszip版就可以了。下载完后解压缩,可以在bin目录下找到System.Data.SQLite.DLL。在vs2008中用AddReference功能把System.Data.SQLite.DLL加到工程里就可以了。运行下面代码试试:stringdatasource="e:/tmp/test.db";System.Data.SQLite.SQLiteConnection.CreateFile(datasource);//连接数据库System.Data.SQLite.SQLiteConnectionconn=newSystem.Data.SQLite.SQLiteConnection();System.Data.SQLite.SQLiteConnectionStringBuilderconnstr=newSystem.Data.SQLite.SQLiteConnectionStringBuilder();connstr.DataSource=datasource;connstr.Password="admin";//设置密码,SQLiteADO
.NET实现了数据库密码保护conn.ConnectionString=connstr.ToString();conn.Open();//创建表System.Data.SQLite.SQLiteCommandcmd=newSystem.Data.SQLite.SQLiteCommand();stringsql="CREATETABLEtest(usernamevarchar(20),passwordvarchar(20))";cmd.CommandText=sql;cmd.Connection=conn;cmd.ExecuteNonQuery();//插入数据sql="INSERTINTOtestVALUES('a','b')";cmd.CommandText=sql;cmd.ExecuteNonQuery();//取出数据sql="SELECT*FROMtest";cmd.CommandText=sql;System.Data.SQLite.SQLiteDataReaderreader=cmd.ExecuteReader();StringBuildersb=newStringBuilder();while(reader.Read()){sb.Append("username:").Append(reader.GetString(0)).Append("\n").Append("password:").Append(reader.GetString(1));}MessageBox.Show(sb.ToString());2.2.4使用SQLite的注意事项在确定是否在应用程序中使用SQLite:之前,应该考虑以下几种情况:目前没有可用于SQLite的网络服务器。从应用程序运行位于其他计算机上的SQLite的惟一方法是从网络共享运行。这样会导致一些问题,像UNIX®和Windows®网络共享都存在文件锁定问题。还有由于与访问网络共享相关的延迟而带来的性能下降问题。SQLite只提供数据库级的锁定。虽然有一些增加并发的技巧,但是,如果应用程序需要的是表级别或行级别的锁定,那么DBMS能够更好地满足您的需求。正如前面提到的,SQLite可以支持每天大约100,00次点击率的Web站点——并且,在某些情况下,可以处理10倍于此的通信量。对于具有高通信量或需要支持庞大浏览人数的Web站点来说,应该考虑使用DBMS。SQLite没有用户帐户概念,而是根据文件系统确定所有数据库的权限。这会使强制执行存储配额发生困难,强制执行用户许可变得不可能。SQLite支持多数(但不是全部)的SQL92标准。不受支持的一些功能包括完全触发器支持和可写视图。如果您感到其中的任何限制会影响您的应用程序,那么您应该考虑使用完善的DBMS。如果您可以解除这些限制问题,并且对快速灵活的嵌入式开源数据库引擎很感兴趣,则应重点考虑使用SQLite。一些能够真正表现SQLite优越性能的领域是Web站点,可以使用SQLite管理应用程序数据、快速应用程序原型制造和培训工具。由于资源占用少、性能良好和零管理成本,嵌入式数据库有了它的用武之地,它将为那些以前无法提供用作持久数据的后端的数据库的应用程序提供了高效的性能。现在,没有必要使用文本文件来实现持久存储。SQLite之类的嵌入式数据库的易于使用性可以加快应用程序的开发,并使得小型应用程序能够完全支持复杂的SQL。这一点对于对于小型设备空间的应用程序来说尤其重要。嵌入式数据库对于加快应用程序开发也很重要,尤其是在用于数据库抽象层(例如PEAR::DB或ezSQL)时。最后,SQLite正在积极开发中,未来一定会有新的功能,会对开源社区更有用。2.2.5SQLite的语言绑定可以从C/C++程序中使用这个库,还可以获得对Tcl和一些其他脚本语言的绑定。在CPAN的
DBD::SQLite上有一个Perl的DBI/DBD模块,它不是到SQLite的接口,而是包括整个SQLite数据库引擎在其中并不需要任何额外的软件。还有一个Python模块叫做PySQLite。PHP从PHP5.0开始包含了SQLite,但是自5.1版之后开始成为一个延伸函式库。SQLite能与PHP4一起工作但不包含在其中。Rails2.0.3将缺省的数据库配置改为了SQLite3。我此次的项目用的是c#连接sqlite数据库,代码如下所示:usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Data.SQLite;namespaceCalendar{publicclassSQLiteHelper{publicstaticstringconnString=@"datasource=Calendar.db;pooling=true;failifmissing=false";publicstaticSQLiteDataReaderExecuteReader(stringsqlCommand,SQLiteParameter[]sps){SQLiteConnectionconn=newSQLiteConnection(connString);conn.Open();SQLiteCommandcmd=conn.CreateCommand();cmd.CommandText=sqlCommand;cmd.CommandType=System.Data.CommandType.Text;if(sps!=null)cmd.Parameters.AddRange(sps);returncmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);//intindexContent=reader.GetOrdinal("Content");//intindexIsSecret=reader.GetOrdinal("IsSecret");//intindexAddTime=reader.GetOrdinal("AddTime");//if(reader.HasRows)//{//while(reader.Read())//{//Diaryd=newDiary();//d.Content=reader[indexContent].ToString();//d.IsSecret=reader[indexIsSecret].ToString();//d.AddTime=(DateTime)reader[indexAddTime]//list.Add(d);//}//returnlist;//}}publicstaticintExecuteNonQuery(stringsqlCommand,SQLiteParameter[]sps){using(SQLiteConnectionconn=newSQLiteConnection(connString)){conn.Open();using(SQLiteCommandcmd=conn.CreateCommand()){if(sps!=null)cmd.Parameters.AddRange(sps);cmd.CommandText=sqlCommand;cmd.CommandType=System.Data.CommandType.Text;returncmd.ExecuteNonQuery();}}}2.2.6SQLite的客户端管理SQLite亦可以作为桌面数据库使用,以下为第三方SQLite的GUI软件。例如,SQLiteMan,使用QT开发的一个SQLite客户端,支持多语言、跨平台。SQLiteManSQLiteManager,以火狐浏览器的扩展形式提供的SQLite客户端。SQLiteDatabaseBrowser,agraphicalclienttoaccessSQLitedatabasesSqlProSQLClient,anothergraphicalclienttoworkwithSQLitedatabases。
2.2.7SQLite的类型SQLite的数据类型首先你会接触到一个让你惊讶的名词:Typelessness(无类型).对!SQLite是无类型的.这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中,无论这列声明的数据类型是什么(只有在一种情况下不是,稍后解释).对于SQLite来说对字段不指定类型是完全有效的.如:CreateTableex1(a,b,c);诚然SQLite允许忽略数据类型,但是仍然建议在你的CreateTable语句中指定数据类型.因为数据类型对于你和其他的程序员交流,或者你准备换掉你的数据库引擎时能起到一个提示或帮助的作用.SQLite支持常见的数据类型,如:CREATETABLEex2(aVARCHAR(10),bNVARCHAR(15),cTEXT,dINTEGER,eFLOAT,fBOOLEAN,gCLOB,hBLOB,iTIMESTAMP,jNUMERIC(10,5)kVARYINGCHARACTER(24),lNATIONALVARYINGCHARACTER(16));前面提到在某种情况下,SQLite的字段并不是无类型的.即在字段类型为”IntegerPrimaryKey”时.3系统需求分析3.1用户需求1.将日历和日记集成到一款软件上,让用户可以在特定的时间查看,编辑,添加日志;2.日志行程的自动提醒,该系统能根据用户自己设定的系统提醒时间来提醒用户,时差以秒级计算,非常准确;3.设置隐私日志,最大程度上保护用户的隐私。3.2功能需求桌面日历的功能需求包括四个方面,具体内容如图3-1所示。|日志的简要内容||日志篇数|查看日志|是否为私密日志||日志创建的时间|||日志内容桌面日历系统|添加日志|设置私密日志||设置闹钟提醒||闹钟提醒|根据待办事项性质显示提醒时间|||密码设置|设置|铃声设置图5-1桌面日历的功能需求我此次项目分为四个模块,分别是查看日记,添加日记,闹钟提醒和设置。1.在查看日志中,可以查看到指定日期的日志篇数和日志的简要内容,是否为私密日志以及日志的创建时间。如果在该日期内,没有日志记录,则会出现相应的提示。如果查阅到日志记录,而用户设置为私密日志,则必须输入指定的密码,方可查阅,否则不能查看。如果用户未设置为私密日记,即可直接查阅,并且可以对内容进行编辑保存。这样做,不仅保护了用户的隐私性,而且体现了此款软件的人性化。2.在添加日志中,可以直接添加日志内容,还可以设置是否选择为私密日志和是否设置待办事项闹钟提醒。如果设置为待办事项,则可以设置具体的闹钟提醒日期。确保满足所有用户的需求。3.在闹钟提醒中,可以根据待办事项是三天内待办,一周内待办,一个月内待办,显示出相应的事项和提醒时间。4.在日志设置中,包括了日志密码设置和闹钟铃声设置。密码设置方面,输入当前密码,输入新的密码,重复新密码,只有全部输入正确,才能修改密码,否则会出现提示:输入错误。铃声设置方面,可以浏览本地的铃声进行铃声预览并且保存设置。3.3性能需求该系统主要是为了方便用户进行日程管理,所以要求界面要简洁,操作要方便。功能要完善,并且不能出现导致该系统崩溃的重大BUG。因为该系统为多用户系统,所有用户资料均保存在数据库内,所以要求数据库安全性要高,运行要稳定,执行速度快。为保护用户信息,各用户密码和每日行程不能在数据库中以明文显示。该系统基于Windows操作平台,符合当前大多数人的操作系统,更加大众化。4.桌面日历的系统功能实现4.1查看日记模块在查看日志模块中,可以查看到指定日期的日志篇数和日志的简要内容,是否为私密日志以及日志的创建时间。如果在该日期内,没有日志记录,则会出现相应的提示。如果查阅到日志记录,而用户设置为私密日志,则必须输入指定的密码,方可查阅,否则不能查看。如果用户未设置为私密日记,即可直接查阅,并且可以对内容进行编辑保存。下列为此模块的代码:)privatevoidbtnSave_Click(objectsender,EventArgse)//是一个响应事件,object后是引起响应{//的事件,EventArgs后是响应的信息。stringcontent=txtContent.Text.Trim();if(string.IsNullOrEmpty(content){MessageBox.Show(this,"日志内容不能为空!");//如果日记内容为空,则会跳出一个信息框提示return;}stringstrIsSecret;if(IsSecret==true){strIsSecret="是";//“是”表示选择设置私密日志}Else{strIsSecret="否";//表示“否”不选择设置私密日志}stringsql;if(IsRemind==true)//如果选择设置待办事项提醒,则会出现选择闹钟提醒的年,月,日stringremindTime=CurDate.ToString("yyyy-MM-dd")+string.Format("{0}:{1}:00",comboRemindHour.Text,txtRemindMinute.Text.Trim());sql=string.Format("insertintoDiary(Content,IsSecret,AddTime)values('{0}','{1}','{2}')",content,strIsSecret,remindTime);;}else{sql=string.Format("insertintoDiary(Content,IsSecret,AddTime)values('{0}','{1}','{2}')",content,strIsSecret,System.DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss"));}intret=SQLiteHelper.ExecuteNonQuery(sql,null);//连接数据库,如果返回影响的行数为0,则失//败if(ret!=0){MessageBox.Show(this,"成功添加一条日志!");this.Close();}else{MessageBox.Show(this,"日志添加失败!");}}4.2添加日志模块在添加日志模块中,可以直接添加日志,并且选择是否为私密日志。私密日志中,完成md5加密功能,sqlite中存储的密码为了安全起见,采用了md5加密,使密码具有很强的安全性,理论上不可破解,除非知道明文。
MD5即Message-DigestAlgorithm5(消息摘要算法第五版)的简称,是当前计算机领域用于确保信息传输完整一致而广泛使用的散列算法之一(又译哈希算法、摘要算法等),主流编程语言普遍已有MD5的实现。md5的典型应用是对一段信息(message)产生信息摘要(message-digest),以防止被篡改。比如,在unix下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.md5的文件,在这个文件中通常只有一行文本,大致结构如:md5(tanajiya.tar.gz)=0ca175b9c0f726a831d895e269332461这就是tanajiya.tar.gz文件的数字签名。md5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的md5信息摘要。如果在以后传播这个文件的过程中,无论文件的内容发生了任何形式的改变(包括人为修改或者下载过程中线路不稳定引起的传输错误等),只要你对这个文件重新计算md5时就会发现信息摘要不相同,由此可以确定你得到的只是一个不正确的文件。如果再有一个第三方的认证机构,用md5还可以防止文件作者的"抵赖",这就是所谓的数字签名应用。md5还广泛用于加密和解密技术上。比如在unix系统中用户的密码就是以md5(或其它类似的算法)经加密后存储在文件系统中。当用户登录的时候,系统把用户输入的密码计算成md5值,然后再去和保存在文件系统中的md5值进行比较,进而确定输入的密码是否正确。通过这样的步骤,系统在并不知道用户密码的明码的情况下就可以确定用户登录系统的合法性。这不但可以避免用户的密码被具有系统管理员权限的用户知道,而且还在一定程度上增加了密码被破解的难度。正是因为这个原因,现在被黑客使用最多的一种破译密码的方法就是一种被称为"跑字典"的方法。有两种方法得到字典,一种是日常搜集的用做密码的字符串表,另一种是用排列组合方法生成的,先用md5程序计算出这些字典项的md5值,然后再用目标的md5值在这个字典中检索。我们假设密码的最大长度为8位字节(8bytes),同时密码只能是字母和数字,共26+26+10=62个字符,排列组合出的字典的项数则是p(62,1)+p(62,2)….+p(62,8),那也已经是一个很天文的数字了,存储这个字典就需要tb级的磁盘阵列,而且这种方法还有一个前提,就是能获得目标账户的密码md5值的情况下才可以。这种加密技术被广泛的应用于unix系统中,这也是为什么unix系统比一般操作系统更为坚固一个重要原因。对md5算法简要的叙述可以为:md5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。在md5算法中,首先需要对信息进行填充,使其字节长度对512求余的结果等于448。因此,信息的字节长度(bitslength)将被扩展至n*512+448,即n*64+56个字节(bytes),n为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息字节长度=n*512+448+64=(n+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。md5中有四个32位被称作链接变量(chainingvariable)的整数参数,他们分别为:a=0x01234567,b=0x89abcdef,c=0xfedcba98,d=0x76543210。当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息中512位信息分组的数目。将上面四个链接变量复制到另外四个变量中:a到a,b到b,c到c,d到d。主循环有四轮(md4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。以一下是每次操作中用到的四个非线性函数(每轮一个)。f(x,y,z)=(x&y)|((~x)&z)g(x,y,z)=(x&z)|(y&(~z))h(x,y,z)=x^y^zi(x,y,z)=y^(x|(~z))(&是与,|是或,~是非,^是异或)这四个函数的说明:如果x、y和z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。f是一个逐位运算的函数。即,如果x,那么y,否则z。函数h是逐位奇偶操作符。假设mj表示消息的第j个子分组(从0到15),<<ff(a,b,c,d,mj,s,ti)表示a=b+((a+(f(b,c,d)+mj+ti)<<gg(a,b,c,d,mj,s,ti)表示a=b+((a+(g(b,c,d)+mj+ti)<<hh(a,b,c,d,mj,s,ti)表示a=b+((a+(h(b,c,d)+mj+ti)<<ii(a,b,c,d,mj,s,ti)表示a=b+((a+(i(b,c,d)+mj+ti)<<这四轮(64步)是:第一轮ff(a,b,c,d,m0,7,0xd76aa478)ff(d,a,b,c,m1,12,0xe8c7b756)ff(c,d,a,b,m2,17,0x242070db)ff(b,c,d,a,m3,22,0xc1bdceee)ff(a,b,c,d,m4,7,0xf57c0faf)ff(d,a,b,c,m5,12,0x4787c62a)ff(c,d,a,b,m6,17,0xa8304613)ff(b,c,d,a,m7,22,0xfd469501)ff(a,b,c,d,m8,7,0x698098d8)ff(d,a,b,c,m9,12,0x8b44f7af)ff(c,d,a,b,m10,17,0xffff
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 上海市县(2024年-2025年小学五年级语文)人教版能力评测(上学期)试卷及答案
- 景德镇市2024-2025学年上学期期中质量检测卷(答案)
- 帆布便鞋产业深度调研及未来发展现状趋势
- 厨房用海绵产业深度调研及未来发展现状趋势
- 剑道用胸甲产业规划专项研究报告
- 健身用拉筋板产业深度调研及未来发展现状趋势
- 商业会议策划行业经营分析报告
- 口服布洛芬止痛剂产业深度调研及未来发展现状趋势
- 外科仪器和设备的修理和维护行业市场调研分析报告
- 宠物用计步器产业深度调研及未来发展现状趋势
- 特种作业人员台账.doc
- 国家开放大学《管理英语1》边学边练参考答案
- 3章SAA的功能应用
- (完整版)装饰装修工程监理细则(详解)最新(精华版)
- 电焊中级工(四级)职业技能鉴定考试题库
- 氧化铝生产工艺教学(拜耳法)(课堂PPT)
- 多巴胺的药理作用及用法PPT参考幻灯片
- 钢结构网架翻新改造施工方案
- 水稻雄性不育系鉴定
- 少先队鼓号队常用鼓号曲谱
- 土方运输次数登记卡
评论
0/150
提交评论