[转载]浅析正则表达式—(原理篇) - Mr.小丁 - 博客园

mikel阅读(859)

[转载]浅析正则表达式—(原理篇) – Mr.小丁 – 博客园.

前言:

  其实这篇文章很久之前就应该发出来,由于种种原因没有 发出来,如果这篇文章中有错误,还请大家指出,小弟并改正之,没有学不会的东西,只有不想学的东西,只要功夫深,铁杵磨成针,我的至理名言:吾生也有涯而 知也无涯,以有涯随无涯,殆矣。我们只要坚持将其看完,相信大家的正则表达式会有一个提升空间!本文属于.NET正则表达式里面的内容,由于不同语言正则 表达式有所不同。

首先先讲解下正则表达式的基础知识:

  1.字符串的组成

  对于字符串”123“而言,包括三个字符四个位置。如下图所示:

  2.占有字符和零宽度

  正则表达式匹配过程中,如果子表达式匹配到东西,而并 非是一个位置,并最终保存到匹配的结果当中。这样的就称为占有字符,而只匹配一个位置,或者是匹配的内容并不保存到匹配结果中,这种就称作零宽度,后续会 讲到的零宽度断言等。占有字符是互斥的,零宽度是非互斥的。也就是一个字符,同一时间只能由一个子表达式匹配,而一个位置,却可以同时由多个零宽度的子表 达式匹配。

  3.控制权和传动

  正则表达式由左到右依次进行匹配,通常情况下是由一个 表达式取得控制权,从字符串的的某个位置进行匹配,一个子表达式开始尝试匹配的位置,是从前一子表达匹配成功的结束位置开始的(例如:(表达式一)(表达 式二)意思就是表达式一匹配完成后才能匹配表达式二,而匹配表达式二的位置是从表达式一的位置匹配结束后的位置开始)。如果表达式一是零宽度,那表达式一 匹配完成后,表达式二匹配的位置还是原来表达式以匹配的位置。也就是说它匹配开始和结束的位置是同一个。

  

  举一个简单的例子进行说明:正则表达式:123

  源数据:123

  讲解:首先正则表达式是从最左侧开始进行匹配,也就是 位置0处进行匹配,首先得到控制权的是正则表达式中的“1”,而不是源数据中的“1”,匹配源数据中的“1”,匹配成功,将源数据的“1”进行保存到匹配 的结果当中,这就表明它占有了一个字符,接下来就将控制权传给正则表达式中的“2”,匹配的位置变成了位置1,匹配源数据中的“2”,匹配成功,将控制权 又传动给了正则表达式的“3”,这时候匹配的位置变成了位置2,这时候就会将源数据中的“3”进行匹配。又有正则表达式“3”进行传动控制权,发现已经到 了正则表达式的末尾,正则表达式结束。

一、元字符

限定符 描述 模式
.

匹配出换行符以外的任意字符

\d*\.\d

\w

匹配字母数字或下划线或者汉字或者下划线

“be+”
\s

匹配任意空白符

  

“rai?n”
\d

匹配数字

“,\d{3}”
\b

匹配单词开始或结束,它只是匹配一个位置

“\d{2,}”
^

匹配字符串开始

“\d{3,5}”
$

匹配字符串结束

“\d{3,5}”

 

二、转义字符

如果你想要得到元字符本身的话需要使用“\”来取消这些元字符的特殊意义

 

三、字符类

  首先字符类使用“[]”包起来的,例如以下这个例子:(大小写要区分)

  ①[aeiou]则表示匹配任意一个英文元音字母(这个仅仅是匹配一个,也就是说你如果匹配了a这个整个正则表达式就已经结束了,这里面的逻辑表示的是“或”的意思),再看这个例子[.!?]表示匹配.或者?或者!

  ②[a-zA-Z0-9]这个正则表达式表示的是匹配a到z的任意一个小写字母,或者是A到Z的任意一个字母,或者是数字0到9任意一个.

四.重复(MSDN上称作是限定符)

代码/语法

说明

*

重复0次或多次

+

重复一次或多次

?

重复零次或1次

{n}

重复n次

{n,}

重复至少n次

{n,m}

重复至少n次,但不多于m次

 

五.分支条件

  其实正则表达式中的分支条件,就指的是有几种规则:用“|”把不同的规则分开

  来看下例子:

  ①0\d{2}-\d{8}|0\d{3}-\d{7}:匹配两种以连字号分隔的电话号码;一种是三位区号8位本地号(例如:010-12345678),另外一种规则则是4位区号7位本地号(例   如:0315-8834524)

  ②\d{5}-\d{4}|\d{5}:需要注意的是 使用分支条件是一定要注意分支条件的顺序,如果改成\d{5}|\d{5}-\d{4}这个样子的话,那么只会匹配五位数字而不会匹配后面的四位数字(例 如:我们利用第二个匹配12345-1234,它只会匹配12345,原因是:正则表达式是从左到右依次匹配,如果满足了某个分支的话它就不会再管其他分支了)

 

六.分组

  你可以使用小括号()来指定字表达式

  ①(\d{1,3}){3}\d{3}:这个正则表达式的意思就是把我们分组的小括号里面的东西重复三次,也就是说我们至少匹配3个最多匹配9个数字,后面再加上三个数字

 

  我们可以看图,最后一个是1234567891 123也就是说前面是十个数字按照我们的常理来分析的话就应该匹配应该最多的是9个所以匹配之后的数到2就匹配成功了。

  OK我们讲到分组不知道你们对上面这幅图有没有什么想法?对,没错就是为啥还有0,1之分呢?想知道答案跟我继续看下去,保证你有意外收获哦!

  也许大家会问为什么这里的写的1里面匹配的是这些数字,我们稍后我们会为你解析这是为什么会是这些数字!

七.反义字符

代码/语法

说明

\W

匹配任意一个不是字母或数字下划线或汉字的字符

\S

匹配任意一个不是空白符的字符

\D

匹配不是数字的字符

\B

匹配不是单词开头或者结尾的位置

[^X]

匹配除了X以外的任意字符

[^aeiou]

匹配除了aeiou这几个字母以外的任意字符

 

八.反向引用

  使用小括号指定一个子表达式后,匹配这个子表达式的文 本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标 志,第一个出现的分组的组号为1,第二个为2,以此类推。但是其实分组号不是这么简单:

  •分组0对应整个正则表达式

  •实际上组号分配过程是要从左向右扫描两遍的:第一遍只给未命名组分配,第二遍只给命名组分配--因此所有命名组的组号都大于未命名的组号

  •你可以使用(?:exp)这样的语法来剥夺一个分组对组号分配的参与权.

  通过上面三条讲述我们可以清楚地知道分组的方式是怎样 的,其实意思就是首先我们先对没有为组进行命名的组进行分配组号(从左到右依次次分配),然后再对分配组号的组进行分配组号(使用(?<组 名>)方式显示分配组名称),如果你想剥夺某一个组的组号可以采用(?:exp)这种方式进行剥夺,也就是不给他分配组号,可以理解为跳过此组。看 一下例子:

  正则表达式:(?<work>3)(1)(2)(?<SmallDing>565)

  匹配文本:312565

  匹配结果表明首先0号组的是匹配的整个表达式,匹配1号组名的则是1,匹配2号组的是2,匹配3号组的就是命名为work组名的3,匹配4号组的则是匹配命名为SmallDing组名的565,显然可以看到分配组号就是按照以上的规则来分配。

说到了反向引用我们来看一下反向引用是什么概念,我们前面已经详细讲解了组号的分配,那么反向引用则用于重复搜索前面某个分组匹配的文本,例如\1代表分组1匹配的文本

请看下面的例子:

  正则表达式:(1)(2)(3)\2则表示匹配123且在此匹配组号为2的内容也就是再次匹配2

  匹配文本:1232

  匹配结果如下图所示:

  而至于想知道怎样取消分组号那就跟着我的脚步走,来看看下面的内容吧!

  正则表达式:(?<work>333) (?<smallDing>222)(?:\d{3})该正则表达式代表的是显示为匹配333的组分配组名为work,显示为匹配222结果 的组分配组名为222,但是如果匹配3位数字这个组已经取消了组号,所以该组号是没有的,也就是整个正则表达式是第一个组号为0,首先将所有未命名的组进 行分配组号,而只有一个(?:\d{3})这个没有分配组名,但是它却将组号进行取消了,所以组号不会给它分配。

  源文本为:333222123

  匹配结果为:如下图所示:

那现在我们就来讲一下零宽断言和负零宽断言

常见的几种分组方法

分类

代表/语法

说明

 

 

捕获

 

 

(exp)

匹配exp,并捕获文本到自动命名的组里

(?<name>exp)

匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)

(?:exp)

匹配exp,不捕获匹配文本,也不给分组分配组号

 

 

 断言

 

 

 

(?=exp)

匹配exp前面位置,但是不匹配exp

(?<exp)

匹配exp后面位置,但是不匹配exp

(?!exp)

匹配后面的不是exp的位置,但是不匹配exp

(?<!exp)

匹配前面不是exp的位置,但是不匹配exp

注释

(?#comment)

注释

  零宽度断言

  1.(?=exp):也叫零宽度正预测先行断言,它匹配自身出现的位置后面能匹配表达式exp

  例如:\b\w+(?=ing\b)则这个正则表达式 就是匹配一ing结尾的单词,但是不包含ing,这个零宽度正预测先行断言可以这样理解,我们就以上面的正则表达式作为例来进行讲解,首先我们肯定是匹配 源文本为doing它会先匹配d的时候它会瞻仰一下后面跟的是不是ing,如果不是就会继续往下走,匹配到第二个字符o它会预测(或瞻仰)下后面是不是 ing如果是整个表达式就结束了,并且不匹配ing。而这个可以总结一句话就是匹配exp前面的东西

  2.(?<=exp):也叫零宽度正回顾断言, 它匹配自身出现位置的前面匹配表达式exp,这句话听着很绕口,其实零宽度正回顾断言中解释说是自身出现位置这个自身出现位置是表示它匹配的文本,就比如 说(?<=Ding)\d{3}这个正则表达式,这里的自身出现的位置仅仅是从开始匹配文本的时候也就是\d{3}也就是主动权在这个\d{3}的 时候才是自身匹配的位置。举例说明源文本,比如匹配Din123,按照我们的常理理解的是数字123是自身匹配的位置,但是前面不是Ding所以匹配不成 功,我们可以讲这个表达式理解为就是以exp为开始的正则表达式但是不包含exp,意思就是匹配exp后面的东西。

  负向零宽断言:(可以和上面的进行对比来学哦!这个表达式的是否定的)

  1.(?!exp):也叫零宽度负预测先行断言,断言此位置的后面跟的不能匹配表达式exp,

  例如:\d{3}(?!123):正则表达式的含义表达了前面匹配的是三个数字,匹配的位置就是当前匹配的这三个数字后面跟的不能是123。

  2.(?<!exp):零宽度负回顾断言,断言此位置前面跟的不是exp的位置。

  九.平衡组

  接下来我来讲一下平衡租的原理,在上面我们做下了铺 垫,也就是说我们在第六节的时候提出来了一系列问题,是不是感觉一头雾水,没关系的,到了这一节终于守得云开见月明了,听过本章节的学习我相信你们会对上 面的问题进行一个详细合理的回答!OK,Come On Baby!懂你们迫不及待心情,一定会说你咋这多废话呢,好,闲话少说,继续….

说到平衡组有些人就会想到分组,没错他们之间是有联系的,也就是我们前面所讲的分配组号的问题,那下面呢我们先引出语法,详细见下表

语法

说明

(?’group’)

把捕获的内容命名为group,并压入堆栈

(?’-group’)

从堆栈上弹出最后压入堆栈名为group的捕获内容,如果堆栈为空则本组匹配失败

(?(group)yes|no)

如果堆栈上存在名为group的捕获内容的话,继续匹配yes部分的表达式,否则匹配no的表达式

(?!)

零宽度负先行断言,由于没有后缀表达式,试图匹配总是失败

  也许大家看到这些语法都不知道是什么概念,也不知道这 个平衡组到底用在什么地方合适,接下来我们我们就来说一个场景分析它用在什么位置比较合适,有时我们需要匹配像 ( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用\(.+\)则只会匹配到最左边的左括号和最右边的右括号之间的内 容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如 ( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢? 为了避免(和\(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把 xx <aa <bbb> <bbb> aa> yy这样的字符串里,最长的配对的尖括号内的内容捕获出来?

  接下来我们对这些语法进行分析,怎么样一个平衡法,大家都见过第一个语法,语法的内容讲解的就是为一个组分配组名,这里我们为什么还强调一下分配组名的问题么?前面不是提到过这些问题了么!那现在让我们解析一下平衡法以及用这些语法去构建一个平衡。

  我们先以一个例子开始,正则表达式: (?’Group’123)(?’Group’456)看这个正则表达式,你会发现一些问题,恩?怎么给两个组分配了一个组名,这样返回的Group组名 获取的到底是个什么东东呢?大家来猜一下(匹配文本:123456)会是个什么结果?

先看一下测试结果:

我们可以看到0组当人不让的是整个表达式的,而Group组里面获取的是456,而不是123,这是为什么呢?那么我们就来分析一下他的原理,一张图搞懂原理

  OK,我们来讲一下组其实内部是一个堆栈,也就是我们 分别往组名为Group的堆栈中放入了两个内容,第一个压入栈的是123,而第二压入栈的是456,Group组获取的文本是堆栈的top,也就是栈顶的 数据,所以Group获取的数据是456,而不是123,那么有些人说了我不想要456,我就想要123怎么实现?这样也好办啊!我们就弹出栈顶数据不就 行了么!

  看下面的实例:(?’Group’123)(?’Group’456)(?’-Group’)这里的表达式(?’-Group’)就是压出堆栈栈顶的数据也就是如下图所示的:

 

  那么现在栈顶的数据就是123了,那么我们就来看一下匹配的结果是不是我们想的这样:

  

  那么我们就可以想到分组名的是这样没有分组名的组也是 这样的匹配原理那么我们回到第六章就可以将答案找出来,为什么这个组里的数据会是这个了!剩下还有(?(group)yes|no)深入讲解下这个表达式 是什么意思,我们前面已经讲到了分组是一个堆栈,可以压入和弹出,但是再弹出的时候我们不知道它有没有弹完用什么办法来可以检测它是不是已经到了栈底了 呢?那么用这个正则表达式就可以检测到!它说的意思就是如果我们已经将数据全部都弹出去了就会执行一个表达式在No的位置,“|”表示分割两种不同情况, 如果还存咱数据就说明还没有到栈底,就会执行yes的表达式。那么我们就开始举例说明:正则表达式:(?’group’123) (?’group’456)(?’-group’)(?(group)1|2):这个表达式含义就是如果堆栈中还有数据就匹配1,否则就匹配2,看下面测 试结果表明堆栈中还有数据。

 

十、贪婪与非贪婪

  首先先说一下关于贪婪匹配和非贪婪匹配的一些基本概念,贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。

  下面是一些限定符(限定符指定在输入字符串中必须存在上一个元素(可以是字符、组或字符类)的多少个实例才能出现匹配项)

  贪婪匹配的限定符如下表所示:

限定符 描述 模式 匹配
* 匹配上一个元素零次或多次 \d*\.\d “.0″,”19.9″和”219.9”
+ 匹配上一个元素一次或多次 “be+” “been”和”bee”,”bent”和”be”
匹配前面的元素零次或一次   “rai?n” “ran”和”rain”
{n} 匹配上一个元素恰好n次 “,\d{3}” “1.043.6”中的.043
{n,} 匹配上一个元素至少n次 “\d{2,}” “166”,”29″和”1930″
{n,m} 匹配上一个元素至少n次,但不多于m次 “\d{3,5}” “166”,”16546″,”132654″中的13265

  非贪婪是在贪婪限定符后面多加一个“?”,如下表所示:

  

限定符 描述 模式 匹配
*? 匹配上一个元素零次或多次,但次数尽可能少 \d*?\.\d “.0″,”19.9″和”219.9”
+? 匹配上一个元素一次或多次,但次数尽可能少 “be+?” “been中的”be”,bent”中的”be”
?? 匹配上一个元素零次或一次,但次数尽可能少 “rai??n” “ran”和”rain”
{n}? 匹配前导元素恰好 n 次 “,\d{3}?” “1.043.6”中的.043
{n,}? 匹配上一个元素至少 n 次,但次数尽可能少 “\d{2,}?” “166”,”29″和”1930″
{n,m}? 匹配上一个元素的次数介于 n 和 m 之间,但次数尽可能少 “\d{3,5}?” “166”,”16546″,”132654″中的”132″,”654″

 

十一、贪婪匹配和非贪婪匹配原理

  这是最后一章节,也是最难理解的一章节了,希望大家跟 进脚步学习下!其实这节贪婪匹配与懒惰匹配应该放在重复后面讲,因为这个和重复有关系,那么下面详细介绍什么是贪婪匹配什么是非贪婪匹配,贪婪与非贪婪模 式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能 少的匹配。非贪婪模式只被部分NFA引擎所支持。

  从原理角度分析一下贪婪匹配与懒惰匹配,接下来我们将以一个例子分析

  匹配两个正则表达式,正则表达式一为:.*

  正则表达式二是:.*?

  源文本是:“Regex”

  (1).贪婪

  

  注:为了能够看清晰匹配过程,上面的空隙留得较大,实际源字符串为“”Regex””,下同。

  来看一下匹配过程。首先将控制权交给“””,由它来匹 配第一个字符”匹配成功,将控制权转交给“.*”,这时候控制权掌握在了“.*”的手上,由于“*”是优先词量,在可匹配与不可匹配的情况下,优先尝试匹 配,他就会尝试匹配第一字符R,匹配成功就会继续往下匹配,匹配第二字符e,匹配成功,继续向右匹配,直到匹配到结尾的“””,匹配成功,再向后匹配时发 现已经到结尾了,“.*”结束匹配将控制权转交给”””,”””发现已经到了源字符串的结尾,看有没有可供回溯的状态,将控制权给了“.*”,“.*”还 回一个字符“x”,然后将控制权转交给“””,来匹配后面的字符“””,匹配成功正则表达式结束。这句表达式只进行了一次回溯。

  (2).懒惰

  源字符串:”Regex” 

  正则表达式:”.*?” 

  看一下非贪婪模式的匹配过程。首先由第一个“””取得 控制权,匹配位置0位的“””,匹配成功,控制权交给“.*?”。“.*?”取得控制权后,由于“*?”是忽略优先量词,在可匹配可不匹配的情况下,优先 尝试不匹配,由于“*”等价于“{0,}”,所以在忽略优先的情况下,可以不匹配任何内容。从位置1处尝试忽略匹配,也就是不匹配任何内容,将控制权交给 正则表达式最后的“””。 

  “””取得控制权后,从位置1处尝试匹配,由“””匹配位置1处的“R”,匹配失败,向前查找可供回溯的状态,控制权交给“.*?”,由“.*?”吃进一个字符,匹配位置1处的“R”,再把控制权交给正则表达式最后的“””。

  “””取得控制权后,从位置2处尝试匹配,由“””匹配位置1处的“e”,匹配失败,向前查找可供回溯的状态,重复以上过程,直到由“.*?”匹配到“x”为止,再把控制权交给正则表达式最后的“””。 

  “””取得控制权后,从位置6处尝试匹配,由“””匹配字符串最后的“””,匹配成功。 

  此时整个正则表达式匹配成功,其中“.*?”匹配的内容为“Regex”,匹配过程中进行了五次回溯。 

 

  写的很认真但是难免会有错误,希望大家多多包涵,多多指出,时刻保持学习的身段,正所谓三人行必有我师焉。人外有人天外有天,只有保持不断学习的精神,才能达到我们的目标。我会将其更新并且改正。

  这篇文章为了方便大家传阅将其写成word文档,可以进行下载,下载地址如下:

  百度网盘:http://pan.baidu.com/s/1kTKB3Zx 提取密码:l6q4

  其中有我在公司的技术分享视频,由于是第一次录制可能有些细节没有讲得很清楚。也在上面百度网盘中。

  参考文章:

  图片是从下面文章中找到的:

    http://www.jb51.net/article/31491.htm

  http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaocheng.html#mission

  测试工具也在里面:

  http://deerchao.net/tutorials/regex/common.htm

  谢谢各位的提的意见,从你们的意见中将这篇文章尽自己最大努力完善,这篇文章写得不完美,需要大家的努力。

   接下篇对令宽度进行详细讲解:

   浅析正则表达式——柳暗花明又一村篇

[转载]QQ邮件群发 - xiaodao - 博客园

mikel阅读(1014)

[转载]QQ邮件群发 – xiaodao – 博客园.

在项目也完成的差不多了,就把程序重新修正了发布。
本程序由 Microsoft Visual Studio 2010 编写,在测试机上安装了
.NET Framework 3.5(SP1 完整安装包) 正常通过测试。
此次升级使用 SQLite、TemplateEngine 开源库,如需要源码请到其官方网站下载。
本程序可以免费在您的计算机中复制分发副本运行,不提供源码。

由于开发时间很短,不保证能正常发送,但其代码是前一版本升级过来的,应没有什么问题,如果有问题请联系我:hulaka@vip.qq.com
********操作说明********

导入的数据如果不符合格式可以先用替换工具(记事本、Word)将其设置为正确格式。

SendMail.exe 程序的 UI 部分。
Bin.exe 程序的运行部分。
Shell.vbs 实际运行中没有任何作用,作为 Shell 代码留作备用查看。
SendMail.db 程序数据库。
Mail.htm 要发送的邮件正文,注意必须将内容编辑到“<body>内容</body>”之间。
fup.asp Shell 服务器脚本,可以使用小刀编写的 FTPBatch(已含在程序包中,下载源码) 批量上传。
********更新日志********

2010-8-15 V1.1:

1、半 UI 的方式,解决了操作不方面的问题;
2、使用 SQLite 嵌入式数据库,程序可以分发多个副本运行;
3、SQL 执行自带了一些简易的命令语句;
4、支持报表查看,实时状况一目了然(使用了 TemplateEngine 解析);

 

下载程序包 >>

Unable to execute dex: java.nio.BufferOverflowException. Check the Eclipse l

mikel阅读(753)

更新了sdk adt,就出现这问题,官方又重新下载了,adt结果有错误。我崩溃了。求解惑!!!

我就这样反复找问题,还是一筹莫展。

解决方法:

你可能是直接import的代码,代码本身会在你的项目下建立一个依赖包  Android Dependencies,在eclipse中右键这个工程文件夹,
在Build Path选项中选择  remove it from build path。。。然后就没问题了。。希望可以帮助到你。

[转载]用代码截图去理解ASP.NET MVC原理 - 黑树 - 博客园

mikel阅读(996)

[转载]用代码截图去理解MVC原理 – 黑树 – 博客园.

【概述】
看了蒋金楠先生的《ASP.NET Mvc框架揭密》,这本书详细地讲解了mvc的原理,很深奥也很复杂,看了几遍才将就明白了一点。他在第一章用了一个他自己写的mvc框架作为例子,代码 看着有点多,所以为了帮助理解,我想用截图的方式一步一步地描述mvc的流程,本人能力有限,写的不好,还望大家包涵。如果蒋老师看到这篇文章,也希望能 对我理解错误的地方进行指正。
 
一、先在web.config中注册自定义的HttpModule
二、输入网址
三、添加默认的路由规则
四、注册PostResolveRequestCache事件
五、解析RouteData
六、解析请求的controller和action
七、封装RequestContext
八、获取MvcHandler
 
九、指定MvcHandler处理http请求
 
十、通过反射建立Controller对象
 
十一、通过反射建立Controller对象
 
十二、用生成的controller对象执行请求
 
十三、通过反射建立Action
 
十四、通过反射建立Action

 
十五、由自定义的RawContentResult显示结果
十六、结果显示
 
【总结】
上面所用的代码是从蒋先生的博客上下载的源码,看过书后用断点一步步跟了几遍,稍微理解了点这个流程。用蒋先生的话做个总结:实际上整个ASP.NET MVC框架就是通过自定义的HttpMoudle(UrlRoutingModule)和HttpHandler(MvcHandler)实现的。
希望此文能帮到更多在学习mvc的朋友,谢谢支持。
 

[转载]程序员生存定律--细论影响人生成绩的四个要素(1) - 理想流 - 博客园

mikel阅读(921)

[转载]程序员生存定律–细论影响人生成绩的四个要素(1) – 理想流 – 博客园.

程序员生存定律这系列的目录在这里:程序员生存定律–目录

喜欢从头瞄的,可以移步。

——————————————————————————

定律要素之一:自身价值

在金庸先生构建的武侠世界里,最犀利的杀伐武功应该是《独孤九剑》,但学会了独孤九剑却失了内功的令狐冲一样会被一堆无赖按到地上揍个鼻青脸肿。待到学会了吸星大法,内力大进,那就再没这回事了。

根据打铁还要自身硬的道理,修炼确实应该先从内功开始,但不是说招式就不必要了,这很辨证。至于究竟那个更重要这样的问题不在具体的时空背景下是没有答案的。

从最终表现来看,一个人的价值(或者说内功)可以体现在几乎无限多的地方,如:编程语言、分析设计、沟通、管理、估算、流程改善等等。但如果为各种技能稍做一点分类后就会发现,人创造价值的基本途径只有两个:一个是完全依赖于自身的技能,另一个则是假于他人之手。

后者也许不太容易理解,这里举一个简单的例子:假设张三和李四的技术能力都非常的优秀,但两者性格不合,一旦在一起工作就非常容易各自固守己见,寸 步不让,每天争吵不断。这个时候王二出现了,王二的技术能力并不优秀,但比较擅长协调各个人的意见,有王二在,张三和李四就可以配合的比较好。在这种情形 下,王二创造了价值,虽然很大程度上这种创造依赖于A和B。

具体来讲,编码、设计、测试、估算、需求分析等更类似于直接通过自身的技能创造价值,而管理、流程改善等则类似于后者。专注于设计、编码、测试等实现工作的人在现实中往往被定义为程序员,而专注于管理、流程改善等方面的人在现实里则往往被定义为管理者。

从可创造价值大小的角度看,一般情形下两者似乎都没有一种准确限度:伟大的政治家和伟大的科学家可以同样的伟大。但从现实来看,至少是在国内,很多时候人们更倾向于认为管理类职位拥有更高的价值。现实中很多公司中确实如此,但这并不总是对的。

似乎可以在某一条线上把公司安放在不同的位置上,越过某条界限之后,直接做事的人所创生的价值才可能超过管理人员。这反过来要求岗位的技术附加值要 比较高。想象下在制造类企业中,从收入的角度看,生产线上的工人的收入总是会偏低。同理,在软件公司中,越是技术含量低的开发工作,这点体现的越为明显。 而一旦到了顶级软件公司中故事就可能会不一样了。

 

在《微软的秘密》这本书中有这样一段描述:

我们中有些人对开发人员怀有极度的不满,那简直就是嫉妒。达瑞尔•希文斯是 Windows NT的主要开发人员之一,他有9辆保时捷,我当然也希望能够拥有9辆保时捷。但我怨恨达瑞尔么?当然不。他绝对受之无愧,他真的棒极了。 如果用我的支票来给他开工资,我也愿意。不过从长远来看,过一两年你肯定就能得到应得的报酬。如果由于某些原因,我们引入了达瑞尔,并付给他足够买9辆保 时捷的薪水,而他一旦干得不够好,就不会在这里工作很久… …但这些开发人员都是精心挑选出来的人才……唯一的不利之处在于,总有一部分 人感到开发人员才是“主角”,但这正是这一行业的本质。

持上述看法的人是Windows NT的高级产品经理理查德•巴斯,从描述来看,这个管理者的收入是要低于被管理的技术人员的。

促成这一结果的三个关键词是:微软、Windows NT、主要开发人员。微软抓住天时雄霸PC的操作系统市场,而在操作系统中 Windows NT正是核心,在前两者基础上达瑞尔•希文斯又是主要的开发人员。为使技术人员的收入超过管理人员的,这三个因素恐怕是缺一不可。这在以 销售为核心的公司里很难复制,但在以产品为核心的公司里却始终存在着可能性。

单以方向自身而言,很难单纯讲那条是金光大道,而那条是华容道。关键点首先在于要避免选择自身内部蕴含矛盾,比如你想做技术却选了不以技术为核心支撑的公司,选了管理,却在纯研发环境里。其次在于无论那条路上都要努力走到专业和高端。

而不管技术还是管理,影响增值整个过程的因素都比较多:知识体系上的认知、方向的选择、博与专的平衡、知识的可流动性等都要分别进行考察。对这些点的考察将在后面逐渐展开。

 

定律要素之二:自身价值上的表达力

 

很多人咋一看这个标题,也许会有疑问:假如说是一个很牛很牛的大侠,那还需要表达力么?

实际情形是,如果大侠总是猫在山洞里隐居,那么有没有表达力其实一点都不关键,但现在关键的是江湖需要表达力,所以大侠一入江湖,就变的需要表达力了。

一说到表达力,很多人就会想到沟通和说话,但其实说话远不是表达力的核心。敏于事讷于言的人很多,难道他们就没有表达力了么?显然不是的。一个人的过往、行止、习惯、性格等都是表达力的一部分。

我们先来看一个简单的例子。

2012的CSDN上有一篇翻译的文章,叫“编程的技能和做员工的技能–那个更重要?”这篇文章里描述了两个极端的例子:

 

Rodrigo毕业于麻省理工,他在业余时间开发编译器。他是Haskell语言的 核心代码捐助者,他开发了很多非常有名的Python程序库。他写出的代码都是非常健壮的代码,可读性好,能够优雅的处理各种程序上的临界计算场景。然 而,他通常是拖延几天才回复邮件,你很少见他会接听电话,他看起来并不真正理解按时完成任务的重要性,他按自己的方式做事,你不可能弄清楚他究竟是怎么想 的,只感觉他脑子里都是一些漫无边际的想法。

Gabriella并不是一个非常优秀的程序员,她写的程序看起来显然很业余。15 到20行就能完成的程序她写了30行。她的程序里有bug,这让QA部门在上面花费了不少时间,她没有真正理解写出的代码应该具有好的性能的道理——“能 用就行啦!”。然而,她很热情——她收到邮件几分钟内必给予回复,她从不漏接一个电话,她善于沟通,她能把复杂的技术问题清楚的讲给客户听,她从没有逾期 完不成任务,她不断的寻求反馈来改进自己的工作,她是一个很随和的人,同事喜欢跟她说话。

 

这两个极端的例子很有意思,但如果我们真的二选一的去判断那个更重要,就会失去领会职场中一个本质问题的机会。

文中所描述的做员工的技巧事实上很像拱猪游戏里面的梅花10(变压器),他并非与所谓的编程技能相对立,而是普遍存在于每一个程序员的身上,任何一个程序员必然同时具备这两方面的能力:编程技能与做员工的技能,而做员工的技能则像一个变压器,最终放大或缩小你的真实能力。这就是表达力的功效,而做员工的技巧正是表达力的一部分。

那表达力为什么会有价值?

我们都知道管中窥豹是不好的,但很不幸即使是在最为公正理智的组织里,大多数人仍然是被管中窥豹的。企业的组织结构基本上呈现为金字塔形状,而位置越往上,权柄越大,也即是说位置在下面的人,其评判权利掌握在其上司手中。

而当上位者对下位者进行认知时,上位者印象中的某个人和真实的某个人往往会有差异。而好的组织和不好的组织的一个区别则是这种偏差究竟是主观造成的,还是客观现实而无法避免,而绝不是这种区别是否存在。

这种差异得以存在的客观原因有很多,比如:

 

  • 信息丢失

层级一旦产生,信息往往需要中转,总经理要想看到某个人,往往要通过几个层级,这个过程中无疑的信息会被丢失。

  •  信息量过大

一个人能处理的信息是有限的。比如一个Manager负责一个20个人的团队,那么由于待处理的信息过多,就就很可能在是推卸责任还是陈述困难上产生误判。

  • 语言

 

即使是信息没丢失,不同的人对同样的信息理解也可能不一致。比如说V手势在英国就意味着滚开而不是胜利。

这类因素最终导致认知上的偏差成为一种无法规避的客观现实,是一种必须去适应而无法彻底改变的东西。像组织行为学这类学科中会把这个问题单独作为一个研究项目:印象管理(impression management),首因效应等探讨的都是这个事情。

这并不难理解,通过自我推销、赞扬别人、适当的从众、搞好人际关系这类印象管理的手段来管理个人表现面无疑的会让自己产生溢价,提升自己在别人眼中的价值。

毕竟在组织里,别人眼中的你才有现实意义,即使它和真实的你有所差异。从长期的视角来看,影响自身价值表达的几个主要因素是:资历、自身性格特征、借势的程度以及权术的运用等。这几点将在后面进行展开说明。

最后需要做一点区别的是改善表达力与恶意专营。

两者间本质上并无差别,有差别的是程度。从适用场景来看,在任人唯亲的环境里曲意逢迎是一种生存必备技能,但即使在最公平的组织里也需要改善自己的表达力。

年轻的程序员往往会仇恨上面所说的这点,并用充满负面情绪的词汇去形容这类技能比如:拍马屁,无耻。但其实不是,从人生效能的角度看,忽视这点是危险的,除非你在自身价值上已经达到了众人瞩目的地步,比如:简历上就一句话,我创造了Python。

 

最后看一个欠缺表达力的历史故事:

弹铗而歌

《战国策》和《史记》里都讲述了这样一个故事:

冯谖因为太穷而无法生活,就申请成为孟尝君的门客,但当孟尝君问他有什么本事时,冯谖却回答说自己没什么本事。

结果孟尝君虽然吸纳了他,但冯谖却被安排为最下等的门客。

孟尝君的门客有三个等级:一等门客出门有车坐,二等门客有鱼吃,三等门客只能吃粗劣的饭菜。

冯谖并不很满意,就弹自己的剑而做歌,说:长剑啊,我们回去吧!没有鱼吃。

下人把这事儿告诉了孟尝君,孟尝君还是很大度,说:那就给他鱼吃。

过一阵,冯谖又开始弹自己的剑而做歌,说:长剑啊,我们回去吧!出门没车坐。

左右的人取笑他之后,又把这消息告诉了孟尝君,孟尝君又很大度,说:给他车座。

接下来,冯谖继续弹,还是这个调子,说:长剑啊,我们回去吧!没法养家。

这时候大家已经很厌恶他了,但孟尝君还是问了他的困难,并派人给把他母亲也养了起来。

接下来冯谖连续做了几件很体现自己远见卓识的事情。

第一件是当他申请替孟尝君到自己领地上收债的时候,他把债条都给烧了。理由很简单,孟尝君家里啥都不缺,就缺人心归附。这一举措,在孟尝君被罢黜时,给孟尝君提供了东山再起的缓冲。

第二件是他去忽悠魏王,说齐国强盛都是因为孟尝君,现在他被罢黜了,如果能为魏国效 力,那么魏国富国强兵指日可待。魏王听了后,就派使臣携重礼,三次延请孟尝君到魏国为相。齐王一看,这可不得了,孟尝君确实是人才,要不然魏国怎么会这么 劳师动众来请他。孟尝君因此而得以恢复相位。

第三件是孟尝君恢复相位后,感叹说:以前那堆门客,我一落难就都跑了,现在我恢复了 相位,他们有什么脸面来见我,谁要让我见到了,我一定呸他一脸。冯谖当即跪倒进行劝谏,说:富贵多士,贫贱寡友是自然规律,希望孟尝君能够遇客如故,潜台 词是:你要这么干了,树敌不说,那还能有可用之人。孟尝君又听取了他的建议。

也就是说孟尝君很辉煌的一生和这个没事谈剑要东西的冯谖是分不开的。

也许有的程序员会感觉冯谖这样不挺好么,但在现代冯谖的做事方法实际上是取死之道,几乎百分百会被现存规则轰成灰灰。

从后来行事来看,冯谖无疑是有才华的,但他得以体现才华的机会完全依赖于时势而非是自己争取来的。

他所做的所有事情都是在看不到回报的时候多索取:要鱼、要车、要养家、从孟尝君的角 度看,这些可能连长线投资都算不上。因为在他要东西这个时间点,这个人本身有没有价值则完全没人知道—等价于无价值。在古代还有孟尝君,但在现代企业 里,这么做落在周围人的眼里就是眼高手低,几乎一定会被开除掉。指望沧海横流方显英雄本色是不太行的,万一一辈子沧海也不横流呢。

 

但偏偏冯谖和很多程序员的行事风格还真的有点类似,很多程序员擅长做事但不擅长表达,再加上很多时候程序员收入不低,所以人生境地没准就真和冯谖早时有点类似。

[转载]程序员生存定律--交换是职场里一切的根本 - 理想流 - 博客园

mikel阅读(789)

[转载]程序员生存定律–交换是职场里一切的根本 – 理想流 – 博客园.

程序员生存定律这书的目录在这里:程序员生存定律–目录

喜欢从头瞄的,可以移步。

———————————————————————————————-

支撑职场的基本规则是交换,交换的两端分别是你可创造的价值与你的职场位置(包含收入)。交换就像任督二脉间的通道一样,越是通畅,人生也就越顺风顺水;堵得越死,人也就越寸步难行。

这点要刻在脑子里,一旦要忘记了,就赶紧打自己两个耳光。忘了这点的人一旦被炒,就会很委屈的发“不要拿公司当家”这类感慨。

那什么是交换?

在一般人眼里,交换就是你有个东西我要,我有个东西你要,大家互通有无这样一个过程。但在学者眼里,事情却要更复杂一点。何新先生在《反主流经济学》中,对交换进行了深度剖析,他说:

  • 社会交换成立之第一前提,就是人类之有欲求与需要,而靠自身不能满足。

   因此,事物是否具有使用价值,决定于其能否满足人类之某种欲求与需要。所以,事物之内在属性形成其使用价值。

  • 私有制,占有,占有权利,是社会交换得以发生之第二前提。

   人有需求之物,而先为他人已据有者,若欲取之,只有二途:或强取(掠夺、战争、索要),或巧取——后者即交换。

  • 随机之交换,导致对交换品的偶然随机定价,故成交之价格有极大随意性。

  而常态之交换,则必然趋向理性之定价,即均衡定价。买卖双方经协商而接受的均衡定价之尺度,其依据乃参照商品所内涵之真实价值。

  故:(1)商品确有真实价值存在。

        (2)真实价值乃是一种无形的、形而上的虚拟实体。(马克思说:价值是一种社会关系的反映。)

  • 因此,商品价值之评估有三重性:

  一为使用价值,二为内涵价值,三为外化的实际交换价值。

  交换价格是内涵价值的外化表现。内涵价值与价格之不同,在于内涵价值是内在的、非外现的。

  • 物品买卖成交之交换量,谓之价格或市场价格。

    价格具主观性,是商品内涵固有之价值之外化。内涵价值能否得到实现,取决于需求者之购买评估。内涵价值得到市场实现,意味着商品转换为货币。

  • 但是,价值在市场中之二重化,价格对价值之背离,造成等价交换规律之破坏。等价交换意味着等价价值品之交换,并非意味同等价格品之交换。同等价格对同等价格之交换,未必是等价交换。因市场价格之形成,受市场之需求度影响,而非单纯决定于价值之同等性。

上面这段文字说的是经济,所以很多人会看的云里雾里,但其中对交换的解析入木三分,只要我们还承认工作本身也是一种个人和法人间的交换,那么就逃不出这些约束虽然有杀鸡用牛刀之嫌疑。

尽管上面的解释已经非常清楚,但为了让其更加的通俗易懂,这里附加一点说明:

交换本身起源于互有所需,比如:某一公司开发打印机驱动程序,那么就需要了解页面描述语言(PDL)、操作系统打印子系统技能的程序员。

交换本身的基本原则是等价交换,但这种原则往往会被市场需求度等因素破坏。比如:TTS可能很难搞,一个人学习了数十年,本应获得较高的市场价格,但很不幸,如果搞这个的人碰巧很多,或者应用还不广,这时候交换价格也可能很低。想想同样是在科大讯飞,工作实质没什么太大变化,但在移动互联网兴起前和兴起后交换的价格会不会有很大差异。

破坏这一原则的因素还有很多,比如说垄断。如果一个人掌握的技术只有一家公司用,那么这个公司具有破坏等价交换原则的权利。反过来讲,如果某项技术只有某个人掌握,那么这个人具有破坏等价交换的权利。

工资可以表示为一种成交价格,这一价格具有一定的随意性,具体表现为同样工作内容,不同公司,不同时间点,收入差异可能非常巨大。比如:同等技术能力下,表现力好的程序员可能更容易获得较好的薪资。但总体市场行情却在一定范围内趋向于稳定,比如毕业生的起薪大致在10K/月以下,GoogleFacebook这些公司的平均薪资相差也不大。

这也就意味着,影响最终交换价格(即工资收入的)的主要是两个因素:内含价值和市场因素(稀缺性等)。

在程序员与公司进行交换的过程中,其中最为基础的一点是你要有维护自身权利的能力,即程序员自身要有选择权,在只能被选择时,事情会趋向于另一个极端:必须不停的让步,放弃各种可争得的权利,最直接的表现是收入上没有议价能力。

很少有公司会主动宣传工作首先是一种交换,但这一事实本身却应该没什么太多的争议。但细想下来这个基础支撑点也只能是交换, 恰如食物、水与生命间的关联。对外,企业有所产出,与客户交换获取利润;对内,则是员工有所产出,与企业交换获取工资等等。这是经济形态所决定的,在这一 前提下,裁员与跳槽都是一种必然出现的现象,反倒是雇佣终身制是反其道而行。

认清交换是第一支撑之后,我们就可以推导出职场生存定律。

[转载]支付宝手机网站支付接口 FOR ECShop-PHP教程-第七城市

mikel阅读(1076)

[转载]支付宝手机网站支付接口 FOR ECShop-PHP教程-第七城市.

支付宝WAP网站版本的支付接口网上整合的比较少,看到很多网站在卖,顿觉无语。

主要是得自己查看支付宝官方提供的SDK中的开发文档。

支付宝sdk下载地址:http://club.alipay.com/read-htm-tid-9976972.html

1. 要使用支付宝手机网站支付接口,除了要配置基本的帐号外,还必须配置openssl密钥文件。关于key的生成,一定要看文档,在此不详述。文档上演示的 在线上传key的界面地址为:https://mobiless.alipay.com/home/index.htm ,key一定要存在,而且地址要正确,不然支付宝那边不能返回有效的界面

2.以独立的支付接口形式提供,便于用户根据自己的需求再做定制;

3. 附件提供的代码是简单的集成,仅起一个演示作用,没有考虑代码的复用性之类

ecshop支付宝手机网站支付接口下载地址: http://files.cnblogs.com/x3d/ecshop_payment_alipay_wap.zip

[转载]个性二维码开源专题 - 五加乘 - 博客园

mikel阅读(1114)

[转载]个性二维码开源专题 – 五加乘 – 博客园.

二维码原理介绍:

二维码为什么是黑白相间的?黑色表示二进制的“1”,白色表示二进制的“0”

“我们之所以对二维码进行扫描能读出那么多信息,就是因为这些信息被编入了二维码之中。”黄海平说,“制作二维码输入的信息可以分成三类,文本信 息,比如名片信息;字符信息,比如网址、电话号码;还有图片信息,甚至还可以包括简短的视频。”数据信息是怎么被编入的呢?信息输入后,首先要选择一种信 息编码的码制。现在常见的二维码都是以QR码作为编码的码制。QR码是矩阵式二维码,它是在一个矩形空间内,通过黑、白像素在矩阵中的不同分布,来进行编 码的。我们知道电脑使用二进制(0和1)数来贮存和处理数据,而在二维码中,用黑白矩形表示二进制数据我们肉眼能看到的黑色表示的是二进制“1”,白色表 示二进制的“0”,黑白的排列组合确定了矩阵式二维条码的内容,以便于计算机对二维码符号进行编码和分析。

 

百度经验:http://jingyan.baidu.com/article/86f4a73e520e3b37d6526981.html

 

开始使用:

命名规则最好遵守,因为套入模版使用的是反射技术,对前缀命名有要求。

 

1.创建类库

命名Yc.QrcodeLib.xxx 

2.创建类

命名QrEncode

手脚架:

基础参数:

///
/// 二维码默认参数
///

QRCodeEncoder
///
/// 二维码大小
///

public int QRCodeScale { get; set; }

///
/// 二维码版本(默认0时,自动适应版本)
///

public int QRCodeVersion { get; set; }

///
/// 二维码编码
///

public QRCodeEncoder.ENCODE_MODE QRCodeEncodeMode { get; set; }

public enum ENCODE_MODE
{
ALPHA_NUMERIC = 0,
NUMERIC = 1,
BYTE = 2,
}

///
/// 二维码容错率
///

public QRCodeEncoder.ERROR_CORRECTION QRCodeErrorCorrect { get; set; }

public enum ERROR_CORRECTION
{
L = 0,
M = 1,
Q = 2,
H = 3,
}
///
/// 二维码容边距
///

public int FrameSpacing { get; set; }
///
/// 二维码容高边距
///

public int FrameSpacingH { get; set; }
///
/// 二维码容宽边距
///

public int FrameSpacingW { get; set; }

基础方法:

///
/// 修改填充形状
///

ChangeFillShape(...)

填充色示例:

QRCodeEncoder _qrCodeEncoder = new QRCodeEncoder();
_qrCodeEncoder.QRCodeForegroundColor = Color.Red;

背景色示例:

QRCodeEncoder _qrCodeEncoder = new QRCodeEncoder();
_qrCodeEncoder.QRCodeBackgroundColor = Color.Red;

边距示例:

QRCodeEncoder _qrCodeEncoder = new QRCodeEncoder();
_qrCodeEncoder.FrameSpacing = 4;

 

其他就不一一示例了,都大同小异的。

希望这篇文章对大家,研究二维码有更深的认识。

 

以下是开源地址,国外github,国内oschina.net

oschina.net:

http://git.oschina.net/cheng5x/Yc.QrCode

 

github:

https://github.com/cheng5x/YcQrCode

 

官方网站
http://original-ad.com

码晒客讨论QQ群:
28629273

[转载]使用c#创建php可以调用的dll - 做最好的自己 - 博客频道 - CSDN.NET

mikel阅读(1079)

[转载]使用c#创建php可以调用的dll – 做最好的自己 – 博客频道 – CSDN.NET.

1. 创建一个 C# Class Library ,命名为:HelloWorld

2. 打开项目的属性,在点选左边的 “Application”(就是第一个tab) , 然后点击 Assembly Information 按钮 ,在弹出的Dialog中, 必须在底部勾上: Make assembly COM-visible !否则 , 这个dll将不能以COM方式访问 .(  也可以在代码中的类声明中写上[ComVisible(true)] , 效果一样,需要增加using System.Runtime.InteropServices;引用)

3. 创建强命名签名文件并使用
使用vs.net的“Vsitual Studio .Net工具”–>Vistual Studio .Net命令提示符,输入 sn -k d:\HelloWorld.snk回车即创建了强命名签名文件
打开项目的属性,点选左边Signing 勾上Sign the assembly 在 Choose a strong name key file:处选择<Browse> 选择刚才创建的HelloWorld.snk文件

4. 创建类库并编译成dll

namespace HelloWorld
{
[ComVisible(true)]
public class Hello
{
public string Write()
{

return "Hello World";
}
}

}

5. 找到dll文件夹路径 ,然后使用vs.net的“Vsitual Studio .Net工具”–>Vistual Studio .Net命令提示符
进入该dll文件夹下输入: regasm  HelloWorld.dll<回车>。
这时候,这个.dll的.net程序集就变成一个标准的Com组件了,但是还不能用,必须让它变成全局Com组件.
这个regasm 实用程序将创建一个类型库并在 Windows 注册表中对其进行注册,以使 PhysServer2.dll 中的类对 COM 客户端可用 .
需要做下面步骤
将程序集添加到全局程序集缓存中
进入提示符窗口,输入: gacutil /I HelloWorld.dll<回车>
这时,你的这个dll就被复制到全局程序集缓存中了.也就是说无论在这个电脑的哪个硬盘上都可以使用此dll组件了.
如果不进行强命名签名,这一步会提示加载失败

PHP测试

<!--?php   $r=new Com("HelloWorld.Hello");   $s=$r--->Write();
echo $s;
?&gt;

[转载]性能分析工具-PerfView - 张善友 - 博客园

mikel阅读(1271)

[转载]性能分析工具-PerfView – 张善友 – 博客园.

Roslyn的PM(程序经理) Bill Chiles,Roslyn使用纯托管代码开发,但性能超过之前使用C++编写的原生实现,这有什么秘诀呢?他最近写了一篇文章叫做《Essential Performance Facts and .NET Framework Tips》里头推荐了一个性能分析工具《Improving Your App’s Performance with PerfView》。 PerfView能够收集Windows事件跟踪(ETW)数据来追踪程序的调用流向,这些程序通过调用哪个函数识别频率。除了配置程序性能数据 (Perfmon、PAL和Xperf等工具不能轻松完成),PerfView还能分析程序内存堆来帮助确定内存的运用是否高效。它还有一个Diff功 能,可以让你确定跟踪间的任意差别来帮助你认出所有逆行。最后,该工具还有一个Dump功能可以生成一个程序内存转储。

安装PerfView

从微软下载的 PerfView 包括一个zip压缩文件,其中只有一个可执行的文件perfview.exe,这简化了安装。你可以将这个文件复制到多个你想跟踪的服务器上,然后在这些 服务器或你本地的工作站中分析数据。PerfView在Windows Vista、Windows 7、Windows Server 2008、Windows Server 2008 R2和Windows Server 2012上都受到支持,要求.NET FX 2.0以上。

收集配置数据

PerfView利用Windows事件追踪,而ETW从Windows 2000 Server以来就一直内置于操作系统中。只是最近才有XPerf和PerfView一类的工具利用ETW数据来解决性能问题。事件数据被收集到一个事件 跟踪日志(ETL)中。根据你想要跟踪事件的数量和时间的长度,ETL文件可能会非常大。你可以限制这个日志文件的大小,如果空间受限或者你不知道问题何 时发生的话,你还可以让它们循环。默认每毫秒一次的采样间隔在收集时间内产生了大概百分之十的CPU开支。建议大概5000个样本(5秒)用于一次代表性 配置采样。

开始一次数据收集有两种方式,用运行命令启动一个程序或者用收集命令在计算机范围内收集数据。这些命令可以由收集下拉菜单下的GUI引发,或者从 CLI或脚本中执行“PerfView run”或“PerfView collect”命令。下图显示运行命令tutorial.exe时收集数据的过程,tutorial.exe是一个内置的训练练习。
image

查看结果

一旦你在些之间针对性能问题收集了数据,你可以用PerfView分析ETL文件。该ETL文件会出现在左边的窗口,有收集日志或运行命令期间你提 供的名字。通过双击该RTL文件,十来个独立的节点会和指代它们内容的名字一起出现。例如,你会在下图中看到跟踪信息、程序、事件、CPU堆栈。双击各个 节点,适当的查看器会打开这些内容。

image

为了针对一个特定程序分析计算密集型性能问题,你将需要学习要调用的堆栈和函数。这可以通过双击左侧窗口中的“CPU堆栈”节点完成。接着你会得到 提示来选择你感兴趣的程序。最后,该CPU堆栈查看器会在独立的窗口中打开,如下图QQ进程的信息 ,你可以确定调用了哪个函数以及它们的频率。

image

如果你仔细查看上面的例子,你会发现第一行显示<<user32!?>>。“!?”代表PerfView不能解析这个模块名称。 你可以双击这个未知模块名称并选择“查找符号”来显示该模块名称。按用户指南所述配置符号路径对于解析操作系统函数名称也许是有必要的。

PerfView是一个便于用户的工具,可以用来收集和分析ETW数据用于解决配置程序性能数据的问题。这个工具可以快速地显示为这个程序执行的操作系统函数,了解性能问题可能潜藏的位置。