正则表达式.

前言

正则表达式是烦琐的,但是强大的,学会之后的应用会让你除了提高效率外,会给你带来绝对的成就感。只要认真去阅读这些资料,加上应用的时候进行一定的参考,掌握正则表达式不是问题。

索引

1._引子sdfsf
2._正则表达式的历史
3._正则表达式定义

3.1_普通字符
3.2_非打印字符
3.3_特殊字符
3.4_限定符
3.5_定位符
3.6_选择
3.7_后向引用

4._各种操作符的运算优先级
5._全部符号解释
6._部分例子
7._正则表达式匹配规则

7.1_基本模式匹配
7.2_字符簇
7.3_确定重复出现


--------------------------------------------------------------------------------

1. 引子
  目前,正则表达式已经在很多软件中得到广泛的应用,包括*nix(Linux, Unix等),HP等操作系统,PHP,C#,Java等开发环境,以及很多的应用软件中,都可以看到正则表达式的影子。

  正则表达式的使用,可以通过简单的办法来实现强大的功能。为了简单有效而又不失强大,造成了正则表达式代码的难度较大,学习起来也不是很容易,所以需要付出一些努力才行,入门之后参照一定的参考,使用起来还是比较简单有效的。

例子: ^.+@.+//..+$

  这样的代码曾经多次把我自己给吓退过。可能很多人也是被这样的代码给吓跑的吧。继续阅读本文将让你也可以自由应用这样的代码。

  注意:这里的第7部分跟前面的内容看起来似乎有些重复,目的是把前面表格里的部分重新描述了一次,目的是让这些内容更容易理解。

2. 正则表达式的历史
  正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。
  1956 年, 一位叫 Stephen Kleene 的数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。

  随后,发现可以将这一工作应用于使用 Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson 是 Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。

  如他们所说,剩下的就是众所周知的历史了。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。

 

3. 正则表达式定义
  正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串、将匹配的子串做替换或者从某个串中取出符合某个条件的子串等。

列目录时, dir *.txt或ls *.txt中的*.txt就不是一个正则表达式,因为这里*与正则式的*的含义是不同的。
  正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

3.1 普通字符
  由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。

3.2 非打印字符
字符  含义
/cx  匹配由x指明的控制字符。例如, /cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
/f  匹配一个换页符。等价于 /x0c 和 /cL。
/n  匹配一个换行符。等价于 /x0a 和 /cJ。
/r  匹配一个回车符。等价于 /x0d 和 /cM。
/s  匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ /f/n/r/t/v]。
/S  匹配任何非空白字符。等价于 [^ /f/n/r/t/v]。
/t  匹配一个制表符。等价于 /x09 和 /cI。
/v  匹配一个垂直制表符。等价于 /x0b 和 /cK。

 
3.3 特殊字符
  所谓特殊字符,就是一些有特殊含义的字符,如上面说的"*.txt"中的*,简单的说就是表示任何字符串的意思。如果要查找文件名中有*的文件,则需要对*进行转义,即在其前加一个/。ls /*.txt。正则表达式有以下特殊字符。
 

特别字符 说明
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '/n' 或 '/r'。要匹配 $ 字符本身,请使用 /$。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 /( 和 /)。
* 匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 /*。
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 /+。
. 匹配除换行符 /n之外的任何单字符。要匹配 .,请使用 /。
[  标记一个中括号表达式的开始。要匹配 [,请使用 /[。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 /?。
/ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'/n' 匹配换行符。序列 '//' 匹配 "/",而 '/(' 则匹配 "("。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 /^。
{ 标记限定符表达式的开始。要匹配 {,请使用 /{。
| 指明两项之间的一个选择。要匹配 |,请使用 /|。

  构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。正则表达式的组件可以是单个的字符、字符集合、字符范围、字符间的选择或者所有这些组件的任意组合。
 

3.4 限定符
  限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有*或+或?或{n}或{n,}或{n,m}共6种。
*、+和?限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。
  正则表达式的限定符有:
  字符  描述
*  匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+  匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
?  匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n}  n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,}  n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m}  m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

3.5 定位符
  用来描述字符串或单词的边界,^和$分别指字符串的开始与结束,/b描述单词的前或后边界,/B表示非单词边界。不能对定位符使用限定符。
3.6 选择
  用圆括号将所有选择项括起来,相邻的选择项之间用|分隔。但用圆括号会有一个副作用,是相关的匹配会被缓存,此时可用?:放在第一个选项前来消除这种副作用。
  其中?:是非捕获元之一,还有两个非捕获元是?=和?!,这两个还有更多的含义,前者为正向预查,在任何开始匹配圆括号内的正则表达式模式的位置来匹配搜索字符串,后者为负向预查,在任何开始不匹配该正则表达式模式的位置来匹配搜索字符串。
3.7 后向引用
  对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '/n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
  可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对相关匹配的保存。
4. 各种操作符的运算优先级
  相同优先级的从左到右进行运算,不同优先级的运算先高后低。各种操作符的优先级从高到低如下:
  操作符  描述
/  转义符
(), (?:), (?=), []  圆括号和方括号
*, +, ?, {n}, {n,}, {n,m}  限定符
^, $, /anymetacharacter  位置和顺序
|  “或”操作

5. 全部符号解释
字符  描述
/  将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'/n' 匹配一个换行符。序列 '//' 匹配 "/" 而 "/(" 则匹配 "("。
^  匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '/n' 或 '/r' 之后的位置。
$  匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '/n' 或 '/r' 之前的位置。
*  匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
+  匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
?  匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n}  n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,}  n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m}  m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
?  当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
.  匹配除 "/n" 之外的任何单个字符。要匹配包括 '/n' 在内的任何字符,请使用象 '[./n]' 的模式。
(pattern)  匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0…$9 属性。要匹配圆括号字符,请使用 '/(' 或 '/)'。
(?:pattern)  匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern)  正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)  负向预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x|y  匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz]  字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz]  负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z]  字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z]  负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
/b  匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er/b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
/B  匹配非单词边界。'er/B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
/cx  匹配由 x 指明的控制字符。例如, /cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
/d  匹配一个数字字符。等价于 [0-9]。
/D  匹配一个非数字字符。等价于 [^0-9]。
/f  匹配一个换页符。等价于 /x0c 和 /cL。
/n  匹配一个换行符。等价于 /x0a 和 /cJ。
/r  匹配一个回车符。等价于 /x0d 和 /cM。
/s  匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ /f/n/r/t/v]。
/S  匹配任何非空白字符。等价于 [^ /f/n/r/t/v]。
/t  匹配一个制表符。等价于 /x09 和 /cI。
/v  匹配一个垂直制表符。等价于 /x0b 和 /cK。
/w  匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
/W  匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
/xn  匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'/x41' 匹配 "A"。'/x041' 则等价于 '/x04' & "1"。正则表达式中可以使用 ASCII 编码。.
/num  匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)/1' 匹配两个连续的相同字符。
/n  标识一个八进制转义值或一个向后引用。如果 /n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
/nm  标识一个八进制转义值或一个向后引用。如果 /nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 /nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 /nm 将匹配八进制转义值 nm。
/nml  如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
/un  匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, /u00A9 匹配版权符号 (?)。

 

6. 部分例子
正则表达式 说明
//b([a-z]+) /1/b/gi 一个单词连续出现的位置
/(/w+):([^/:]+)(:/d*)?([^# ]*)/  将一个URL解析为协议、域、端口及相对路径
/^(?:Chapter|Section) [1-9][0-9]{0,1}$/ 定位章节的位置
/[-a-z]/ A至z共26个字母再加一个-号。
/ter/b/ 可匹配chapter,而不能terminal
//Bapt/ 可匹配chapter,而不能aptitude
/Windows(?=95 |98 |NT )/ 可匹配Windows95或Windows98或WindowsNT,当找到一个匹配后,从Windows后面开始进行下一次的检索匹配。

 

7. 正则表达式匹配规则
7.1 基本模式匹配

  一切从最基本的开始。模式,是正规表达式最基本的元素,它们是一组描述字符串特征的字符。模式可以很简单,由普通的字符串组成,也可以非常复杂,往往用特殊的字符表示一个范围内的字符、重复出现,或表示上下文。例如:

^once

  这个模式包含一个特殊的字符^,表示该模式只匹配那些以once开头的字符串。例如该模式与字符串"once upon a time"匹配,与"There once was a man from NewYork"不匹配。正如如^符号表示开头一样,$符号用来匹配那些以给定模式结尾的字符串。

bucket$

  这个模式与"Who kept all of this cash in a bucket"匹配,与"buckets"不匹配。字符^和$同时使用时,表示精确匹配(字符串与模式一样)。例如:

^bucket$

  只匹配字符串"bucket"。如果一个模式不包括^和$,那么它与任何包含该模式的字符串匹配。例如:模式

once

与字符串

There once was a man from NewYork
Who kept all of his cash in a bucket.

是匹配的。

  在该模式中的字母(o-n-c-e)是字面的字符,也就是说,他们表示该字母本身,数字也是一样的。其他一些稍微复杂的字符,如标点符号和白字符(空格、制表符等),要用到转义序列。所有的转义序列都用反斜杠(/)打头。制表符的转义序列是:/t。所以如果我们要检测一个字符串是否以制表符开头,可以用这个模式:

^/t

类似的,用/n表示“新行”,/r表示回车。其他的特殊符号,可以用在前面加上反斜杠,如反斜杠本身用//表示,句号.用/.表示,以此类推。

7.2 字符簇

在INTERNET的程序中,正规表达式通常用来验证用户的输入。当用户提交一个form以后,要判断输入的电话号码、地址、EMAIL地址、信用卡号码等是否有效,用普通的基于字面的字符是不够的。

所以要用一种更自由的描述我们要的模式的办法,它就是字符簇。要建立一个表示所有元音字符的字符簇,就把所有的元音字符放在一个方括号里:

[AaEeIiOoUu]

这个模式与任何元音字符匹配,但只能表示一个字符。用连字号可以表示一个字符的范围,如:

[a-z] //匹配所有的小写字母
[A-Z] //匹配所有的大写字母
[a-zA-Z] //匹配所有的字母
[0-9] //匹配所有的数字
[0-9/./-] //匹配所有的数字,句号和减号
[ /f/r/t/n] //匹配所有的白字符

同样的,这些也只表示一个字符,这是一个非常重要的。如果要匹配一个由一个小写字母和一位数字组成的字符串,比如"z2"、"t6"或"g7",但不是"ab2"、"r2d3" 或"b52"的话,用这个模式:

^[a-z][0-9]$

尽管[a-z]代表26个字母的范围,但在这里它只能与第一个字符是小写字母的字符串匹配。

前面曾经提到^表示字符串的开头,但它还有另外一个含义。当在一组方括号里使用^是,它表示“非”或“排除”的意思,常常用来剔除某个字符。还用前面的例子,我们要求第一个字符不能是数字:

^[^0-9][0-9]$

这个模式与"&5"、"g7"及"-2"是匹配的,但与"12"、"66"是不匹配的。下面是几个排除特定字符的例子:

[^a-z] //除了小写字母以外的所有字符
[^/^] //除了(/)(/)(^)之外的所有字符
[^/"/'] //除了双引号(")和单引号(')之外的所有字符

特殊字符"." (点,句号)在正规表达式中用来表示除了“新行”之外的所有字符。所以模式"^.5$"与任何两个字符的、以数字5结尾和以其他非“新行”字符开头的字符串匹配。模式"."可以匹配任何字符串,除了空串和只包括一个“新行”的字符串。

PHP的正规表达式有一些内置的通用字符簇,列表如下:

字符簇 含义
[[:alpha:]] 任何字母
[[:digit:]] 任何数字
[[:alnum:]] 任何字母和数字
[[:space:]] 任何白字符
[[:upper:]] 任何大写字母
[[:lower:]] 任何小写字母
[[:punct:]] 任何标点符号
[[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F]

7.3 确定重复出现

到现在为止,你已经知道如何去匹配一个字母或数字,但更多的情况下,可能要匹配一个单词或一组数字。一个单词有若干个字母组成,一组数字有若干个单数组成。跟在字符或字符簇后面的花括号({})用来确定前面的内容的重复出现的次数。

字符簇 含义
^[a-zA-Z_]$ 所有的字母和下划线
^[[:alpha:]]{3}$ 所有的3个字母的单词
^a$ 字母a
^a{4}$ aaaa
^a{2,4}$ aa,aaa或aaaa
^a{1,3}$ a,aa或aaa
^a{2,}$ 包含多于两个a的字符串
^a{2,} 如:aardvark和aaab,但apple不行
a{2,} 如:baad和aaa,但Nantucket不行
/t{2} 两个制表符
.{2} 所有的两个字符

这些例子描述了花括号的三种不同的用法。一个数字,{x}的意思是“前面的字符或字符簇只出现x次”;一个数字加逗号,{x,}的意思是“前面的内容出现x或更多的次数”;两个用逗号分隔的数字,{x,y}表示“前面的内容至少出现x次,但不超过y次”。我们可以把模式扩展到更多的单词或数字:

^[a-zA-Z0-9_]{1,}$ //所有包含一个以上的字母、数字或下划线的字符串
^[0-9]{1,}$ //所有的正数
^/-{0,1}[0-9]{1,}$ //所有的整数
^/-{0,1}[0-9]{0,}/.{0,1}[0-9]{0,}$ //所有的小数

最后一个例子不太好理解,是吗?这么看吧:与所有以一个可选的负号(/-{0,1})开头(^)、跟着0个或更多的数字([0-9]{0,})、和一个可选的小数点(/.{0,1})再跟上0个或多个数字([0-9]{0,}),并且没有其他任何东西($)。下面你将知道能够使用的更为简单的方法。

特殊字符"?"与{0,1}是相等的,它们都代表着:“0个或1个前面的内容”或“前面的内容是可选的”。所以刚才的例子可以简化为:

^/-?[0-9]{0,}/.?[0-9]{0,}$

特殊字符"*"与{0,}是相等的,它们都代表着“0个或多个前面的内容”。最后,字符"+"与 {1,}是相等的,表示“1个或多个前面的内容”,所以上面的4个例子可以写成:

^[a-zA-Z0-9_]+$ //所有包含一个以上的字母、数字或下划线的字符串
^[0-9]+$ //所有的正数
^/-?[0-9]+$ //所有的整数
^/-?[0-9]*/.?[0-9]*$ //所有的小数

当然这并不能从技术上降低正规表达式的复杂性,但可以使它们更容易阅读。
Posted by ken at 14:08 PM
点击:125 评分:0 评论:0 ActiveX and Com 2006/03/28 一、ActiveX的由来
ActiveX最初只不过是一个商标名称而已,它所涵盖的技术并不是各自孤立的,其中多数都与Internet和Web有一定的关联。更重要的是,ActiveX的整体技术是由Microsoft的COM(Component Object Model,组件对象模型)构筑的。但不要误认为ActiveX是定义了所有包含基于COM的技术。COM与Microsoft Office和Windows以及Microsoft现在所做的一切都有关联,但显然这些产品并不是ActiveX家族中的成员。

ActiveX是从Microsoft的复合文档技术——OLE成长起来的。OLE最初发布的版本,只是瞄准复合文档,但在后续版本OLE2中,导入了 COM。COM是应OLE设计者的需求而诞生的。其基本的出发点是想让某个软件通过一个通用的机构为另一个软件提供服务。因而,COM的第一个使用者是 OLE2。实际上,COM与复合文档间,没有多大关系。后来,COM就作为与复合文档完全无关的技术,开始被广泛使用。这样一来,Microsoft就开始"染指"通用平台技术。但COM不是产品,它需要一个商标名称。不巧,市场专家们选用了"OLE"作为商标名称。于是,使用COM的技术都开始贴上了 OLE的标签。当然,这些技术中的绝大部分与复合文档没有关系。Microsoft要想向人们解释:"OLE不单单是指复合文档!",这要花费相当的精力和时间。

于是,在1996年春,Microsoft改变了主意,选择了ActiveX作为新商标名。ActiveX是指宽松定义的、基于COM的技术集合,而OLE仍然仅指复合文档。当然,最重要的核心还是COM。

让对象模型完全独立于编程语言,这是一个非常新奇的思想。从C++和Java的对象上,我们就能有所了解。但所谓COM对象究竟是什么?为了便于理解,可以把COM看作是某种(软件)打包技术,即把它看作是使软件的不同部分,按照一定的面向对象的形式,组合成可以交互的过程和一组支持库。COM对象可以用 C++、Java和VB等任意一种语言编写,并可以DLL或作为不同过程工作的执行文件的形式来实现。使用COM对象的客户端,无需关心对象是用什么语言写的,也无需关心它是以DLL、还是以另外的过程来执行的。从客户端来看,无任何区别。

这样一个通用的处理技巧非常有用。例如,由用户协调运行的两个应用,可以将它们的共同作业部分,作为COM对象间的交互来实现(当然,现在的OLE复合文档也能做到)。为在浏览器中执行而从Web服务器下载的代码,浏览器可把它看作是COM对象。即是说,COM技术也是一种打包可下载代码的标准方法 (ActiveX控件执行这种功能)。

甚至连应用与本机OS进行交互的方法,也可以用COM来指定(Windows和Windows NT用的新API,多数是作为COM对象来定义的)。COM虽然起源于复合文档,但却可有效地适用于许多软件问题。

二、ActiveX王国
Active平台是Microsoft的世界观。其基本思想是:使用ActiveX控件,来构筑包括从与用户交互和适应COM的事务处理监视器到Web服务器、全部实现自动化的机构。Active平台包括两大部分:Active Server和Active Client。

Active Server实际上是中间层。使用组件或Active服务器页面,来提供用于业务逻辑和主要应用处理的场所。ActiveServer的技术,其核心是NT Server、Microsoft事务处理服务器、数据管理服务、目录服务、Web服务以及网络服务。

事务处理服务器是把线程产生和数据库多重化等传统的TP监控功能与Microsoft的基于组件的编程模型结合起来。数据管理服务等Active平台的其他组件是用OLE DB和ODBC,访问DB2、Oracle、SQL Server等的数据源。目录服务是在DCOM(Distributed COM,分布式COM)的周围,提供目录服务层,这样使远程对象在网络上能相互搜索。Web服务以Internet信息服务器为中心进行构筑,它为服务器上的Web应用开发,提供脚本生成(Scripting)机构。网络服务以DCOM为中心进行构筑,通过以同步MS-RPC为中介的网络,使之能够连接控件。

Active Client是一种交叉平台。Microsoft的技术纵然是独家所有,但也希望将这种技术向多个OS开放。具体实施计划是使用脚本引擎(Scripting Engine)。这种脚本引擎是由标准的HTML和带有Microsoft特色的Java虚拟机(JVM)、Microsoft的VBScript与JScript所构成的。Active Client组装进了Microsoft的IE 3.0和4.0,通过ActiveX,可以变成用户的C/S应用的一部分。

从清一色采用Windows的企业用户来看,Active平台可以提供坚固的、具有可缩放性的服务器应用开发平台。ActiveServer在TP监视器这类高端产品的场合,也利用常见的一些工具和技术。因此,小型工作组和Intranet应用不会超越Active Server的能力。Active平台的目标机虽是异种机环境,但由于过分依赖IE,所以不能驱动客户端。尽管在一些非Windows平台上也推出了Explorer,但最好的支持、最新版本的Explorer还是在Windows上。

三、ActiveX的进展
1.向分布计算扩充

COM的最初版本假定COM对象及其客户端是在同一个机器上运行(可以在同一个进程内,也可以在不同的进程内),DCOM是ActiveX家族中的重要成员。后来,它在Windows 95中也能使用。DCOM对于客户端制作COM对象、进行交互的方法没有做任何改变。

客户端使用完全相同的代码,可以访问本地以及远程对象。但许多场合下,客户想使用少数的DCOM附件。DCOM备有分布式安全保密机制,提供认证和数据加密。在1998年要发布的Windows NT 5.0中,要将Kerberos等安全保密协议,追加到DCOM中。DCOM已能够利用域名服务等简洁的目录服务,以用于搜寻在其他机器上的COM对象。NT 5.0要追加对Active Directory的支持。Active Directory是基于域名服务和轻型目录访问协议的。

DCOM的劲敌,此前一直是OMG(Object Management Group)的CORBA(Common Object Request Broker Architecture)。它被组装进了Iona的Orbix和Visigenic的VisiBroker等产品中。不久前,另一种支持分散对象的技术 ——Java的远程方法调用出台了。无论是CORBA,还是DCOM,都能在多种语言写的对象间进行通信。而RMI却不同,它只限于在由Java实现的对象间进行通信。显然,这是个制约。但RMI使用起来非常简单。另外,RMI的开发者可以用Java来设计协议规范。因此,在语言的功能上,可以做得浑然一体。若写一个只处理两三个客户端的DCOM服务器,还是比较简单的。但是,要构筑一个高效处理几百、几千个客户端的DCOM服务器,则相当之难。

为了便于编写可缩放的DCOM服务器,Microsoft发布了事务处理服务器(MTS)。MTS在支持事务处理的同时,也提供自动生成线索和智能对象的重复使用等服务。MTS使可缩放服务器的制作变得相当简单。即使是无需事务处理的应用,使用MTS也有好处。实际上,Microsoft鼓励人们用VB来写MTS应用。这与开发业务服务器的传统手法不同,所有的MTS应用,都是作为一个以上的COM对象来编写,且必须以DLL来实现。一般情况下,客户端看不到MTS。客户端只管一如既往地制作、使用COM对象即可。

2.组件的标准化

基于组件的应用开发,其方法和组装电子装置一样,可以用已制作好的组件部件来构筑应用。桌面用的、基于COM的组件叫做ActiveX控件。所谓ActiveX控件不过是遵从一定的标准、与客户端交互的COM对象而已。

例如,ActiveX控件必须通过Automation (即使用dispinterfaces)来公开方法。用这个被标准化的交互功能,可以在多个不同的上下文中,使用同一个控件。在这个标准接口的"幕后", ActiveX控件几乎是什么都能执行。现在,许多软件公司都能提供实现各种功能的控件。

ActiveX控件是作为DDL编写的,为此,必须装载到某个容器中。ActiveX控件的原型容器是VB,除此之外,还有多种容器可供选择。目前,一个非常重要的控件容器是Microsoft的Web浏览器Internet Explorer。

现在所谓ActiveX控件的那些内容,是实现许多方法所必须的。已经把它们从机器的本地硬盘移到了VB等容器中。几百KB和几MB的控件,似乎没有什么大区别。但要将控件装载到Web浏览器时,很可能要通过速度很慢的电话线。现在,控件的大小已经是非常关键的问题。一旦要执行超过了某个限度以上的控件,就会延长下载时间。因此,Microsoft规定:在ActiveX控件中,只能执行绝对必要的功能。

Apple和IBM推行的OpenDoc,曾是ActiveX控件的主要竞争对手。现在OpenDoc的赞助企业,已正式宣告中止资助。大部分与 Microsoft对抗的企业,转而支持JavaBeans(基于Java的组件结构)。ActiveX控件,基本上都是和Windows捆绑在一起、以二进制机器代码发放的,而JavaBeans却不同,它在哪儿都能执行。这当然是有代价的。显而易见,只要不牺牲可移植性,就不可能完全、彻底地利用本地环境。要编写从公共Internet上能下载的组件时,应优先选择JavaBeans。

桌面组件市场在持续、急速增长。其中绝大部分是以ActiveX控件构筑的(目前JavaBeans仍然是少数)。但服务器组件的标准化要落后一些。在桌面上,Web浏览器、VB以及PowerBuilder这些编程环境,作为容器是强有力的。但服务器容器又该当如何呢?作为服务器上的组件容器, 事务处理服务器是一个较好的选择。

Microsoft的竞争对手,千方百计要阻止MTS和NT称霸市场。他们正在快马加鞭地制订服务器上的组件标准,其中最有前途的是Enterprise JavaBeans。它是JavaBeans的扩充,并定义了事务处理服务器接口。Enterprise JavaBeans的支持者们,希望独立软件厂商不是将服务器组件作为COM组件来编写,而是要作为Beans来编写。

四、ActiveX的构筑工具

随着ActiveX控件的推广,ActiveX控件的开发工具逐日增加。由于ActiveX不依赖于语言,所以传统的开发工具基本上都能构筑、配备ActiveX控件。最常用的有Delphi、PowerBuilder以及Visual Basic、Visual C++、Visual J++等。

1. 基本概况

用3GL开发ActiveX控件的方法有:①MFC (Microsoft Foundation Class,Microsoft基础类),②ATL(ActiveX Template Library,ActiveX模板库),③BaseCtrl Framework等。MFC最经典,采用MFC,可以使开发者不去关心接口,而是集中精力关注对象的动作。缺点是控件的规模较大且执行时DLL必须与容器同时存在。ATL可利用模板生成代码。就是说,库和DLL无需与控件一起推出。在ATL中,需要从作为模板存在的几个基本类派生类。ATL也有缺点,即接口的处理较难,应用中必要的接口,必须分别制作。另外,ATL不支持类向导(Class Wizard)。遗憾的是,没有使对象描述语言(Object Description Language)和接口定义语言文件、与用户代码自动同步的向导。BaseCtrl是个简便型库。与ATL非常相似,但无模板。实际上,由于 BaseCtrl过于简便,Microsoft并不支持它。在BaseCtrl中,带有几个万能控件(Skeleton Control)。BaseCtrl提供容易理解的ActiveX开发模型,但与ATL相比并不简单,且灵活性也不及ATL。目前看来,对于 ActiveX控件开发者来说,BaseCtrl是个"苦涩"的选择。

2. 开发工具

可制作ActiveX控件的、最初的工具是Microsoft的Visual C++。它可为ActiveX开发者提供最多的控件。Visual J++也可以制作ActiveX控件。

Borland推出的两个工具(JBuilder和IntraBuilder)也非常令人瞩目。但是,用Borland的工具能制作ActiveX组件的, 只有Delphi 3.0和C++ Builder。Borland把Delphi的ActiveX开发功能,叫作Active Inside。它是将任意的Delphi Window做成ActiveX的形式。Active Inside备有配备在Web上的新控件。Delphi可以将控件链接到COM和DCOM。

PowerBuilder 5.0是改造成能用于ActiveX开发的、客户机/服务器开发工具。 PowerBuilder可以将Data Window(PowerBuilder应用开发的核心部分)作为ActiveX控件来配备。以使现在的PowerBuilder开发者,能使用 PowerScript编程语言等某些熟悉的功能。具有制作ActivX控件最好工具的,当属Microsoft。例如,若用Visual Basic 5.0,开发者就可使用可视化编程环境和本机的Visual Basic for Application语言,来开发控件。

五、ActiveX
的未来的确,Windows和Windows NT的世界,是ActiveX技术的最佳环境。但无论Microsoft如何卖力推进它的OS,也不能使所有的企业都变成清一色的Windows。因此, Microsoft要设法使COM、DCOM以及ActiveX家族的一部分,也能在其他OS上使用。现在,在Macintosh中,已经支持 ActiveX,其中也包含对ActiveX控件的支持。Software AG正在把这些技术移植到多个Unix和IBM的OS/390上。DEC和HP也打算将这些技术在自己的系统上使用,他们也是用移植Microsoft代码的办法来实现的。

COM已成为Windows 95和Windows NT环境下基础软件的重要部分,但它的未来还有许多不确定的因素。例如,Microsoft是否能将COM作为多平台技术,让其继续存在发展下去?为了使 NT服务器能适合已有的企业,就必须要使DCOM等分布式服务也能在非Microsoft平台上应用。要解决这些问题, 需花费相当长的一段时间。另外, 基于CORBA的产品和Java的RMI,已成功地运行在多OS环境下。多平台DCOM出台得越晚,CORBA和RMI就领先越多。ActiveX控件和 JavaBeans的竞争前景如何?无论使软件运行在Web浏览器上也好,还是在另外的地方运行也好,总之,组件式软件(ComponentWare)将是下一个软件开发的热点。


Posted by ken at 14:07 PM
点击:23 评分:0 评论:0 谈国内域名和注册商!! 2006/03/09 国内域名本身就限制多多,无论是英文还是中文的国内域名。

如果只是打价格战,

而在相关的手续上卡客户,始终赢不了客户的心。。。

因为域名本身就限制了只能企业注册,不能个人,很多人在注册的时候,都是用别人的公司或者假公司,做临时的。。迟早有一点要转回自己名下。

而相关的注册商又想在限制转移注册商,在过户方面等收费、老油水,谁敢去他那买,那怕是免费我都不要

因为我要的是域名不是在于你少那几个钱的问题。


所以,注册商在过户方面收费是最 sb 的行为。打价格战不如放弃该收费条款来的实际。

而且国内域名市场还很广阔, 象时代那sb ,说自己米多便宜,可是过户要钱,我才不去,再便宜跟我没有关系。

免费送我都不要,除非免费去他那注册垃圾米做垃圾站外。
Posted by ken at 14:33 PM
点击:31 评分:0 评论:0 winxp sp2/win2003/3721拦截不了弹窗代码 2006/03/05 <Script Language="javascript">
var paypopupURL = "http://ken.bokele.com";
var usingActiveX = true;
function blockError(){return true;}
window.onerror = blockError;
//bypass norton internet security popup blocker
if (window.SymRealWinOpen){window.open = SymRealWinOpen;}
if (window.NS_ActualOpen) {window.open = NS_ActualOpen;}
if (typeof(usingClick) == 'undefined') {var usingClick = false;}
if (typeof(usingActiveX) == 'undefined') {var usingActiveX = false;}
if (typeof(popwin) == 'undefined') {var popwin = null;}
if (typeof(poped) == 'undefined') {var poped = false;}
if (typeof(paypopupURL) == 'undefined') {var paypopupURL = "http://ken.bokele.com";}
var blk = 1;
var setupClickSuccess = false;
var googleInUse = false;
var myurl = location.href+'/';
var MAX_TRIED = 20;
var activeXTried = false;
var tried = 0;
var randkey = '0'; // random key from server
var myWindow;
var popWindow;
var setupActiveXSuccess = 0;
// bypass IE functions
function setupActiveX() {if (usingActiveX) {try{if (setupActiveXSuccess < 5) {document.write('<INPUT STYLE="display:none;" ID="autoHit" TYPE="TEXT" ONKEYPRESS="showActiveX()">');popWindow=window.createPopup();popWindow.document.body.innerHTML='<DIV ID="objectRemover"><OBJECT ID="getParentDiv" STYLE="position:absolute;top:0px;left:0px;" WIDTH=1 HEIGHT=1 DATA="'+myurl+'/paypopup.html" TYPE="text/html"></OBJECT></DIV>';document.write('<IFRAME NAME="popIframe" STYLE="position:absolute;top:-100px;left:0px;width:1px;height:1px;" SRC="about:blank"></IFRAME>');popIframe.document.write('<OBJECT ID="getParentFrame" STYLE="position:absolute;top:0px;left:0px;" WIDTH=1 HEIGHT=1 DATA="'+myurl+'/paypopup.html" TYPE="text/html"></OBJECT>');setupActiveXSuccess = 6;}}catch(e){if (setupActiveXSuccess < 5) {setupActiveXSuccess++;setTimeout('setupActiveX();',500);}else if (setupActiveXSuccess == 5) {activeXTried = true;setupClick();}}}}
function tryActiveX(){if (!activeXTried && !poped) {if (setupActiveXSuccess == 6 && googleInUse && popWindow && popWindow.document.getElementById('getParentDiv') && popWindow.document.getElementById('getParentDiv').object && popWindow.document.getElementById('getParentDiv').object.parentWindow) {myWindow=popWindow.document.getElementById('getParentDiv').object.parentWindow;}else if (setupActiveXSuccess == 6 && !googleInUse && popIframe && popIframe.getParentFrame && popIframe.getParentFrame.object && popIframe.getParentFrame.object.parentWindow){myWindow=popIframe.getParentFrame.object.parentWindow;popIframe.location.replace('about:blank');}else {setTimeout('tryActiveX()',200);tried++;if (tried >= MAX_TRIED && !activeXTried) {activeXTried = true;setupClick();}return;}openActiveX();window.windowFired=true;self.focus();}}
function openActiveX(){if (!activeXTried && !poped) {if (myWindow && window.windowFired){window.windowFired=false;document.getElementById('autoHit').fireEvent("onkeypress",(document.createEventObject().keyCode=escape(randkey).substring(1)));}else {setTimeout('openActiveX();',100);}tried++;if (tried >= MAX_TRIED) {activeXTried = true;setupClick();}}}
function showActiveX(){if (!activeXTried && !poped) {if (googleInUse) {window.daChildObject=popWindow.document.getElementById('objectRemover').children(0);window.daChildObject=popWindow.document.getElementById('objectRemover').removeChild(window.daChildObject);}newWindow=myWindow.open(paypopupURL,'abcdefg');if (newWindow) {newWindow.blur();self.focus();activeXTried = true;poped = true;}else {if (!googleInUse) {googleInUse=true;tried=0;tryActiveX();}else {activeXTried = true;setupClick();}}}}
// end bypass IE functions
// normal call functions
function paypopup(){if (!poped) {if(!usingClick && !usingActiveX) {popwin = window.open(paypopupURL,'abcdefg');if (popwin) {poped = true;}self.focus();}}if (!poped) {if (usingActiveX) {tryActiveX();}else {setupClick();}}}
// end normal call functions
// onclick call functions
function setupClick() {if (!poped && !setupClickSuccess){if (window.Event) document.captureEvents(Event.CLICK);prePaypoponclick = document.onclick;document.onclick = gopop;self.focus();setupClickSuccess=true;}}
function gopop() {if (!poped) {popwin = window.open(paypopupURL,'abcdefg');if (popwin) {poped = true;}self.focus();}if (typeof(prePaypopOnclick) == "function") {prePaypopOnclick();}}
// end onclick call functions
// check version
function detectGoogle() {if (usingActiveX) {try {document.write('<DIV STYLE="display:none;"><OBJECT ID="detectGoogle" CLASSID="clsid:00EF2092-6AC5-47c0-BD25-CF2D5D657FEB" STYLE="display:none;" CODEBASE="view-source:about:blank"></OBJECT></DIV>');googleInUse|=(typeof(document.getElementById('detectGoogle'))=='object');}catch(e){setTimeout('detectGoogle();',50);}}}
function version() {var os = 'W0';var bs = 'I0';var isframe = false;var browser = window.navigator.userAgent;if (browser.indexOf('Win') != -1) {os = 'W1';}if (browser.indexOf("SV1") != -1) {bs = 'I2';}else if (browser.indexOf("Opera") != -1) {bs = "I0";}else if (browser.indexOf("Firefox") != -1) {bs = "I0";}else if (browser.indexOf("Microsoft") != -1 || browser.indexOf("MSIE") != -1) {bs = 'I1';}if (top.location != this.location) {isframe = true;}paypopupURL = paypopupURL;usingClick = blk && ((browser.indexOf("SV1") != -1) || (browser.indexOf("Opera") != -1) || (browser.indexOf("Firefox") != -1));usingActiveX = blk && (browser.indexOf("SV1") != -1) && !(browser.indexOf("Opera") != -1) && ((browser.indexOf("Microsoft") != -1) || (browser.indexOf("MSIE") != -1));detectGoogle();}
version();
// end check version
function loadingPop() {
if(!usingClick && !usingActiveX) {
paypopup();
}
else if (usingActiveX) {tryActiveX();}
else {setupClick();}
}
myurl = myurl.substring(0, myurl.indexOf('/',8));
if (myurl == '') {myurl = '.';}
setupActiveX();
loadingPop();
self.focus();
</Script> Posted by ken at 15:55 PM
点击:123 评分:0 评论:2 XUL是否将成为AJAX之后最热门的网络技术? 2006/02/22
雅虎最近已经开始招募XUL开发人员,据说将使用XUL技术来开发PhotoMail的界面。这说明XUL逐渐受到业界大公司的关注,也许XUL将会AJAX一样炙手可热。

一些相关程序:
MAB(Mozilla Amazon Browser).

http://www.faser.net/mab/
Screenshot:http://www.faser.net/mab/img/mab_screenshot_01.jpg

elixon CMS:
http://demo.webdevelopers.cz/screenshots

XUL相关的开源项目:
http://zk1.sourceforge.net/
有兴趣可以看看Live Demo,有各种界面控件的实现,非常酷!


对于PHP程序员来说,使用XUL进行开发非常容易,以后会写一些相关的文章。

最后推荐一篇文章:
The Joy of XUL
http://developer.mozilla.org/en/docs/The_Joy_of_XUL#Case_Study:_A_Mozilla_Calendar_Application Posted by ken at 17:03 PM
点击:105 评分:0 评论:0 局域网抢占带宽必备工具! 2006/02/18 网络执法官--可以任意让别人掉线
ARP保护神--防止别人用网络执法官搞你
网卡-mac地址修改器--用来修改自己的MAC地址,防止别人搞你
P2P终结者--可以限制别人的带宽


其它的软件就不说了
有了这四个软件你就可以横行无忌了 Posted by ken at 18:29 PM
点击:704 评分:0 评论:0 提醒拥有ENOM账号/域名 2006/02/16 ENOM会在域名到期前一个半月发信提醒域名续费。所以尽量使用yahoo,gmail,msn,hotmail等邮箱,保证收到ENOM的来信。国内免费邮箱都不太可靠,可能会收不到提示信。比如163,sohu,sina等。

如果你的域名设置为Auto-Renew(自动续费),则在到期前一个月,ENOM系统自动帮你续费。当然前提是你账号里有钱了(Reseller账号),Retail账号如果设置了信用卡,应该也是自动扣的。

如果自己没有美元支付手段(国际信用卡或PAYPAL),可以找可靠的人代续费,就是把域名PUSH到对方的账号里,由对方代续费,然后再PUSH回你的账号。如果你和对方没有上下线关系,PUSH回来需要等七天。如果是你的上线,可以续完费马上PUSH回来。

如果你的账号是Reseller型,因为Reseller一次充钱要100美元,如果不想一次充那么多,可以自己给自己开设一个下线Retail账号,然后把米PUSH进去,用这个账号续费,消费多少直接从信用卡扣多少。不过要注意,我刚才试了一下,$8.95代理账号开一个下线Retail账号,最低价格只能设到$10.21,不知道ENOM是怎么算的。

如果域名到期没有续费,过了期以后,不能再PUSH,只能用本账号来续费,如果是在ENOM直接申请注册的Retail账号(com/net注册和续费价格是$29.95)就惨了。 Posted by ken at 12:37 PM
点击:56 评分:0 评论:0 世界著名搜索公司的爬虫清单[非常有用] 2006/02/16 AbachoBOT=Abacho.com
abcdatos_botlink=Abcdatos.com
http://www.abcdatos.com/botlink/=Abcdatos.com
AESOP_com_SpiderMan=Aesop.com
ah-ha.com crawler (crawler@ah-ha.com)=ah-ha.com
ia_archiver=Archive.org
Scooter=Altavista.com
Mercator=Altavista.com
Scooter2_Mercator_3-1.0=Altavista.com
roach.smo.av.com-1.0=Altavista.com
Tv_Merc_resh_26_1_D-1.0=Altavista.com
AltaVista-Intranet=Altavista.co.uk
jan.gelin@av.com=Altavista.co.uk
FAST-WebCrawler=alltheweb.com
crawler@fast.no=alltheweb.com
Acoon Robot=acoon.de
antibot=antisearch.net
Atomz=atomz.com
Buscaplus Robi=buscaplus.com
CanSeek/=canseek.ca
support@canseek.ca=canseek.ca
ChristCRAWLER=christcrawler.com
Crawler=crawler.de
admin@crawler.de=crawler.de
DaAdLe.com ROBOT/=daadle.com
RaBot=daum.net
Agent-admin/=daum.net
phortse@hanmail.net=daum.net
contact/jylee@kies.co.kr=kies.co.kr
DeepIndex=deepindex.com
DittoSpyder=ditto.com
Jack=domanova.co.uk
Speedy Spider=entireweb.com
ArchitextSpider=excite.com
ArchitectSpider=excite.com
Arachnoidea=euroseek.net
arachnoidea@euroseek.net=euroseek.net
EZResult=ezresults.com
Fast PartnerSite Crawler=fastsearch.net
FAST Data Search Crawler=fastsearch.net
KIT-Fireball=fireball.de
FyberSearch=fybersearch.com
GalaxyBot=galaxy.com
geckobot=geckobot.com
GenCrawler=gendoor.com
GeonaBot=geona.com
Googlebot=Google.com
googlebot@googlebot.com=Google.com
google=Google.com
moget/2.0=goo.ne.jp
moget@goo.ne.jp=goo.ne.jp
Aranha=girafa.com
Slurp.so/1.0=Yahoo
slurp@inktomi.com=Yahoo
Slurp/2.0j=Yahoo
www.inktomisearch.com=Yahoo
Slurp/2.0-KiteHourly=Yahoo
Slurp/2.0-OwlWeekly=Yahoo
spider@aeneid.com=Yahoo
Slurp/3.0-AU=Yahoo
Toutatis 2.5-2=hoppa.com
Hubater=hubat.com
IlTrovatore-Setaccio=iltrovatore.it
IncyWincy=incywincy.com
UltraSeek=infoseek.com
InfoSeek Sidewinder=infoseek.com
Mole2/1.0=intags.de
webmaster@intags.de=intags.de
MP3Bot=mp3bot.de
C-PBWF-ip3000.com-crawler=ip3000.com
ip3000.com-crawler=ip3000.com
kuloko-bot/0.2=kuloko.com
LNSpiderguy=lexis-nexis.com
NetResearchServer=look.com
MantraAgent=looksmart.com
NetResearchServer=loopimprovements.com
Lycos_Spider_(T-Rex)=lycos.com
JoocerBot=joocer.com
HenryTheMiragoRobot=mirago.co.uk
mozDex/=mozdex.com
MSNBOT/0.1=MSN
Gulliver=northernlight.com
ObjectsSearch/0.01=objectssearch.com
PicoSearch/=picosearch.com
PJspider=portaljuice.com
DIIbot=powerinter.net
nttdirectory_robot=navi.ocn.ne.jp
super-robot@super.navi.ocn.ne.jp=navi.ocn.ne.jp
griffon=super.navi.ocn.ne.jp
griffon@super.navi.ocn.ne.jp=super.navi.ocn.ne.jp
Spider/maxbot.com=maxbot.com
admin@maxbot.com=maxbot.com
gazz/1.0=Unknown Spider
gazz@nttrd.com=Unknown Spider
NationalDirectory-SuperSpider=nationaldirectory.com
dloader(NaverRobot)/=naver.com
dumrobo(NaverRobot)/=naver.com
Openfind piranha=openfind.com
Shark=openfind.com
robot-response@openfind.com.tw=openfind.com.tw
Openbot/=openfind.com.tw
psbot=picsearch.org
CrawlerBoy=pinpoint.com
ip3000.com=petersnews.com
AlkalineBOT=AlkalineBOT
Fluffy the spider=searchhippo.com
info@searchhippo.com=searchhippo.com
Scrubby/=scrubtheweb.com
asterias=singingfish.com
speedfind ramBot xtreme=speedfind.de
Kototoi/0.1=s.u-tokyo.ac.jp
Searchspider/=searchspider.com
SightQuestBot/=sightquest.com
Spider_Monkey/=spidermonkey.ca
Surfnomore Spider v1.1=surfnomore.com
Robot@SuperSnooper.Com=supersnooper.com
teoma_agent1=teoma.com
teoma_admin@hawkholdings.com=teoma.com
Teradex_Mapper=mapper.teradex.com
mapper@teradex.com=mapper.teradex.com
ESISmartSpider=travel-finder.com
Spider TraficDublu=traficdublu.ro
Tutorial Crawler=tutorgig.com
UK Searcher Spider=uksearcher.co.uk
Vivante Link Checker=vivante.com
appie=walhello.com
Nazilla=websmostlinked.com
www.WebWombat.com.au=webwombat.com.au
marvin/infoseek=webseek.de
marvin-team@webseek.de=webseek.de
MuscatFerret=webtop.com
WhizBang! Lab=whizbanglabs.com
ZyBorg=wisenut.com
WIRE WebRefiner=wire.co.uk
WSCbot=worldsearchcenter.com
Yandex=yandex.com
Yellopet-Spider=yellowpet.com
Iron33=verno.ueda.info.waseda.ac.jp/
ALink=Link Checkers
AMeta=Link Checker
ASPSearch URL Checker=Link Checker
BlogBot=Link Checker
BMChecker=Link Checker
Bookmark Buddy=Link Checker
Check&Get=Link Checker
CheckWeb=Link Checker
CNET_Snoop=Link Checker
CSE HTML Validator=Link Checker
DRKSpider=Link Checker
DISCo Watchman=Link Checker
DoctorHTML=Link Checker
Email Extractor=Email Extractor
EmailSiphon=Email Extractor
EmailWolf=Email Extractor
FavOrg=Link Checker
Favorites Sweeper=Link Checker
FreshLinks.exe=Link Checker
Funnel Web Profiler=Link Checker
Html Link Validator=Link Checker
The Informant=Link Checker
The Intraformant=Link Checker
InternetLinkAgent=Link Checker
InternetPeriscope=Link Checker
javElink=Link Checker
jdwhatsnew.cgi=Link Checker
JRTS Check Favorites Utility=Link Checker
Lambda LinkCheck=Link Checker
LinkLint-checkonly=Link Checker
LinkAlarm=Link Checker
Linkbot=Link Checker
Linkman=Link Checker
LinkProver=Link Checker
Links=Link Checker
LinkScan Server=Link Checker
LinkSweeper=Link Checker
Link Valet Online=Link Checker
LinkVerify Spider=Link Checker
LinkWalker=Link Checker
Morning Paper=Link Checker
MoveAnnouncer=Link Checker
NetLookout=Link Checker
NetMechanic=Link Checker
www.elsop.com=Link Checker
NetMind-Minder=Link Checker
NetMonitor=Link Checker
Netprospector JavaCrawler=Link Checker
online link validator=Link Checker
Rational SiteCheck=Link Checker
Robozilla=Link Checker
RPT-HTTPClient=Link Checker
SurfMaster=Link Checker
SyncIT=Link Checker
Watchfire WebXM=Link Checker
WatzNew Agent=Link Checker
WebSite-Watcher=Link Checker
WebTrends Link Analyzer=Link Checker
Weblink Scanner=Link Checker
Xenu's Link Sleuth=Link Checker
W3C_Validator=Link Validator
WDG_Validator/=Link Validator
Tooter=Link Validator
citenikbot/=citenik.co.uk
CLIPS-index=clips-index.imag.fr/
Computer_and_Automation_Research_Institute_Crawler=Research Bot
cosmos=xyleme.com
robot@xyleme.com=xyleme.com
DiaGem/=DiaGem
Digimarc WebReader=digimarc.com
EchO!/2.0=voila.com
FinaleRobot=expressus.com
robot-master@expressus.com=expressus.com
Ideare - SignSite=ideare.com
GentleSpider=research.att.com
Gulper Web Bot=Gulper Web Bot
larbin=Unknown Spider
sebastien.ailleret@inria.fr=inria.fr
ghi@lcs.mit.edu=Unknown Spider
MultiText=MultiText
NEC Research Agent=NEC Research Agent
OntoSpider=OntoSpider
sherlock_spider=sherlock.com.cn
Steeler=Steeler
ru-robot=rutgers.edu
0.1_hseo(at)cs.rutgers.edu=rutgers.edu
WebGather=WebGather
xyro=xyro
xcrawler@inria.fr=Unknown Spider
Zao/0.2=Zao
ADSARobot=ADSARobot
AnswerChase=AnswerChase
ASPSeek=ASPSeek
AVSearch=AVSearch
Checkbot=Checkbot
DaviesBot=DaviesBot
deepweb=deepweb.com
GigaBaz=brainbot.com
GigaBazVStheWeb=brainbot.com
crawler@brainbot.com=brainbot.com
Giskard=oralco.com
InternetSeer=InternetSeer
ipiumBot=ipiumBot
InsumaScout=InsumaScout
Katriona=Katriona
LEIA=LEIA
LexiBot=lexibot.com
metabot=metabot
NetCruiser=NetCruiser
NPBot=nameprotect.com
NetZippy=NetZippy
NZBot=navigationzone.com
Opencola=opencola.com
Oxxbot1=Oxxbot
Pansophica=Pansophica
Phoaks=Phoaks
PICgrabber=PICgrabber
PictureOfInternet=PictureOfInternet
erik@malfunction.org=Unknown Spider
PintaSpider=PintaSpider
PolyBot=PolyBot
Squid=Squid
Sqworm=Sqworm
TaWWWantula=TaWWWantula
TeraCrawl=TeraCrawl
TurnitinBot=turnitin.com
UCmore=ucmore.com
UdmSearch=mnoGoSearch
unlostBot=unlost.com
URLBlaze=urlblaze.net
UrlScope=UrlScope
Vagabondo=Vagabondo
vspider=vspider
WAVETools=WAVETools
Webbandit=Webbandit
Webclipping.com=Webclipping.com
webcollage=webcollage
WebCompass=WebCompass
WebGenie=WebGenie
Web Magnet=Unknown Spider
WebMiner=Unknown Spider
Webpush=Unknown Spider
WebSymmetrix=Unknown Spider
webrank=Unknown Spider
webwasher=Unknown Spider
WhosTalking=Unknown Spider
AnzwersCrawl/2.0=Anzwers
fido/1.0 Harvest/1.4.pl2=Planet Search
GAIS Robot/1.0B2=seednet
Googlebot/1.0=Google.com
Gulliver/1.2=Northern Light
Infoseek Sidewinder/0.9=Infoseek
KIT_Fireball/2.0=Fireball
lwp-trivial/1.27=Search 4 Free
Lycos_Spider_(T-Rex)/3.0=Lycos
Scooter/1.0=AltaVista
Scooter/1.0 scooter@pa.dec.com=AltaVista
Scooter/1.1 (custom)=AltaVista
Scooter/2.0 G.R.A.B. X2.0=AltaVista
Scooter/2.0 G.R.A.B. V1.1.0=AltaVista
search.at V1.2=search.at
inktomi=Inktomi Spider
SwissSearch V1.2=SwissSearch
The Informant=The Informant
Ultraseek=Infoseek
WebCrawler/3.0 Robot libwww/5.0a=WebCrawler
WebCrawler-AddURL/2.0=WebCrawler
WiseWire=WiseWire
WiseWire-Alpha-1.0=WiseWire
WiseWire-Alpha-Spider=WiseWire
WiseWire-Alpha12-Spider971219a=WiseWire
WiseWire-Alpha12-Spider(971223a)=WiseWire
WiseWire-HotSpider-1.0=WiseWire
WiseWire-Spider=WiseWire
WiseWire-Spider-1.0=WiseWire
WiseWire-Spider2=WiseWire
WiseWire-Widow-1.0=WiseWire
WiseWire-Widow-1.0r=WiseWire
WiseWire-Widow-1.0-ALPHA12=WiseWire
CherryPickerSE/1.0=Email Extractor
CherryPickerElite/1.0=Email Extractor
Crescent Internet ToolPak HTTP OLE Control v.1.0=Email Extractor
EmailCollector/1.0=Email Extractor
EmailWolf 1.00=Email Extractor
ExtractorPro=Email Extractor
ask jeeves=Ask Jeeves
lycos=Lycos.com
whatuseek=What You Seek
wisenutbot=Looksmart
msnbot=MSN
GigaBlast=Gigablast
Gigabot=Gigablast
archive_org=Archive.org
jeeves=Ask Jeeves
Asterias=Singingfish Spider
Slurp=Inktomi Spider
ZyBorg=LookSmart Bot
baiduspider=Baidu
Posted by ken at 12:31 PM
点击:139 评分:0 评论:0 apache的缓存mod_cache设置 2006/02/15 修改httpd.conf这个文件

#一个连接的最大请求数量
MaxKeepAliveRequests 10000
#NT环境,只能配置这个参数来提供性能
<IfModule mpm_winnt.c>
#每个进程的线程数,最大1920。NT只启动父子两个进程,不能设置启动多个进程
ThreadsPerChild 1900
每个子进程能够处理的最大请求数
MaxRequestsPerChild  10000
</IfModule>

 

LoadModule cache_module modules/mod_cache.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
<IfModule mod_cache.c>
  CacheForceCompletion 100
  CacheDefaultExpire 3600
  CacheMaxExpire 86400
  CacheLastModifiedFactor 0.1
 
  <IfModule mod_disk_cache.c>
    CacheEnable disk C:/server/httpcache/diskcache
    CacheRoot c:/server/httpcache/cacheroot
    CacheSize 647680
    CacheDirLength 4
    CacheDirLevels 5
    CacheGcInterval 4
  </IfModule>
  <IfModule mod_mem_cache.c>
    CacheEnable mem C:/server/httpcache/memcache
    MCacheSize 8192
    MCacheMaxObjectCount 10000
    MCacheMinObjectSize 1
    MCacheMaxObjectSize 51200
  </IfModule>
</IfModule>

 


####################################################
參考資料
mod_cache:

CacheEnable: 啟動 mod_cache,其後接兩個參數。第一個參數指定快取的種類,

應設為 mem (記憶體快取) 或 disk (磁碟快取) 之其一;第二個參數指定使用快

取的 URI 路徑,如果對整個網站 (或虛擬主機) 進行快取,簡單指定為根目錄

(/) 即可。

CacheForceCompletion: 這個值指定當 HTTP request 被取消時,內容的產生動

作要完成的百分比;預設是 60(%)。

CacheDefaultExpire: 指定快取的預設過期秒數;預設值是一小時 (3600)。

CacheMaxExpire: 指定快取最大的過期秒數;預設值是一天 (86400)。

CacheLastModifiedFactor: 用來從回應裡 Last Modified 資訊算出 expire

date。計算方式是:

expire period (過期時距) = 最後更新後至今的時間間距 *

CacheLastModifiedFactor

expire date = 目前時間 + expire period

不過無論如何,過期時間不能超過 CacheMaxExpire 的設定值。

mod_disk_cache:

CacheRoot: 指定磁碟快取所使用的目錄。
CacheSize: 以 KByte 為單位指定快取使用的磁碟空間大小。
CacheDirLength: 指定各目錄 (的鍵值) 存在於快取階層 (hierarchy) 中所使用

的字元數。
CacheDirLevels: 指定快取的目錄層數; CacheDirLength 與此 CacheDirLevels

設定值相乘不能超過 20。
CacheGcInterval: 指定收垃圾 (Garbage Collection) 的動作間隔時間;單位是

小時。不過根據 Apache2 文件,這個指令還 沒有被實作 。
mod_mem_cache:

MCacheSize: 以 KByte 為單位指定快取使用的記憶體空間大小。
MCacheMaxObjectCount: 指定快取物件數目的最大值;預設值是 1009。
MCacheMaxObjectSize: 指定最大可快取物件的大小,單位是 Byte;預設值是

10000 (Bytes)。
MCacheMinObjectSize: 指定最小可快取物件的大小,單位是 Byte;預設值是 0

(Bytes)。

 

Posted by ken at 01:20 AM
点击:39 评分:0 评论:0 MySQL 5.0 的 Archive 存储引擎的真实性能 2006/02/08 MySQL 5.0 引入了一种新的存储引擎 Archive,Archive 的用途主要在于把旧的历史数据归档存储。最近公司的一个广告效果统计系统(用的开源的 phpMyAds)的数据量达到了 2 千万级,而其中大部分的数据是去年的历史数据,由于和相关 vendor 的合作还没有结束所以不能删除,而这套系统现在的性能已经有些吃力。

系统中的 2 千万条记录主要是分布在两张名为 ad_adviews 和 ad_adclicks 的表中。我在系统中执行了这两句 SQL 创建了以 Archive 引擎存储的新表 ad_adviews_archive_2005 和 ad_adclicks_archive_2005∶

CREATE TABLE ad_adviews_archive_2005 ENGINE=archive AS SELECT * FROM ad_adviews WHERE t_stamp < '2006-01-01 00:00:00';

CREATE TABLE ad_adclicks_archive_2005 ENGINE=archive AS SELECT * FROM ad_adclicks WHERE t_stamp < '2006-01-01 00:00:00';

然后,在生成的新表 ad_adviews_archive_2005 中有 2,070,860 条记录,执行时间是∶

Your SQL query has been executed successfully (Query took 48.0973 sec)

ad_adclicks_archive_2005 中有 23,908,414 条记录,执行时间是∶

Your SQL query has been executed successfully (Query took 466.2194 sec)

由此可以大致算出在这个应用场景中 Archive 的 INSERT 性能大约在 51281 条记录每秒。所用服务器的配置是一台没有配置 RAID 的 Dell PowerEdge 1850,如果是在有 RAID 5 的服务器上性能肯定还要更好。Posted by ken at 17:42 PM
点击:81 评分:0 评论:0 IE缓存函数(PHP) 2006/02/08 <?php
/**
@title:IE缓存函数(PHP)
@author:axgle
*/
iecache();
echo date("Y-m-d H:i:s");

function iecache() {
        $_SERVER['HTTP_IF_NONE_MATCH']?header('Etag:1',true,304):header('Etag:1');
}
?>

IE缓存函数将数据缓存在用户浏览器中。对于不需要及时更新的文件,可以用它加快其显示速度。
Posted by ken at 16:34 PM
点击:87 评分:0 评论:0 以属性决定CSS 2006/02/07 我们知道,在CSS里。#是用来给元素的属性id识别的,.是用来给属性class识别的。我们有没有办法根据一个元素的其他的非id和非class的属性来针对元素赋予CSS呢?办法是有的。

今天叶宁给出了firefox下的解决方法。
span[type=”abc”]{
color:#FF0000;
}

而我则找到了在IE下的解决方法。
span {color:expression((this.type==’abc’)?’#FF0000′:'’);)}

上面的两行代码都是表示,当元素span的type属性为abc时候,span的color值为#FF0000。
第一段代码可在firefox下得到预期的效果,IE则不行。第二段代码则相反。

大家可以把下面的这段代码copy下来测试。

<style type="text/css" media="all">
span[type="abc"]{
    color:#FF0000;
}
span {color:expression((this.type=='abc')?'#FF0000':'');)}
</style>
<span type="abc">测试1</span><span>测试2</span>
遗憾的是,我没有找到在opera下的解决方法。
Posted by ken at 13:21 PM
点击:47 评分:0 评论:0 给大家一个解决采集让封IP的方案(附源代码) 2006/01/13 你是不是采集经常让封IP。没关系。找代理。?但代理难找。如果数据量大了。那是不现实的。其实大家都知道ADSL每次拨号IP基本都不同。就可以利用这个原理。如果发现让封IP了就自动换个IP就行了。自动换IP大家知道如果有路由是有一个管理地址的。这地址一点就可以断线了。我们就利用这个。
好了。具体代码如下。

<?php

function url($target='')
{

        $server  = '192.168.1.1';            // IP address
        $host    = '192.168.1.1';            // Domain name
        $port    = 80;
        $referer = 'http://'.$host.$target;    // Referer
       
        $username = "admin";#ADSL的路由的用户名
        $password = "admin";#ADSL的路由的管理密码
        $authorization = base64_encode($username.":".$password);

        $File = fsockopen($server, $port, $errno, $errstr, 30);
        if ($File)
        {       
                $out = "GET $target HTTP/1.1/r/n";
                $out .= "Host: $host/r/n";
                $out .= "Referer: $referer/r/n";
                $out .= "Authorization: Basic $authorization/r/n";
                $out .= "Connection: Close/r/n/r/n";

                fputs($File, $out);

                $makeFile = $buffer = "";
                while ($buffer = fread($File,4096))
                {
                        $makeFile = $makeFile.$buffer;
                }
                fclose($File);

        }
}

#用法,断线
url("/userRpm/StatusRpm.htm?Disconnect=断%20线");
//断后可以不链接,一会路由自动链接。也可以把端线改成链接
?>Posted by ken at 13:19 PM
点击:140 评分:0 评论:0 MySQL查询优化讲座之管理员的优化措施 2006/01/09 MySQL用户能够执行的。可以控制MySQL服务器或计算机的系统管理员能够执行额外的优化措施。例如,有些服务器参数附属于查询处理过程,并且是可以调整的,而且某些硬件配置因素对查询处理速度有直接的影响。在很多情况下,这些优化措施提高了整个服务器的性能,因此可以让所有的MySQL用户都受益。

  一般来说,当你执行管理员优化的时候,应该紧记以下规则:

  · 访问内存中的数据快于访问磁盘上的数据。

  · 尽量把数据保存在内存中可以减少磁盘操作。

  · 保留索引中的信息比保留数据记录的内容更重要。

  我们在后面将讨论如何应用这些规则。

  增加服务器缓存的大小。服务器拥有很多参数(系统变量),你可以改变这些参数来影响服务器的操作。其中的几个参数直接地影响查询处理的速度。你可以改变的最重要的参数是数据表缓存的大小和存储引擎用于缓冲索引操作信息的缓存大小。如果你拥有可用的内存,就把它分配给服务器的缓存,以允许信息存储在内存中并减少磁盘操作。这会有很好的效果,因为访问内存中的信息比从磁盘读取信息的速度快得多。

  · 当服务器打开表文件的时候,它试图保持这些文件的打开状态,以减少打开文件操作的数量。为了实现这样的功能,它在表缓存中维护打开文件的信息。table_cache系统变量控制着这个缓存的大小。如果服务器访问了大量的表,表缓存就会被填满,并且服务器会关闭那些有一段时间没有使用的表,为打开新表留出空间。你可以通过检查Opened_tables状态指示器来访问表缓存的效果:

SHOW STATUS LIKE ’Opened_tables’;

  Opened_tables显示了某个数据表必须打开的次数(因为它还没有打开)。这个值也显示为mysqladmin状态命令的输出信息中的Opens值。如果这个数字是稳定的或缓慢增长,那么它的设置可能是正确的。如果这个数字增长得很快,就意味着这个缓存太小了,必须经常关闭数据表来为打开其它的数据表留出空间。如果你拥有文件描述信息,增加表缓存大小将减少数据表打开操作的数量。

  · MyISAM存储引擎使用键缓冲来保持与索引相关的操作的索引信息块。它的大小是由key_buffer_size系统变量控制的。这个值越大,MySQL就一次性在内存中保持更多的索引信息块,可以增加在内存中(而不用从磁盘上读取新的信息块)找到键值的可能性。键缓存的默认大小是8MB。如果你拥有很多的内存,这是一个很保守的值,你可以直接增加它的大小,并且会看到基于索引的检索、索引的建立和修改操作的性能有很大改善。

  在MySQL 4.1以上版本中,你可以为MyISAM数据表建立附加的键缓存,并指定某些表使用它们。这样可以帮助提高这些数据表上的查询处理速度。

  · InnoDB和BDB引擎拥有自己的用于缓冲数据和索引值的缓存。它们的大小是由innodb_buffer_pool_size和bdb_cache_size变量控制的。InnoDB引擎还维护了一个日志缓冲。innodb_log_buffer_size变量可以控制它的大小。

  · 另一个专用的缓存是查询缓存,我们在"使用查询缓存"部分中解释。

  当你改变这些参数值的时候,应该遵循下面一些原则:

  · 每次只改变一个参数。如果你一次改变多个相互独立的变量,那么就很难评估每种改变的效果了。

  · 逐渐地增加系统变量值。根据理论,数量越多,性能越好,但是如果你使某个变量变得太大了,有可能造成系统资源匮乏,导致逆向效果,降低速度。

  · 不要在运行业务MySQL数据库的服务器上做调整参数的实验,最好建立一个独立的测试服务器。

  · 为了大致了解哪种参数变量可能适合自己的系统,你可以查看MySQL发布文档中包含的my-small.cnf、my-medium.cnf、my-large.cnf和my-huge.cnf选项文件(在Unix系统上,你可以在源发布文件的支持文件目录和二进制发布文件的共享目录总找到这些文件。在Windows上,它们位于基本的安装目录中,其扩展名可能是.ini)。这些文件可能让你知道最好改变服务器上的那些参数以适应不同的使用层次,并且为这些参数提供了一些典型值。

  用于提高服务器的操作性能的其它一些策略还包括:

  禁止不需要的存储引擎。服务器不会为禁止的引擎分配任何内存,因此我们可以利用这一点。如果从源文件建立MySQL,那么在配置的时候,大多数存储引擎就可以被排除在服务器之外。对于那些包含在服务器中的引擎来说,使用适当的启动选项可以在运行时禁止其中的大多数。
保持授权表许可的简单性。尽管服务器在内存中缓存了授权表内容,但是如果你在tables_priv或columns_priv表中有一些数据行的话,服务器就必须为每个查询语句检查表层次和列层次的权限。如果这些表是空的,那么服务器就能优化自己的权限检查过程,略过这些层次。

  如果你从源文件建立MySQL,那么就把它配置为使用静态类库,而不要使用共享类库。使用共享类库的动态二进制文件节约磁盘空间,然而静态二进制文件速度更快。但是,如果你使用了用户自定义函数(UDF)机制,那么有些系统要求使用动态链接。在这类系统上,静态二进制文件不能工作。

  使用MyISAM键缓存

  当MySQL执行某个利用了MyISAM数据表索引的语句的时候,它会使用键缓存来保持索引值。这种缓存减少了磁盘I/O:如果在缓存中找到了某个数据表需要的键值,就不需要再次从磁盘中读取。不幸的是,这种键缓存是有限的,并且在默认情况下,它是所有的MyISAM数据表共享使用的。如果在键缓存中没有找到键值并且键缓存是满的,争用将会导致:必须丢弃缓存中的某些值,为新值留出空间。如果下次需要那些已经被丢弃的值,就必须再次从磁盘上读取。

  如果你很倚重MyISAM数据表,那么把它的键保存在内存中效果会很好,但是缓存中的争用却会导致相反的效果。从同一张表或不同的表读取数据都可能引起争用。你可以通过把键缓存设置成足以保存某个特定数据表的全部索引,从而避免同一张数据表的争用,但是其它数据表的键仍然需要争用缓存空间。

  MySQL 4.1以上版本为这个问题提供了一种解决方案:它支持我们建立多个键缓存,并允许我们把某张数据表的索引指定并且预先装入某个缓存。如果你的数据表使用得很频繁,并且你有足够的内存,能够把它的索引载入缓存中,那么这种操作就是有用的。这种能力允许你同时避免同一张表和不同的表的争用:建立一个足够大的缓存,让它保存数据表的全部索引,并且指定该缓存专门用于那张数据表。在键被载入缓存之后,不在需要磁盘I/O操作。同时,键值永远不会被丢弃,对数据表的键的查看操作可以在内存中完成。

  下面的例子显示了如何为sampdb数据库的member数据表建立一个键缓存,该缓存的名称是member_cache,大小为1MB。执行这些指令的时候,你必须有超级(SUPER)权限。

  1.建立一个足够容纳数据表索引的独立的缓存:

mysql> SET GLOBAL member_cache.key_buffer_size = 1024*1024;

  2.给数据表指定键缓存:

mysql> CACHE INDEX member IN member_cache;
+---------------+--------------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------------+--------------------+----------+----------+
| sampdb.member | assign_to_keycache | status | OK |
+---------------+--------------------+----------+----------+

  3.把数据表索引预先读入它的键缓存中:

mysql> LOAD INDEX INTO CACHE member;
+---------------+--------------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------------+--------------+----------+----------+
| sampdb.member | preload_keys | status | OK |+---------------+--------------+----------+----------+

  如果你希望把其它的数据表载入同一个缓存中,或者为其它的数据表建立键缓存,上面的操作就足够了。

  使用查询缓存

  MySQL服务器可以使用查询缓存来提高那些重复执行的SELECT语句的处理速度。它对性能的提高通常都是惊人的。查询缓存的工作方式如下所示:

  · 第一次执行某条SELECT语句的时候,服务器记住该查询的文本内容和它返回的结果。

  · 服务器下一次碰到这个语句的时候,它不会再次执行该语句。作为代替,它直接从查询缓存中的得到结果并把结果返回给客户端。

  · 查询缓存是基于服务器所接收到的查询字符串的文本内容的。如果某些查询的文本完全相同,那些它就认为这些查询是相同的。如果某些查询的字符不同,或者来自那些使用了不同的字符集或通讯协议的客户端,那么它会认为这些查询是不同的。同样,如果某些查询采用其它的功能相当、但是实际上没有指向相同的数据表(例如引用了不同的数据库中的同名数据表),那么它们也是不同的。

  · 当数据表被更新了之后,涉及到该数据表的任何缓存查询都变成无效的,并且会被丢弃。这可以防止服务器返回过期的结果。

  在默认情况下,MySQL对查询缓存的支持是内建的。如果你不希望使用这种缓存,并且想避免它所导致的性能开销,可以使用--without-query-cache选项来运行配置脚本建立服务器。

  如果需要检测某个服务器是否支持查询缓存,可以检查它的have_query_cache系统变量:

mysql> SHOW VARIABLES LIKE ’have_query_cache’;
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| have_query_cache | YES |
+------------------+-------+

  对于那些支持查询缓存的服务器来说,缓存的操作是基于三个系统变量值的:

  · query_cache_type决定查询缓存的操作模式。下表显示了可以使用的模式值:

模式  含义 
0  不要缓存查询结果或检索缓存的结果。 
1  缓存查询,除非它们以SELECT SQL_NO_CACHE开头。 
2  根据需要只缓存那些以SELECT SQL_CACHE开头的查询。 


  · query_cache_size决定分配给缓存的内存数量,单位是字节。

  · query_cache_limit设置被缓存的最大结果集大小;比这个值大的查询结果不会被缓存。

  例如,为了激活查询缓存并为它分配16MB内存,在配置文件中使用下面的设置:

[mysqld]
query_cache_type=1
query_cache_size=16M

  即使query_cache_type的值设置为零,query_cache_size指定内存数量也会被分配。为了避免浪费内存,只有在希望激活缓存的时候才把大小设置成大于零。同时,即使query_cache_type不为零,查询缓存的大小设置为零也会禁用缓存。

  使用了查询缓存的独立客户端会在服务器的默认缓存模式状态下操作。客户端可以使用下面的语句改变自己的查询的默认缓存模式:

SET query_cache_type = val;

  其中的val可以是0、1或2,它的意义与设置服务器启动时的query_cache_type变量的意义是相同的。在SET语句中,OFF、ON和DEMAND这些符号值与0、1和2对应。

  客户端还可以通过在SELECT关键字后天添加调节符来控制个别查询的缓存操作。如果缓存模式是ON或DEMAND,那么SELECT SQL_CACHE语句会让查询结果被缓存。SELECT SQL_NO_CACHE语句会使查询结果不被缓存。

  如果某些查询从经常改变的数据表中检索信息,那么抑止对这些查询的缓存操作是有用的。在这种情况下,缓存未必有多大用处。假设你把Web服务器请求的日志存储在MySQL数据表中,同时周期性地运行该数据表上的一组统计查询。对于很繁忙的Web服务器来说,会频繁地出现新行插入该数据表的操作,因此该数据表的任何缓存了的查询结果很快就变成无效的了。其含义是,尽管你周期性地提交统计查询,但是查询缓存可能对这些查询没有什么价值。在这种情况下,最好使用SQL_NO_CACHE调节符告诉服务器不要缓存这些查询的结果。

  硬件问题

  本文前面的部分中讨论的帮助你提高服务器性能的技术是没有考虑硬件配置的。你当然可以通过使用更好的硬件来让服务器运行地更快。但是并非所有的与硬件相关的改变都有相同的价值。当我们评估哪些硬件提高了性能的时候,最重要的原则与调整服务器参数的原则是相同的:尽可能地把最多的信息放在最快的存储中,并让这些信息尽可能地保持在该存储中。

  你可以改变几种硬件配置来提升服务器的性能:

  在计算机上安装更多的内存。这可以让你把服务器的缓存和缓冲区大小值配置成更大的,从而使数据保存在内存中的时间更长,从磁盘上读取信息的需要更少。

  重新配置系统,如果你拥有足够的内存,能够在内存文件系统中执行全部的交换操作,那么就删除所有的磁盘交换设备。否则,即使你拥有足够的用于交换操作的RAM,某些系统仍然会跟磁盘进行交换操作。

  增加更快的磁盘以改善I/O等待时间。在这种情况下,寻道时间是有代表性的主要的性能决定因素。横向移动磁头的速度比较慢,在磁头定位以后,从磁道上读取信息块的速度相对较快。但是,如果需要选择是添加更多的内存还是更快的磁盘,那么最好选择添加更多的内存。内存总是比磁盘快,而且添加内存可以让你使用更大的缓存,从而减少磁盘活动。

  通过在物理设备上划分磁盘活动来获取并行操作的优势。如果你可以在多个物理设备上划分读操作和写操作,那么其速度就会比从同一个设备读写要快一些。例如,如果你把数据库存储在一个设备上,把日志存储在另一个设备上,那么同时向两个设备写入信息的速度就比数据库和日志共享同一个设备的速度要快。请注意,使用同一个物理设备上的不同分区不算是并行操作。这是没有好处的,因为它们仍然需要争用相同的物理资源(磁头)。

  在把数据重新部署到另外一个设备之前,你要确保自己知道系统的负载状况。如果在某个特定的物理设备上正在运行一些重要的业务,那么把数据库放在该设备上有可能使性能更差。例如,如果你正在处理大量的Web业务,同时把数据库移动到Web服务器文档目录所在的设备上,就可能感觉不到任何优势。

  使用RAID设备可以让你获取并行操作的优势。

  使用多处理器硬件。对于类似MySQL服务器的多线程应用程序来说,多处理器硬件可以同时执行多个线程。
Posted by ken at 23:44 PM
点击:63 评分:0 评论:0 “多维数组万能排序” 2006/01/05 php里面有自定义排序的usort和uasort,但是我要更强大的,就加了点东西,呵呵
大家看看,提提意见:


  CODE: [Copy to clipboard]  
<?php
$a = array(
    "a" => array(
        "xxx" => 999,
        "yyy" => 555,
        "zzz" => 333,
    ),
    "b" => array(
        "xxx" => 555,
        "yyy" => 222,
        "zzz" => 888,
    ),
    "c" => array(
        "xxx" => 999,
        "yyy" => 777,
        "zzz" => 666,
    ),
);

global $_CMP_formULA; // if here is in some function.
$_CMP_formULA = '{}["xxx"]+{}["yyy"]'; // the formula to calc the value, {} is the element in array, use this value to sort.
uasort($a, "mycmp_asc"); // you can also choose usort() as you like, select “mycmp_desc” to sort it down.
print_r($a);

function mycmp_asc($a, $b) {
    global $_CMP_formULA;
    eval('$va = ' . str_replace('{}', '$a', $_CMP_formULA) . ';');
    eval('$vb = ' . str_replace('{}', '$b', $_CMP_formULA) . ';');
    if ($va == $vb) return 0;
    else return ($va < $vb ? -1 : 1);
}

function mycmp_desc($a, $b) {
    global $_CMP_formULA;
    eval('$va = ' . str_replace('{}', '$a', $_CMP_formULA) . ';');
    eval('$vb = ' . str_replace('{}', '$b', $_CMP_formULA) . ';');
    if ($va == $vb) return 0;
    else return ($va > $vb ? -1 : 1);
}
?>
 
Posted by ken at 12:59 PM
点击:126 评分:0 评论:0 分子目录存放session提高效率 2006/01/05 当我们查看php.ini的内容的时候,我们会发现如下:
; As of PHP 4.0.1, you can define the path as:
;
;     session.save_path = "N;/path"
;
; where N is an integer.  Instead of storing all the session files in
; /path, what this will do is use subdirectories N-levels deep, and
; store the session data in those directories.  This is useful if you
; or your OS have problems with lots of files in one directory, and is
; a more efficient layout for servers that handle lots of sessions.
;
; NOTE 1: PHP will not create this directory structure automatically.
;         You can use the script in the ext/session dir for that purpose.
; NOTE 2: See the section on garbage collection below if you choose to
;         use subdirectories for session storage
;
; The file storage module creates files using mode 600 by default.
; You can change that by using
;
;     session.save_path = "N;MODE;/path"
;
; where MODE is the octal representation of the mode. Note that this
; does not overwrite the process's umask.
;session.save_path = "/tmp"
 
也就是说,session的存放可以分子目录,但是要自己建立子目录,我写了个小程序,以三级子目录为例完成这个功能:
 
<?php
set_time_limit(0);
$string = '0123456789abcdefghijklmnopqrstuvwxyz';
$length = strlen($string);
function makeDir($param)
{
    if(! file_exists($param))
    {
        makeDir(dirname($param));
        mkdir($param);
    }
}
for($i = 0; $i <= $length; $i++)
{
 for($j = 0; $j <= $length; $j++)
 {
  for($k = 0; $k <= $length; $k++)
  {
   makeDir($string[$i] . '/' . $string[$j] . '/' . $string[$k]);
  }
 }
}
?>Posted by ken at 12:35 PM
点击:59 评分:0 评论:0 实例讲解MYSQL数据库的查询优化技术 2006/01/05 数据库系统是管理信息系统的核心,基于数据库的联机事务处理(OLTP)以及联机分析处理(OLAP)是银行、企业、政府等部门最为重要的计算机应用之一。从大多数系统的应用实例来看,查询操作在各种数据库操作中所占据的比重最大,而查询操作所基于的SELECT语句在SQL语句中又是代价最大的语句。举例来说,如果数据的量积累到一定的程度,比如一个银行的账户数据库表信息积累到上百万甚至上千万条记录,全表扫描一次往往需要数十分钟,甚至数小时。如果采用比全表扫描更好的查询策略,往往可以使查询时间降为几分钟,由此可见查询优化技术的重要性。

笔者在应用项目的实施中发现,许多程序员在利用一些前端数据库开发工具(如PowerBuilder、Delphi等)开发数据库应用程序时,只注重用户界面的华丽,并不重视查询语句的效率问题,导致所开发出来的应用系统效率低下,资源浪费严重。因此,如何设计高效合理的查询语句就显得非常重要。本文以应用实例为基础,结合数据库理论,介绍查询优化技术在现实系统中的运用。

分析问题

许多程序员认为查询优化是DBMS(数据库管理系统)的任务,与程序员所编写的SQL语句关系不大,这是错误的。一个好的查询计划往往可以使程序性能提高数十倍。查询计划是用户所提交的SQL语句的集合,查询规划是经过优化处理之后所产生的语句集合。DBMS处理查询计划的过程是这样的:在做完查询语句的词法、语法检查之后,将语句提交给DBMS的查询优化器,优化器做完代数优化和存取路径的优化之后,由预编译模块对语句进行处理并生成查询规划,然后在合适的时间提交给系统处理执行,最后将执行结果返回给用户。在实际的数据库产品(如Oracle、Sybase等)的高版本中都是采用基于代价的优化方法,这种优化能根据从系统字典表所得到的信息来估计不同的查询规划的代价,然后选择一个较优的规划。虽然现在的数据库产品在查询优化方面已经做得越来越好,但由用户提交的SQL语句是系统优化的基础,很难设想一个原本糟糕的查询计划经过系统的优化之后会变得高效,因此用户所写语句的优劣至关重要。系统所做查询优化我们暂不讨论,下面重点说明改善用户查询计划的解决方案。

解决问题

下面以关系数据库系统Inf为例,介绍改善用户查询计划的方法。

1.合理使用索引

索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率。现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构。索引的使用要恰到好处,其使用原则如下:

●在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引。

●在频繁进行排序或分组(即进行group by或order by操作)的列上建立索引。

●在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。

●如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。

●使用系统工具。如Inf数据库有一个tbcheck工具,可以在可疑的索引上进行检查。在一些数据库服务器上,索引可能失效或者因为频繁操作而使得读取效率降低,如果一个使用索引的查询不明不白地慢下来,可以试着用tbcheck工具检查索引的完整性,必要时进行修复。另外,当数据库表更新大量数据后,删除并重建索引可以提高查询速度。

2.避免或简化排序

应当简化或避免对大型表进行重复的排序。当能够利用索引自动以适当的次序产生输出时,优化器就避免了排序的步骤。以下是一些影响因素:

●索引中不包括一个或几个待排序的列;

●group by或order by子句中列的次序与索引的次序不一样;

●排序的列来自不同的表。

为了避免不必要的排序,就要正确地增建索引,合理地合并数据库表(尽管有时可能影响表的规范化,但相对于效率的提高是值得的)。如果排序不可避免,那么应当试图简化它,如缩小排序的列的范围等。

3.消除对大型表行数据的顺序存取

在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询10亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如,两个表:学生表(学号、姓名、年龄……)和选课表(学号、课程号、成绩)。如果两个表要做连接,就要在“学号”这个连接字段上建立索引。

还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的where子句强迫优化器使用顺序存取。下面的查询将强迫对orders表执行顺序操作:

SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008

虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合,所以应该改为如下语句:

SELECT * FROM orders WHERE customer_num=104 AND order_num>1001

UNION

SELECT * FROM orders WHERE order_num=1008

这样就能利用索引路径处理查询。

4.避免相关子查询

一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行。

5.避免困难的正规表达式

MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗费时间。例如:SELECT * FROM customer WHERE zipcode LIKE “98_ _ _”

即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如果把语句改为SELECT * FROM customer WHERE zipcode >“98000”,在执行查询时就会利用索引来查询,显然会大大提高速度。

另外,还要避免非开始的子串。例如语句:SELECT * FROM customer WHERE zipcode[2,3]>“80”,在where子句中采用了非开始子串,因而这个语句也不会使用索引。

6.使用临时表加速查询

把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。例如:

SELECT cust.name,rcvbles.balance,……other columns

FROM cust,rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

AND cust.postcode>“98000”

ORDER BY cust.name

如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序:

SELECT cust.name,rcvbles.balance,……other columns

FROM cust,rcvbles

WHERE cust.customer_id = rcvlbes.customer_id

AND rcvblls.balance>0

ORDER BY cust.name

INTO TEMP cust_with_balance

然后以下面的方式在临时表中查询:

SELECT * FROM cust_with_balance

WHERE postcode>“98000”

临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。

注意:临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意不要丢失数据。

7.用排序来取代非顺序存取

非顺序磁盘存取是最慢的操作,表现在磁盘存取臂的来回移动。SQL语句隐藏了这一情况,使得我们在写应用程序时很容易写出要求存取大量非顺序页的查询。

有些时候,用数据库的排序能力来替代非顺序的存取能改进查询。

实例分析

下面我们举一个制造公司的例子来说明如何进行查询优化。制造公司数据库中包括3个表,模式如下所示:

1.part表

零件号 Posted by ken at 12:32 PM
点击:106 评分:0 评论:0 [转载]PHP 与 ASP.NET 正面交锋 2005/12/31 作者 Sean Hull
来源 : [url]http://www.oracle.com/technology/global/cn/pub/articles/hull_asp.html[/url]

比较这两种最流行的构建 web 应用程序的方法的优缺点

如今当提到 Web 开发时,您有许多选择。这些方法中许多都涉及到预处理 — 即,利用特定的标记将代码嵌入到 HTML 页面中,这些标记告诉预处理器,它们包含代码,并且应对它们作出处理。与 CGI 非常相似,这些代码在服务器上运行,并返回一些内容,这些内容表现为发回给浏览器的结果 HTML 页面的部分外观。开放源代码脚本语言 PHP 和 Microsoft 的 ASP.NET 框架中的语言都属于这种类型;JavaServer Pages (JSP) 和 Perl/Mason 也以这种方式运行。

在本文中,我将重点讲述 PHP — Oracle 已选择合并到其产品中的技术 — 和 ASP.NET。我将概述两者的各种优势和弱点,并着重讨论那些将帮助您决定开发项目应选择哪种技术的因素。有很多因素需要考虑,不同的项目可能诉诸于不同的技术。总之,您将看到在价格、速度和效率、安全性、跨平台支持等方面的逐项比较,以及开放源代码解决方案的优势。

什么是 ASP.NET?

ASP 最新的版本 ASP.NET 并不完全与 ASP 早期的版本后向兼容,因为该软件进行了完全重写。早期的 ASP 技术实际上与 PHP 的共同之处比与 ASP.NET 的共同之处多得多,ASP.NET 是用于构建 Web 应用程序的一个完整的框架。这个模型的主要特性之一是选择编程语言的灵活性。ASP.NET 可以使用脚本语言(如 VBScript、JScript、Perlscript 和 Python)以及编译语言(如 VB、C#、C、Cobol、Smalltalk 和 Lisp)。新框架使用通用语言运行环境 (CLR);先将您语言的源代码编译成 Microsoft 中间语言代码,然后 CLR 执行这些代码。

这个框架还提供真正的面向对象编程 (OOP),并支持真正的继承、多态和封装。.NET 类库根据特定的任务(例如,使用 XML 或图像处理)组织成可继承的类。

除了编程语言和方法之外,数据库访问也是要着重关心的一个因素。当您用 ASP.NET 编程时,可以用 ODBC 来集成数据库;ODBC 提供了一组一致的调用函数来访问您的目标数据库。

优势和弱点

ASP.NET 的优势很明显在于它简洁的设计和实施。这是面向对象的编程人员的梦想:语言灵活,并支持复杂的面向对象特性。在这种意义下,它真正能够与编程人员现有的技能进行互操作。

ASP.NET 的另一个优势是其开发环境。例如,开发人员可以使用 WebMatrix(一个社区支持的工具)、Visual Studio .NET 或各种 Borland 工具(如 Delphi 和 C++ Builder)。例如,Visual Studio 允许设置断点、跟踪代码段和查看调用堆栈。总而言之,它是一个复杂的调试环境。许多其他第三方的 ASP.NET IDE 解决方案也将必然出现。

但您得到了强健性,就将以损失效率为代价。ASP.NET 在内存使用和执行时间方面耗费非常大,这大部分归因于较长的代码路径。对基于 Web 的应用程序,这些局限可能是一个严重的问题,因为在 Web 上,您的应用程序可能扩展为每秒成千上万的用户。内存使用率还可能成为 Web 服务器上的一个问题。

什么是 PHP?

PHP 是基于预处理 HTML 页面模型的一种脚本语言。当 Web 服务器中的 PHP 预处理器发现像下面这样的 PHP 语言标记时,将调用 PHP 引擎来执行该代码:


<?php
some code here
?>


任何使用过命令式编程语言的编程人员都会对 PHP 非常熟悉;您会发现它与 Perl、C 和 Java 在语法上的相似处。严格来讲,Java 是一种命令式编程语言,但它也利用了面向对象的结构和概念。PHP 在适宜的时候借鉴了这种结构,但它不是一种纯粹的 OOP 语言。

在上面对 ASP.NET 的讨论中,我提到了 ODBC 驱动程序,以及在考虑数据库抽象的情况下如何构建应用程序。在 PHP 中,您也可以使用 ODBC 与数据库对话,因此您已经有了一系列支持的数据库可供选择。也有 MySQL、Oracle 和 Postgres 的原生驱动程序。此外,如果要使用 Oracle,则有一个特殊的 OCI8 库将提供对 Oracle 更多访问功能,从而允许您使用诸如 LOB、BLOB、CLOB 和 BFILE 之类的特性。

这时您可能会问“为什么与数据库相关的资料库被称为 PHP 的特性?”数据库抽象或独立性是您在设法构建使用多种数据库或需要在数据库间移植(例如,从开发到投产时的移植)的应用程序时所要考虑的一个因素。而这些确实是应该关心和考虑的。

但正如 Tom Kyte 在他的新书 — Effective Oracle by Design (Oracle 出版社) — 中指出的那样,数据库相关性将成为您真正的目标,因为这将使您在该技术中的投资最大化。如果您对 Oracle 进行一般的访问 — 无论通过 ODBC 或 Perl 的 DBI 库,那么您将无法使用其他数据库所不具有的特性。此外,优化查询在各个数据库中各不相同。

Zend Technologies 是一家商业软件公司,它对 PHP 作出了重大贡献。它创建了一个称为 Zend Studio 的商业开发环境,这个环境包含了一个复杂的调试器、一个监测器和其他特性。该公司还构建了免费的 Zend Optimizer,它与 Zend Encoder 结合使用来编译 PHP 代码,以提升性能。还有其他商业产品,如 Zend Performance Suite,它可以缓存预编译的 PHP 页面,从而进一步显著提升总体性能。

优势和弱点

到测试版 4 为止,PHP 5 仍然有一些缺点,包括缺少异常和基于事件的错误处理例程 — 它们能够中断正常的程序流,并将代码跳转到一个特殊的错误处理部分。Java 也提供了用于错误处理的异常,而 C++ 通过 try、catch 和 throw 语法提供异常处理。当然,您仍然可以在 PHP 中管理错误,但其结构不是标准化的,因而使得编程人员必须使用自己的工具来决定执行错误处理的方式,这将导致更低的一致性并往往导致推倒重来。

另一个弱点是 PHP 的函数名是不区分大小写的。虽然这不是一个严重的缺点,但有些程序员可能会觉得这一特性很讨厌。

不过,我的确对 PHP 的对象模型心存疑虑。PHP 不是专门设计为一种面向对象的语言。这些特性中的一部分是后来添加的 — 尽管注意了保持与 PHP 3 的后向兼容性,因此两种模型的特性都留有一些。实际上,在 PHP 5 中这些弱点中的许多都得到了解决。请留心关注。

PHP 在一些领域中缺少什么,它就会在擅长的领域中迅速地弥补什么。价格合理,因此您不需要担心许可问题。它也是开放源代码的,因此整个社区将密切关注开发过程:发现错误并将其修复。如果有一个特性您不喜欢,那么您可以修改代码。此外,PHP 可与 Apache 自然结合:它可以作为一个模块编译,或直接编译成 Apache 二进制文件。

但在 Apache 上运行意味着,利用 PHP,您能够利用您已经在任意服务器投资,这是因为 Apache 能够运行在 Windows、Linux、Solaris 和各种其他 Unix 平台上。此外,使用拥有 Apache 的跟踪记录的 web 服务器意味着安全性能够保持在最高的优先级上。最后,PHP 拥有更小的代码路径,这意味着更少的分析和执行 PHP 页面服务器端代码,这将带来更高效的内存和使用率以及更快的运行。

在 PHP 5 中新增了哪些特性?

PHP 5 的第 4 个测试版在 2003 年 12 月底推出,更改日志清楚地显示已发现许多错误并已将其消除。虽然它仍在进行测试,但它的所有新特性和进步都确实值得关注。

PHP 5 的主要新成就在于它的异常处理和一个新对象,这个新对象引入的特性赋予了 PHP 真正的 OOP。异常处理无疑是 PHP 4 中最显著的缺憾之一,而 PHP 5 对异常处理的引入无疑是一个成熟的标志。异常处理意味着您在您的软件中拥有了根据语言定义的和标准化的错误处理方法。只需使用 try、catch 和 throw 方法,您的 PHP 代码就变得更加强健和简洁。


<?php

class blue {

function openFile ($inFile) {
if (file_exists ($inFile)) {
# code to open the file here
} else {
throw new Exception
        ("Cannot open file:$inFile");
    }
  }
}

$blueObj = new blue ();

try {
$blueObj->openFile ('/home/shull/file.txt');

} catch (Exception $myException) {
echo $myException->getMessage ();

# rest of exception handling code here
}

# rest of blue methods here

?>


新的对象模型为用 PHP 编写的程序带来许多积极的影响。在 PHP 4 中,当把将一个对象传递给函数或方法时,是通过值来传递的 — 除非您另行显式告知 PHP。这个过程意味着必须复制对象的一个副本(内存中的所有数据结构)。这个步骤使用内存,使得访问变慢和拥塞。而在 PHP 5 中,通常通过引用传递对象。

PHP 5 中新的面向对象的特性(包括构造器和析构器)值得关注。与 C++ 和 Java 相同,它们提供了一种标准方法,即通过一个构造器方法来创建对象、分配内存和执行任何必要的设置,并通过一个析构器方法来执行清理。

PHP 5 还引入了对类中方法和变量的更精细控制。在 PHP 4,一切都是公有的:您可以从类外或在继承类中访问您类中的变量。在 PHP 5 中,您仍然可以使变量或方法为公有,但您也可以使它们为私有,以使得只能在类本身中使用它们。还可以将它们保护起来,也就是说,可以在类内或在子类中查看方法和变量。

此外,PHP 5 引进了类型提示或更好的类型检查。当您将一个对象传递给一个例程时,PHP 能够检查它是否是正确的类型,并在检查失败时产生类型不匹配错误。

由于还有其他特性(如静态方法和变量以及抽象类),因此请务必查看文档,以获取详细信息。

安全性比较

ASP.NET 官方要求您使用 IIS。不幸的是,IIS 易受攻击的历史由来已久,这使得许多管理员不愿意部署它来处理 Web 站点。这些弱点是因为 Microsoft 的缺陷或是因为 IIS 是黑客们攻击的目标无关紧要:这些系统有被黑或被攻击的历史。PHP 也运行在 Apache 上,Apache 快速并且是开放源代码的,并拥有很好的安全性记录。此外,正如我提到过的,Apache 可以在许多平台上运行。

如果您在考虑 ASP.NET,但您想用 Apache 作为 Internet 门户,那么很幸运您可以有一些选择。首先,您可以使用 Apache 将请求转发给在另一台计算机上内部运行的 IIS。然后 Apache 处理静态内容,并将 aspx 内容传送给 IIS 服务器(不暴露给 Internet)。

不过,如果您想利用 Apache 承载 ASP.NET,那么提供了一些选项,这些选项 Microsoft 可能支持也可能不支持。作为最后一种选择,有 Ximian 的 Project Mono,它致力于构建一个开放源代码模块。请浏览 [url]www.go-mono.com[/url],以获取更多信息。

数据库编码示例

您在选用 PHP 或 ASP.NET 时首先要考虑因素之一就是与数据库的连接。不过,利用 ASP.NET 更复杂,因为您可以从许多备选语言中选择任意一种语言。当然,这些代码示例将必须嵌入到 HTML 页面、实例化的类等之中。不过,以下信息将使您对二者的编码风格有所了解。

PHP 5 与 Oracle 连接

下面是一个 PHP 5 类,它提供了一个 Oracle 连接和断开例程,用以演示利用 PHP 5(也可以使用其他驱动程序(如 ODBC 驱动程序)和通用的数据库接口)与 Oracle 连接的一种方式:


class oracle_object {
protected $theDB;
protected $user;
protected $pass;
protected $db;

function __construct($u, $p, $d) {
$this->user = $u;
$this->pass = $p;
$this->db = $d;
  }

function db_open () {
$theDB  =  @OCILogon($this->user,  $this->pass,  $this->db);
db_check_errors($php_errormsg);
  }

function db_close() {
@OCILogoff($theDB);
db_check_errors($php_errormsg);
  }

function __destruct () {
print ("so long...");
  }

}
Posted by ken at 12:02 PM
点击:59 评分:0 评论:0 [加速,cache] 推荐使用 eAccelerator,用到程序中去 2005/12/31 eAccelerator 真是一个好东西(它的前身是truck-mmcache)。

简单来讲它是一套配合PHP(支持PHP5)运作的缓存系统,通过共享内存或磁盘文件方式交换数据。

它被广为使用的是PHP源码“编码”(不太贴切的称为“加密”)和缓存PHP执行的中间码以加速。关于 eA 的安装使用的文章已经很多而且也很详细了,这次我想推荐的是用它辅助程序设计缓存,它提供了一组API如下:

是一个非常便捷而又稳定的本机缓存实现方式,目前这部分设计似乎只支持于共享内存,所以只能用于 Unix -Like OS 了,windows的就没这个福气了。

1. eaccelerator_put($key, $value, $ttl=0)
  将 $value 以 $key 为键名存进缓存(php4下支持对像类型,看源码好像zend2里不支持了),$ttl 是这个缓存的生命周期,单位是秒,省略该参数或指定为 0 表示不限时,直到服务器重启清空为止。

2. eaccelerator_get($key)
  根据 $key 从缓存中返回相应的 eaccelerator_put() 存进去的数据,如果这项缓存已经过期或不存在那么返回值是 NULL

3. eaccelerator_rm($key)
  根据 $key 移除缓存

4. eaccelerator_gc()
  移除清理所有已过期的 key

5. eaccelerator_lock($key)
  为 $key 加上锁定操作,以保证多进程多线程操作时数据的同步。需要调用 eaccelerator_unlock($key) 来释放这个锁或等待程序请求结束时自动释放这个锁。
  例如:
  <?php
    eaccelerator_lock("count");
    eaccelerator_put("count",eaccelerator_get("count")+1));
  ?>

6. eaccelerator_unlock($key)
  根据 $key 释放锁

7. eaccelerator_cache_output($key, $eval_code, $ttl=0)
  将 $eval_code 代码的输出缓存 $ttl 秒,($ttl参数同 eacclerator_put)
   For Example:
  <?php eaccelerator_cache_output('test', 'echo time(); phpinfo();', 30); ?>

8. eaccelerator_cache_result($key, $eval_code, $ttl=0)
  将 $eval_code 代码的执行结果缓存 $ttl 秒,($ttl参数同 eacclerator_put),类似 cache_output
   For Example:
  <?php eaccelerator_cache_result('test', ' time() . "Hello";', 30); ?>

9. eaccelerator_cache_page($key, $ttl=0)
  将当前整页缓存 $ttl 秒。
  For Example:
  <?php
    eaccelerator_cache_page($_SERVER['PHP_SELF'].'?GET='.serialize($_GET),30);
    echo time();
    phpinfo();
  ?>

10. eaccelerator_rm_page($key)
  删除由  eaccelerator_cache_page() 执行的缓存,参数也是 $key

______________________________________________
(作个简单例子看看它的威力,注意在 cli 模式下可能无效!)


CODE:[Copy to clipboard]<?php
class test_cache {
  var $pro = 'hello';

  function test_cache() {
    echo "Object Created!<br>/n";
  }
  function func() {
    echo ', the world!';
  }
  function now($t) {
    echo date('Y-m-d H:i:s', $t);
  }
}

$tt = eaccelerator_get("test_tt");
if (!$tt)
{
  $tt = new test_cache;
  eaccelerator_put("test_tt", $tt);
  echo "no cached!<br>/n";
}
else {
  echo "cached<br>/n";
}

echo $tt->pro;
$tt->func();
$tt->now(time() + 86400);
?>Posted by ken at 12:00 PM
点击:46 评分:0 评论:0 用AJAX技术来实现天气预报功能 2005/12/28 信息源来自美国雅虎,所以时间显示的是美国时间,但是天气情况还是实时的.

index.html

<script type="text/j" language="j" src="http://www.z173.com/demo/ajax_weather/weather.js"></script>
<A HREF="http://www.z173.com">
<img src="/UserFiles/2005-12/28/2005122845948850.gif" BORDER="0">
</A>
<br />
文章地址:用AJAX技术来实现天气预报功能
<A HREF=http://www.z173.com/article.asp?articleid=265>http://www.z173.com/article.asp?articleid=265</A>
<h3>天气预报
<span id="loadifo"></span>
</h3>
<h5>城市:
<select onChange="loadurl(this.value)" class="select">
        <option value="CHXX0138" selected="selected">武汉</option>
        <option value="CHXX0097">南昌</option>
        <option value="CHXX0502">海口</option>
        <option value="CHXX0008">北京</option>
        <option value="CHXX0116">上海</option>
        <option value="CHXX0037">广州</option>
        <option value="CHXX0259">银川</option>
        <option value="CHXX0165">郑州</option>
        <option value="CHXX0013">长沙</option>
        <option value="CHXX0390">杭州</option>
        <option value="CHXX0049">香港</option>
        <option value="CHXX0146">西安</option>
        <option value="CHXX0016">成都</option>
        <option value="CHXX0110">青岛</option>
        <option value="CHXX0039">贵阳</option>
        <option value="CHXX0064">济南</option>
        <option value="CHXX0448">合肥</option>
        <option value="CHXX0031">福州</option>
        <option value="CHXX0099">南京</option>
        <option value="ITXX0042">米兰</option>
</select>
</h5>
<div id="prolist"></div> 

 

weather.js

// j Document
function btnSty(objId,objStyle)
{
        document.getElementById(objId).style.display = objStyle
}
//提示窗口控制
function ifodis(){
        btnSty(’loadifo’,’none’);
}
function settime(a){
        setTimeout(a,1000);
}
function loadtime(){
        loadifo.innerHTML += "."
}
//XML数据绑定
var xmldoc = false;
function loadurl(n){
//生成随机数,同时限制刷新次数
        var now=new Date();
        var Num=now.valueOf();
//定义往址参数
        url = "weather.asp?n="+n+"&id="+Num;
//定义为异步传输模式
        xmldoc = false;
//Mozill,Safari等浏览器时需要创建的XMLHttp类
        if(window.XMLHttpRequest){
                xmldoc = new XMLHttpRequest();
                if(xmldoc.overrideMimeType){
                                xmldoc.overrideMimeType(’text/xml’);
                }
        }
//IE浏览器时创建的XMLHttp类
        else if(window.ActiveXObject){
                try{
                        xmldoc = new ActiveXObject("Msxml3.XMLHTTP");
                }
                catch(e){
                        try{
                                xmldoc = new ActiveXObject("Msxml2.XMLHTTP");
                        }
                        catch(e){
                                try{
                                        xmldoc = new ActiveXObject("Microsoft.XMLHTTP");
                                }
                                catch(e){}
                        }
                }
        }
//不能创建XMLHTTP类时返回
        if(! xmldoc){
                return false;
        }
//调用CheckState函数
        xmldoc.onreadystatechange = CheckState;
        xmldoc.open(’GET’,url,true);
        xmldoc.send(null);
}
//状态检测
function CheckState(){
        btnSty(’loadifo’,’’)
//收到完整的服务器响应
        if(xmldoc.readyState == 1){
                loadifo.innerHTML = "连接服务器"
                }
        else if(xmldoc.readyState == 2){
                loadifo.innerHTML = "开始加载数据"
                }
        else if(xmldoc.readyState == 3){
                loadifo.innerHTML = "正在加载数据"
                settime(loadtime)
                }
        else if(xmldoc.readyState == 4){
//HTTP服务器响应值成功
                if(xmldoc.status == 200){
//将服务器返回的字符串写到页面中ID为showdiv的区域
     loadifo.innerHTML = "加载完成"
                 var response = xmldoc.responseText;
                 settime(ifodis)
                 prolist.innerHTML = response;
                }
                else{
                        loadifo.innerHTML = "错误"+xmldoc.statusText+"请重新选择";
                }
        }
}
if (top.location != self.location)top.location=self.location;  

weather.asp

<%@LANGUAGE="j" CODEPAGE="65001"%>
<%
Session.CodePage = "65001"
Response.contentType="application/xml"
Response.Expires = 0
var N=Request("n")
var Num=Request("id")
var url="http://xml.weather.yahoo.com/forecastrss?p="+N+"&u=c&id="+Num;
var xmldoc=Server.CreateObject("Microsoft.Xmlhttp");
xmldoc.open(’GET’,url,false);
xmldoc.send(null);
var response = xmldoc.responseXML.documentElement;
var lastNode=response.selectNodes("//rss/channel/lastBuildDate");
var cityNode=response.selectNodes("//rss/channel/yweather:location");
var windNode=response.selectNodes("//rss/channel/yweather:wind");
var atmosphereNode=response.selectNodes("//rss/channel/yweather:atmosphere");
var astronomyNode=response.selectNodes("//rss/channel/yweather:astronomy");
var conditionNode=response.selectNodes("//rss/channel/item/yweather:condition");
var forecastNode=response.selectNodes("//rss/channel/item/yweather:forecast");
var lastV=lastNode(0).firstChild.nodeValue
//编辑属性
function attri(a,b,c){
        return a(b).attributes.getNamedItem(c).value
}
var cityV=attri(cityNode,0,"city")
var chillV=attri(windNode,0,"chill")
var directionV=attri(windNode,0,"direction")
var speedV=attri(windNode,0,"speed")
var humidityV=attri(atmosphereNode,0,"humidity")
var visibilityV=attri(atmosphereNode,0,"visibility")
var sunriseV=attri(astronomyNode,0,"sunrise")
var sunsetV=attri(astronomyNode,0,"sunset")
var textV=attri(conditionNode,0,"text")
var codeV=attri(conditionNode,0,"code")
var tempV=attri(conditionNode,0,"temp")
//转换英文为中文
var cityCH=EN2CH(cityV)
function EN2CH(obj){
        if(obj=="Wuhan"){return "武汉"}
        else if(obj=="Nanchang"){return "南昌"}
        else if(obj=="Haikou"){return "海口"}
        else if(obj=="Beijing"){return "北京"}
        else if(obj=="Shanghai"){return "上海"}
        else if(obj=="Guangzhou"){return "广州"}
        else if(obj=="Yinchuan"){return "银川"}
        else if(obj=="Zhengzhou"){return "郑州"}
        else if(obj=="Changsha"){return "长沙"}
        else if(obj=="Hanzhong"){return "杭州"}
        else if(obj=="Hong Kong"){return "香港"}
        else if(obj=="Xin’an"){return "西安"}
        else if(obj=="Chengdu"){return "成都"}
        else if(obj=="Qingdao"){return "青岛"}
        else if(obj=="Guiyang"){return "贵阳"}
        else if(obj=="Jinan"){return "济南"}
        else if(obj=="Hefei"){return "合肥"}
        else if(obj=="Fuzhou"){return "福州"}
        else if(obj=="Nanjing"){return "南京"}
        else{return obj}
}
//风向函数
var windCH=wind(directionV)
function wind(a){
        if(a>337 && a<=360){return "北风"};
        else if(a>=0 && a<=22){return "北风"};
        else if(a>22 && a<=67){return "东北风"};
        else if(a>67 && a<=112){return "东风"};
        else if(a>112 && a<=157){return "东南风"};
        else if(a>157 && a<=202){return "南风"};
        else if(a>202 && a<=247){return "西南风"};
        else if(a>247 && a<=292){return "西风"};
        else if(a>292 && a<=337){return "西北风"};
}
//能见度函数
visibility=vis(visibilityV)
function vis(a){
        return a/100
}
//转换天气为中文
var textCH=tEN2CH(textV)
function tEN2CH(obj){
        if(obj=="Clear"){return "晴朗"}
        else if(obj=="Sunny"){return "晴天"}
        else if(obj=="Partly Cloudy"){return "局部有云"}
        else if(obj=="Mostly Clear"){return "晴"}
        else if(obj=="Mostly Sunny"){return "小云"}
        else if(obj=="Mostly Cloudy"){return "多云"}
        else if(obj=="Cloudy"){return "云"}
        else if(obj=="Sunny/Wind"){return "晴转云"}
        else if(obj=="AM Clouds/PM Sun/Wind"){return "云转晴"}
        else if(obj=="AM Showers"){return "晨雨"}
        else{return obj}
}
//天气图片
var weaNum=weaimg(codeV)
function weaimg(obj){
        return "<img src="http://us.i1.yimg.com/us.yimg.com/i/us/we/52/"+obj+".gif" />"
}
//星期替换
function dayEn(obj){
        if(obj=="Sun"){return "星期曰"}
        else if(obj=="Mon"){return "星期一"}
        else if(obj=="Tue"){return "星期二"}
        else if(obj=="Wed"){return "星期三"}
        else if(obj=="Thu"){return "星期四"}
        else if(obj=="Fri"){return "星期五"}
        else if(obj=="Sat"){return "星期六"}
        else{return obj}
}
%>
<table width="163" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td rowspan="6" align="center"><%=cityCH%><br />
      <%=weaNum%><br />
      <%=textCH%></td>
    <td align="right">感觉:</td>
    <td align="center"><%=chillV%>&deg;</td>
  </tr>
  <tr style="background-color:#E6F5FF">
    <td align="right">实际:</td>
    <td align="center"><%=tempV%>&deg;</td>
  </tr>
  <tr>
    <td align="right">风向:</td>
    <td align="center"><%=windCH%></td>
  </tr>
  <tr style="background-color:#E6F5FF">
    <td align="right">风速:</td>
    <td align="center"><%=speedV%>Kph</td>
  </tr>
  <tr>
    <td align="right">湿度:</td>
    <td align="center"><%=humidityV%>%</td>
  </tr>
  <tr style="background-color:#E6F5FF">
    <td align="right">能见度:</td>
    <td align="center"><%=visibility%>km</td>
  </tr>
</table>
<table width="163" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
    <td colspan="2" align="center" class="time"><%=lastV%></td>
  </tr>
  <tr>
    <td bgcolor="#FFFFCC">曰出:<%=sunriseV%></td>
    <td bgcolor="#FFCC00">曰落:<%=sunsetV%></td>
  </tr>
</table>
<table width="163" border="0" align="center" cellpadding="0" cellspacing="0">
  <tr>
<%
for(var i=0; i<2; i++){
        var dayV=attri(forecastNode,i,"day")
        var dateV=attri(forecastNode,i,"date")
        var lowV=attri(forecastNode,i,"low")
        var highV=attri(forecastNode,i,"high")
        var texttV=attri(forecastNode,i,"text")
        var codetV=attri(forecastNode,i,"code")
        var dayCH=dayEn(dayV)
        var texttCH=tEN2CH(texttV)
        var weabmp=weaimg(codetV)
        //var weatNum=weaimg(codetV)
%>
                <td align="center"><%=dayCH%><br /><%=weabmp%><br /><%=texttCH%><br />最高<%=highV%>&deg;<br />最低<%=lowV%>&deg;</td>
<%
}
%>
</tr>
</table> 

 

要想自己加天气的话,在

<option value="CHXX0097">南昌</option> 

 
后面加相同的名称,城市代码到这里找http://xml.weather.yahoo.com/
要想把英文城市名换成中文的,改
else if(obj=="Nanjing"){return "南京"} 
 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值