回归

Shadow

  DonewsBlog  |  Donews首页  |  Donews社区  |  Donews邮箱  |  我的首页  |  联系作者  |  聚合   |  登录
  307篇文章 :: 0篇收藏:: 16篇评论:: 1个Trackbacks

文章

收藏

相册

论坛

软件

存档


正在读取评论……


2006年06月



    摘要:

先增加引用--》microsoft activex data objects 2.0 library

Dim adoCmm As New ADODB.Command
 Dim adoRec As New ADODB.Recordset
 adoCnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\vb\2\news.mdb;Persist Security Info=False"
 adoCmm.ActiveConnection = adoCnn
 adoCmm.CommandType = adCmdText
 adoCmm.CommandText = "select * from employees"
 Print "连接数据库成功"

    (全文共458字)——点击此处阅读全文




    摘要:

SQL Server 开发之 分页存储过程

在工作中经常会用到分页显示数据,如果使用.NET开发,可以使用DataGrid控件的分页功能,也可以使用PagedDataSource类来辅助完成。但这两种方式都将从数据库中获取所有的记录,将记录数目较大时,效率很低,因此直接使用存储过程来进行分页,则将会提供更好的性能。在CSDN的数据库开发社区,有许多大侠都写出了自己的分页存储过程,    (全文共28863字)——点击此处阅读全文





    摘要:http://www.yesky.com/SoftChannel/72348977504190464/20040214/1768206.shtml    (全文共406字)——点击此处阅读全文




    摘要:

描述

返回一个数字格式的表达式。

语法

FormatNumber(Expression[,NumDigitsAfterDecimal [,IncludeLeadingDigit [,UseParensForNegativeNumbers [,GroupDigits]]]])

FormatNumber函数语法有如下几部分:

    (全文共2716字)——点击此处阅读全文



XMLHTTP能干很多事情,但是在这里我们要它干的只是:将指定的网页的HTML代码读出。
如果通过程序读出对方(当当、卓越)的相应HTML代码就好办了,因为商品数据就存储在那庞杂的代码中。

这很简单,我接着写了如下函数:
 
function getBody(infopageurl)
'功能:取得指定网址的html代码
'参数:infopageurl 网页地址
if infopageurl<>"" then
 dim xmlHttp
 set xmlHttp=server.createobject("MSXML2.XMLHTTP")
‘声明XMLHTTP对象
 xmlHttp.open "GET",infopageurl,false
 xmlHttp.send
’上面这两就句就是调用的形式,调用后程序会堵塞在send这句,直到内容被返回。
        getBody=BytesToBstr(xmlhttp.responsebody,"GB2312")‘然后通过xmlhttp.responsebody属性将返回内容读出,这里用到一个BytesToBstr函数将在后面说明。
 set xmlHttp=nothing
end if 
end function
 
关于BytesToBstr,开始返回的结果没有经过这个函数处理,结果返回的汉字是一堆乱码。什么原因就不用深究了。我到www.chinaz.com下载了几个”小偷’的程序,发现里面不约而同的都含有这个函数。大概就是用adodb.stream对结果字符进行了转换。我把它加到我的函数里结果就正常了。
 
Function BytesToBstr(body,Cset)
 dim objstream
 
 set objstream = Server.CreateObject("adodb.stream")
 
 objstream.Type = 1
 
 objstream.Mode = 3
 
 objstream.Open
 
 objstream.Write body
 
 objstream.Position = 0
 
 objstream.Type = 2
 
 objstream.Charset = Cset
 
 BytesToBstr = objstream.ReadText
 
 objstream.Close
 
 set objstream = nothing
End Function

html代码取回来了,我们怎么从中取得需要的数据?答案是正则表达式。
 
正则表达达式就象是一种简单的语言。它用一些特殊的字符模糊地描述一个字符串。然后可以通过程序去检查一个字符串中是否包含你描述的那种字符串,还可以将你描述的字符从一个字符串中取出,这里我们就是利用这个功能来获取需要的数据。
 
举起例子比较容易理解:
* 匹配前面的子表达式零次或多次。例如,zo*(正则表达式) 能匹配 z 、 zoo、zooooo、zoooooooooo
+ 匹配前面的子表达式一次或多次。例如,zo+ 能匹配 zo 以及 zoo,但不能匹配 "z"。
\d 匹配一个数字字符。等价于 [0-9]。  例如, \d+ 可以匹配 1,123,9876
.匹配除 "\n" 之外的任何单个字符。
? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
 
下面要做的就是分析商品数据在html代码中存放的特征,然后写出正则表达式将其取出。
例如,joyo商品的市场价格数据在html代码中是这样存储的“市场价:15.00元”,要做的是把以“市场价:”开头,“元”结尾之间的数值取出。下面函数就实现了这个功能:
 
function Topic(sHtmlcode)
'功能:返回joyo.com商品页面的市场价格数值
'参数:shtmlcode 商品页的html代码
Set regEx = New RegExp'建立使用正则表达式的对象
regEx.IgnoreCase =true
regEx.Global = True
regEx.Pattern ="市场价:(.+?)元"设置表达式
Set Matches = regEx.Execute(shtmlcode)'执行表达式将所有符合描述的字符传存放到一个集合里。
for each sMatch in Matches
Topic=sMatch.SubMatches(0)
'submatches(0)带表第一个子匹配,既小括号中的数值
exit for
next 
set regEx=nothing
end function
 
其他的数据也用同样的方法取得。写正则表达式是一个很有趣而且很复杂的工作。期间我遇到写不出来的,就去CSDN.net的论坛去提问,总是可以得到帮助。
 
还有一点要思考的是:是不是这个表达式对所有的商品页面都适用。如果所有的商品都是用一个asp程序显示那就可以,但是joyo.com不是,它的不同分类中html代码的格式是不同的,所以我们要写几个正则表达式来分别匹配不同形式的数据(比如有些页面中市场价格是这样存储的“市场价:<b>15.00</b>元")。

有了这些函数我们就可以用给定的商品网页地址取得相应的数据了。但是这些网站的商品一般都有万余种,如何获取这些地址就不是那么容易了。这个过程因站而异,这也是真正需要“小偷”智慧的工作之一。
 
拿joyo.com进行分析。进入首页之后我发现里面有个”产品搜索“,选择“所有类别”,关键字置空,点击那个”GO!"检索出了21684条记录。这应该就是joyo.com的所有商品信息了,来的太容易我简直不敢相信。

检索页上包含有10条商品的连接,用正则取得后,再取得转向后10条记录(即下一页)的连接。如此循环就会得出所有商品信息。我用access建了一个表来存放它们。编好了程序挂到机器上就睡觉去了。

这是一个检索结果页的连接:
http://www.joyo.com/ProdSearch/prodsearch.asp?kind=&limitBefore=10&vname=&sorttype=undefined&uid=u5swcqykpzsis0qaiwg79sg5u
其中limitBefore=10 当前页第一条记录前有10条记录,即这一页的第一条是总的第11条记录。
 
第二天兴奋地来到机器上一看,发现记录只有700多条。很郁闷,程序我没加容错处理因为我发现vbscript的错误处理比vb中的还要简略。似乎连on error goto LABEL都不可以使用。我在检索页点来点去希望找出错误的根源,结果发现当其中limitBefore大于750的时候后面就没有记录了。原来是这样。joyo.com的程序员没有让我们这么容易的得到所有数据。这条路是不能走了。
 

下面我开始分析检索结果中商品信息页面的连接:
http://www.joyo.com/shop/shop_product.asp?uid=u5swcqykpzsis0qaiwg79sg5u&prodid=bkbk507440
经分析 prodid=bkbk507440 是这个产品的唯一标识,bkbk表示该产品的所属分类“图书”
 
这是一些其他的主要分类标识:
bkbk 图书
bkmu 音乐
itit 数码
bkbh 日用
itrj 数码产品
bkgm 游戏
bkys 影视
 
只要我遍历所有的prodid然后找出存在的商品页面就可以了。然而怎么判断该prodid是否存在呢,我在地址栏上胡乱打了一个prodid返回了出错结果页面。
 
http://www.joyo.com/errormsg.asp?uid=u5swcqykpzsis0qaiwg79smuw&err=GET%C7%EB%C7%F3%B5%C4%C9%CC%C6%B7ID%B2%BB%B4%E6%D4%DA%A3%AC%B2%D9%D7%F7%CE%DE%B7%A8%BC%CC%D0%F8%A3%A1
 
出错页上有一张红色的“警钟”图案,我估计正常的页面上是不可能包含此图片的。于是以此作为判断prodid是否存在的依据。遍历所有prodid,如果在返回结果html中发现“警钟”图片则不做处理,否则就从页面中取出需要的信息。

遍历6位的prodid是个漫长的过程,粗略的估算,如果每个操作用时1秒的话,则最少需要999999次循,环即999999秒(999999/3600=277多小时)。这显然是太长了,于是我又做了一些优化,发现第一位数字只在0-5之间变化,第二为数字只在0-1之间变化。这样大大的缩短了时间(519999/3600=144多小时),实际的时间更乐观。
 
经过几天的调试终于把图书分类下载完了,接下来我又接着优化程序,做一个更有效率的“小偷”。




    摘要:
下面重新注释了BytesToBstr函数,它的作用是把由xmlhttp.responsebody返回的字节数组转换成文本字符串,如果数据要用做屏幕输入则必须转换否则汉字会出现乱码.
 
 Function BytesToBstr(body)
  'Cset:GB2312 UTF-8
  dim objstream
  set objstream = Server.CreateObject("adodb.stream")
  with objstream
   .Type = 1 '设置返回数据类型为二进制
   .Mode = 3 '打开模式为读写
   .Open    
 &    (全文共5357字)——点击此处阅读全文




    摘要:http://www.pcwiki.net/Html/class5/2006-3/30/20133530833.html    (全文共135字)——点击此处阅读全文



C# 语言经过专门设计,以便不同库中的基类与派生类之间的版本控制可以不断向前发展,同时保持向后兼容。这具有多方面的意义。例如,这意味着在基类中引入与派生类中的某个成员具有相同名称的新成员在 C# 中是完全支持的,不会导致意外行为。它还意味着类必须显式声明某方法是要重写一个继承方法,还是一个仅隐藏具有类似名称的继承方法的新方法。

C# 允许派生类包含与基类方法名称相同的方法。

基类方法必须定义为 virtual。

如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。

如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。

如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不调用基类方法。

可以从派生类中使用 base 关键字调用基类方法。

override、virtual 和 new 关键字还可以用于属性、索引器和事件中。

默认情况下,C# 方法不是虚方法 -- 如果将一种方法声明为虚方法,则继承该方法的任何类都可以实现其自己的版本。若要使方法成为虚方法,必须在基类的方法声明中使用 virtual 修饰符。然后,派生类可以使用 override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法。如果 override 关键字和 new 关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。有关更多信息,请参见编译器警告 CS0108。

为了在实践中演示上述情况,我们暂时假定公司 A 创建了一个名为 GraphicsClass 的类,您的程序使用该类。GraphicsClass 类似如下:

C# 复制到剪贴板class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
}

您的公司使用此类,并且您在添加新方法时将其用来派生自己的类:

C# 复制到剪贴板class YourDerivedGraphicsClass : GraphicsClass
{
    public void DrawRectangle() { }
}

您在应用程序的使用过程中没有遇到任何问题,直到公司 A 发布了 GraphicsClass 的新版本,该新版本类似如下:

C# 复制到剪贴板class GraphicsClass
{
    public virtual void DrawLine() { }
    public virtual void DrawPoint() { }
    public virtual void DrawRectangle() { }
}

现在,GraphicsClass 的新版本中包含了一个称为 DrawRectangle 的方法。最初,一切正常。新版本仍与旧版本二进制兼容 -- 即使在计算机系统中安装新类,部署的所有软件仍将继续工作。在您的派生类中,对方法 DrawRectangle 的任何现有调用将继续引用您的版本。

但是,一旦使用 GraphicsClass 的新版本重新编译应用程序,您将收到来自编译器的警告。有关更多信息,请参见编译器警告 CS0108。

此警告提示您需要考虑您的 DrawRectangle 方法在应用程序中的工作方式。

如果想用您的方法重写新的基类方法,请使用 override 关键字,如下所示:

C# 复制到剪贴板class YourDerivedGraphicsClass : GraphicsClass
{
    public override void DrawRectangle() { }
}

override 关键字可确保派生自 YourDerivedGraphicsClass 的任何对象都将使用 DrawRectangle 的派生类版本。派生自 YourDerivedGraphicsClass 的对象仍可以使用 base 关键字访问 DrawRectangle 的基类版本,如下所示:

C# 复制到剪贴板base.DrawRectangle();

如果不想用您的方法重写新的基类方法,则应注意下面的事项。为避免在两种方法之间引起混淆,可以重命名您的方法。重命名方法可能很耗时且容易出错,而且在某些情况下并不实用。但是,如果您的项目相对较小,则可以使用 Visual Studio 的重构选项来重命名方法。有关更多信息,请参见重构类和类型。

或者,也可以通过在派生类定义中使用关键字 new 来防止出现该警告,如下所示:

C# 复制到剪贴板class YourDerivedGraphicsClass : GraphicsClass
{
    public new void DrawRectangle() { }
}

使用 new 关键字告诉编译器您的定义将隐藏基类中包含的定义。这是默认行为。

重写和方法选择
当在类中指定方法时,如果有多个方法与调用兼容(例如,存在两种同名的方法,并且其参数与传递的参数兼容),则 C# 编译器将选择最佳方法进行调用。下面的方法将是兼容的:

C# 复制到剪贴板public class Derived : Base
{
    public override void DoWork(int param) { }
    public void DoWork(double param) { }
}

在 Derived 的一个实例中调用 DoWork 时,C# 编译器将首先尝试使该调用与最初在 Derived 上声明的 DoWork 版本兼容。重写方法不被视为是在类上进行声明的,而是在基类上声明的方法的新实现。仅当 C# 编译器无法将方法调用与 Derived 上的原始方法匹配时,它才尝试将该调用与具有相同名称和兼容参数的重写方法匹配。例如:

C# 复制到剪贴板int val = 5;
Derived d = new Derived();
d.DoWork(val);  // Calls DoWork(double).

由于变量 val 可以隐式转换为 double 类型,因此 C# 编译器将调用 DoWork(double),而不是 DoWork(int)。有两种方法可以避免此情况。首先,避免将新方法声明为与虚方法同名。其次,可以通过将 Derived 的实例强制转换为 Base 来使 C# 编译器搜索基类方法列表,从而使其调用虚方法。由于是虚方法,因此将调用 Derived 上的 DoWork(int) 的实现。例如:

C# 复制到剪贴板((Base)d).DoWork(val);  // Calls DoWork(int) on Derived.





    摘要:

一. 继承基础知识

   为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总是希望能够利用前人或自己以前的开发成果,同时又希望在自己的开发过程中能够有足够的灵活性,不拘泥于复用的模块。C#这种完全面向对象的程序设计语言提供了两个重要的特性--继承性inheritance 和多态性polymorphism。

   继承是面向对象程序设计的主要特征之一,它可以让您重用代码,可以节省程序设计的时间。继承就是在类之间建立一种相交关系,使得新定义的派生类的实例可以继承已有的基类的特征和能力,而且可以加入新的特性或者是修改已有的特性建立起类的新层次。

   现实世界中的许多实体之间不是相互孤立的,它们往往具有共同的特征也存在内在的差别。人们可以采用层次结构来描述这些实体之间的相似之处和不同之处。


图1 类图    (全文共16173字)——点击此处阅读全文





    摘要:AJAX开发简略 (第二部分)

文章工具
推荐给朋友 推荐给朋友
打印文章此处阅读全文