2006年03月17日

         离我上次更新blog已经很长一段时间了,主要是心情问题,心情不好的时候什么都懒的做,所以就应该学会怎么去调节自己的心情。

         今天刚上msn就碰见轩子了,他让我看看他的择保网,说实话,我很少去评价什么东西的(原因也许是水平不够),所以只能从普通用户的角度去看看,首页给我的第一感觉就是清晰明了,第一感觉很重要的,这样可以不至于浏览者马上离开,整个页面采用div+css结构,这样可以为以后页面的调整提供快速稳定的解决办法。看了一会儿总觉得缺点什么,也许是每个人的审美观不同吧,我觉的有点动态的因素就好了,当然现在网站好像是正在开发中,也许很快就上线运行了。

          关于保险我并不懂,我自己也没什么保险,:)

         但是把保险放到网上去选择,我觉得最重要的一点还是诚信和知名度,诚信很重要,这一点勿庸置疑;知名度也是同样重要,网站一定要有中让人一看上去就很有实力的样子,起码在感觉上要有,因为互联网上的网站说消失就消失,数据的丢失也不是不可能,所以从安全感上说,人们一般都是信任有实力的,大的网站。这一点相信择保网不远的将来会变好的。

       关于网站的功能,我不懂保险所以也没法说,以上都是自己从感觉上说的,呵呵,就像我的题目一样,闲评一下

2005年12月31日

      不知不觉之间2005年就这样过去了,时间就是这样,经历起来觉得很长,但回想起来就转瞬即逝。

       在这一年中有些事深深地印在了我的脑海里,经历了很多很多,因为我是2005届的毕业生,所以说有些事是以前没有经历过的。再这一年中接触的社会多了,自己要找工作,自己要独立面对很多问题,努力让自己去适应这个社会。人不能光有美丽的梦想,还要有着面对现实的生活。

        大学毕业时,有种莫名的的悲哀,毕竟在一块四年了,人生又能有多少个四年呢?

        深夜里,我常常在思考着自己的人生道路,思考着人生这短短几十年应该是个什么样子的,未来充满着迷茫,2006就要来了,新的一年不知又会是什么样的。

2005年12月08日

Repeater Web 控件最主要的用途,是可以将数据依照我们所制定的格式逐一显示出来。只要将想要显示的格式先定义好,Repeater Web 就会依照我们所定义的格式来显示;这个预先定义好的格式我们称为「样版」(Template)。使用样版可以让我们的资料可以更容易、更美观的呈现给使用者;支持样版的Web 控件有Repeater、DataList 以及DataGrid。接下来我们先来了解Repeater Web 控件的使用语法:

<ASP:Repeater

Id="被程序代码所控制的名称"
Runat="Server"
DataSource=’<%# 数据系结叙述%>’
>
<Template Name="样版名称">
以HTML 所定义的样版
</Template >
其它样版定义…
</ASP:Repeater>

Repeater Web 控件所支持的样版如下表所示:


其中Item 样版必须要定义才能顺利显示资料。下列范例利用Repeater Web 控件显示使用者姓名及电子邮件信箱:

<%@Import Namespace=System.Data.ADO%>
<%@Import Namespace=System.Data%>
<!–#Include File="GetTable.inc"–>
<Html>
<ASP:Repeater Id="rpA" Runat="Server">
<Template Name="ItemTemplate">
<ASP:Image Id="I1" ImageUrl="ico1.gif" Runat="Server"/>
姓名:<%#Container.DataItem("UserName")%><br>
<ASP:Image Id="I2" ImageUrl="ico2.gif" Runat="Server"/>
电邮:<%#Container.DataItem("UserEmail")%><br>
</Template>
</ASP:Repeater>
<Script Language="VB" Runat="Server">
Sub Page_Load(Sender As Object, e As EventArgs)
Dim dtDataTable As DataTable=GetTable("CH05\MyWeb.mdb", "Members")
rpA.DataSource=dtDataTable.DefaultView
Page.DataBind()
End Sub
</SCRIPT>
</Html>


    上述范例中定义了一个ItemTemplate 样版,在这个样版中的数据系结叙述使用了<%#Container.DataItem("UserName")%> 这个资料系结叙述,其中Container 英文的意思是容器,这里是表示样版放置在哪个对象中;我们在Repeater Web 控件中使用这个样版,所以这个样版的容器就是Repeater Web 控件。当程序在执行时,使用Container 关键词会传回RepeaterWeb 控件的参考,这时候就可以利用Repeater Web 控件的DataItem 属性取得目前要显示的记录字段。下列范例展现了所有的样版:

<%@Import Namespace=System.Data.ADO%>
<%@Import Namespace=System.Data%>
<!–#Include File="GetTable.inc"–>
<Html>
<ASP:Repeater Id="rpA" Runat="Server">
<Template Name="HeaderTemplate">
<ASP:Image ImageUrl="ico3.gif" Runat="Server"/> <br>
</Template>
<Template Name="ItemTemplate">
<ASP:Image ImageUrl="ico1.gif" Runat="Server"/>
姓名: <%#Container.DataItem("UserName")%><br>
<ASP:Image ImageUrl="ico2.gif" Runat="Server"/>
电邮: <%#Container.DataItem("UserEmail")%><br>
</Template>
<Template Name="AlternatingItemTemplate">
<ASP:Image ImageUrl="ico1.gif" Runat="Server"/>
姓名: <%#Container.DataItem("UserName")%>
<ASP:Image ImageUrl="ico2.gif" Runat="Server"/>
电邮: <%#Container.DataItem("UserEmail")%><br>
</Template>
<Template Name="SeparatorTemplate">
<ASP:Image ImageUrl="ico5.gif" Runat="Server"/><br>
</Template>
<Template Name="FooterTemplate">
<ASP:Image ImageUrl="ico4.gif" Runat="Server"/><br>
</Template>
</ASP:Repeater>
总共有<ASP:Label Id="Label1" Runat="Server"/> 笔记录
<Script Language="VB" Runat="Server">
Sub Page_Load(Sender As Object, e As EventArgs)
Dim dtDataTable As DataTable=GetTable("CH05\MyWeb.mdb", "Members")
rpA.DataSource=dtDataTable.DefaultView
Page.DataBind()
Label1.Text=rpA.Items.Count
End Sub
</SCRIPT>
</Html>

  如果你正在使用ASP.NET,你一定对DataGrid控件非常熟悉。DataGrid控件提供了各种特性,通过这些特性可以很容易地在一个Web页面上以列表形式显示数据。但是,如果你不想使用HTML表格形式呢?此时,可以使用一个DataGrid的一个鲜为人知的兄弟控件,即Repeater控件。Repeater控件提供显示你所需要数据的灵活性。

Repeater控件是什么?
 
Repeater是一个可重复操作的控件,也就是说,它通过使用模板显示一个数据源的内容,而你可以很容易地配置这些模板。Repeater包含如标题和页脚这样的数据,它可以遍历所有的数据选项并应用到模板中。

与DataGrid和DataList控件不同,Repeater控件并不是由WebControl类派生而来。所以,它不包括一些通用的格式属性,比如控制字体,颜色,等等。然而,使用Repeater控件,HTML(或者一个样式表)或者ASP.NET类可以处理这些属性。

HTML在哪里?
Repeater控件与DataGrid (以及DataList)控件的主要区别是在于如何处理HTML。ASP.NET建立HTML代码以显示DataGrid控件,但Repeater允许开发人员决定如何显示数据。所以,你可以选择将数据显示在一个HTML表格中或者一个顺序列表中。这主要取决于你的选择,但你必须将正确的HTML插入到ASP.NET页面中。

模板与DataList一样,Repeater控件只支持模板。以下的模板可供选择:

AlternatingItemTemplate: 指定如何显示每一其它选项。
ItemTemplate: 指定如何显示选项。(AlternatingItemTemplate可以覆盖这一模板。)
HeaderTemplate: 建立如何显示标题。
FooterTemplate: 建立如何显示页脚。
SeparatorTemplate: 指定如何显示不同选项之间的分隔符。
你可以使用这些模板来显示你希望的数据。唯一具有强制性的模板是ItemTemplate,所有其它的模板都是具有选择性的。

数据
对于处理一个数据源,Repeater控件具有与DataGrid与DataList相同的属性:

DataMember:获得或者设置与 Repeater 控件绑定的相应DataSource属性的表格。

DataSource:获得或者设置为 Repeater 显示提供数据的数据源。

除此之外,还有一个Items属性,你可以通过这一属性编程访问Repeater数据中单一选项。它返回一个RepeaterItemCollection对象,为一组RepeaterItem对象的集合,代表 Repeater 数据的每一行。

ASP.NET Web数据控件还有其它一个共性:它们都使用DataBind方法来生成用户界面。调用这一方法可以返回并显示数据(假设DataSource和DataMember属性设置正确)。在查看DataBind方法之前,我们先看看如何在一个Web页面中使用一个Repeater控件。

使用Repeater控件
使用Repeater控件的第一步骤是决定我们将要使用的数据源和字段。例如,我们将要使用SQL Server Northwind数据库中的Employees列表。Web页面将显示职工的完整名字,地址,以及电话号码。HTML将使用DIV标记,用 Repeater 模板来分隔内容。下面是 Web 页面的 HTML 内容:

<%@ Page language="c#" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<html><head>
<title>Builder.com Repeater Example</title>
<meta name="GENERATOR" Content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" Content="C#">
<style>
.alternate {
FONT-WEIGHT: bold;
COLOR: black;
FONT-FAMILY: Verdana, ‘Times New Roman’;
BACKGROUND-COLOR: yellow
}
.row {
FONT-WEIGHT: bold;
COLOR: black;
FONT-FAMILY: Verdana, ‘Times New Roman’;
BACKGROUND-COLOR: white
}
.footer {
FONT-WEIGHT: bold;
COLOR: red;
FONT-FAMILY: Verdana, ‘Times New Roman’;
BACKGROUND-COLOR: gray
}
.header {
FONT-WEIGHT: bold;
COLOR: yellow;
FONT-FAMILY: Verdana, ‘Times New Roman’;
BACKGROUND-COLOR: gray
}
.box {
BORDER-RIGHT: blue groove;
BORDER-TOP: blue groove;
DISPLAY: block;
VERTICAL-ALIGN: baseline;
OVERFLOW: auto;
BORDER-LEFT: blue groove;
CURSOR: wait;
BORDER-BOTTOM: blue groove;
FONT-FAMILY: verdana;
TEXT-ALIGN: center
}
body {
background: #333;
}
</style>
<script language="C#" runat="server">
private void Page_Load(object sender, System.EventArgs e) {
if (!IsPostBack) {
DataSet dset = new DataSet();
string conn = "server=(local);Initial Catalog=Northwind;UID=ctester;PWD=password";
string qry = "SELECT firstname, lastname, address, city, region, postalcode,
homephone FROM employees";
SqlDataAdapter sda = new SqlDataAdapter(qry, conn);
sda.Fill(dset);
Repeater1.DataSource = dset.Tables[0].DefaultView;
Repeater1.DataBind();
} }
</script></head>
<body MS_POSITIONING="GridLayout" bgColor="#00cc99">
<form id="Form1" method="post" runat="server">
<div class="box">
<asp:Repeater id="Repeater1" runat="server">
<HeaderTemplate>
<div class="header" id="header">Northwind Employees</div>
</HeaderTemplate>
<SeparatorTemplate><hr /></SeparatorTemplate>
<ItemTemplate><div class="row">
<%# ((DataRowView)Container.DataItem)["FirstName"] %>
<%# ((DataRowView)Container.DataItem)["LastName"] %><br>
<%# ((DataRowView)Container.DataItem)["Address"] %><br>
<%# ((DataRowView)Container.DataItem)["City"] %>, 
<%# ((DataRowView)Container.DataItem)["Region"] %>  
<%# ((DataRowView)Container.DataItem)["PostalCode"] %><br>
<%# ((DataRowView)Container.DataItem)["HomePhone"] %>
</div></ItemTemplate>
<AlternatingItemTemplate><div class="alternate">
<%# ((DataRowView)Container.DataItem)["FirstName"] %>
<%# ((DataRowView)Container.DataItem)["LastName"] %><br>
<%# ((DataRowView)Container.DataItem)["Address"] %><br>
<%# ((DataRowView)Container.DataItem)["City"] %>, 
<%# ((DataRowView)Container.DataItem)["Region"] %>  
<%# ((DataRowView)Container.DataItem)["PostalCode"] %><br>
<%# ((DataRowView)Container.DataItem)["HomePhone"] %>
</div></AlternatingItemTemplate>
<FooterTemplate><div class="footer">
<%# ((DataView)Repeater1.DataSource).Count + " employees found." %>
</div></FooterTemplate>
</asp:Repeater></div></form></body></html>
 

可以注意到,每个 Repeater 行中样式表控制着文字的外观。除此之外,在网页内容中还添加了一个文本框。嵌入式 C# 代码从 Repeater 的数据源中获取相应的列。每个数据项都被转换成一个DataRowView对象以便显示。

这一页面并不是使用ASP.NET的“后台代码”性质。由于这一原因,页面引用了两个System.Data和System.Data.SqlClient空间名称。这对于使用DataRowView对象和与 SQL Server 交互访问是必需的。

当调用页面时就会触发Page_Load事件。此时会把数据源连接到 Repeater 控件上,并查询数据库。每一Repeater行的代码从潜在数据源中载入数据,并且Web页面显示这些数据。

这一设计使用了样式表(以及 HTML div 标记),所以更改外观只需要更改必要的样式表代码。为了进一步地将数据和显示分离,你可以在一个独立文件中存储样式表,并以一个HTML LINK标记来引用它们。

一个很好的选择
当与其他 ASP.NET 开发者交流时,开发人员对 Repeater 控件知之甚少,这真让我感到惊讶。虽然它不如DataGrid功能强大,但它在许多场合中仍然提供了出色的灵活性。Repeater 控件缺少编辑和排序功能,但可以通过进一步编程而实现。

       有人在Donews上碰到过木马没有?

出于好奇,不知有人用donews的iframe挂过马没有(不道德啊!!!!)      :-)

这是在网页设计师上看到的一篇文章,很适合入门div+css布局的人看,转了过来收藏

你正在学习CSS布局吗?是不是还不能完全掌握纯CSS布局?通常有两种情况阻碍你的学习:

第一种可能是你还没有理解CSS处理页面的原理。在你考虑你的页面整体表现效果前,你应当先考虑内容的语义和结构,然后再针对语义、结构添加CSS。这篇文章将告诉你应该怎样把HTML结构化。

另一种原因是你对那些非常熟悉的表现层属性(例如:cellpadding,、hspace、align="left"等等)束手无策,不知道该转换成对应的什么CSS语句。当你解决了第一种问题,知道了如何结构化你的HTML,我再给出一个列表,详细列出原来的表现属性用什么CSS来代替。

结构化HTML

我们在刚学习网页制作时,总是先考虑怎么设计,考虑那些图片、字体、颜色、以及布局方案。然后我们用Photoshop或者Fireworks画出来、切割成小图。最后再通过编辑HTML将所有设计还原表现在页面上。

如果你希望你的HTML页面用CSS布局(是CSS-friendly的),你需要回头重来,先不考虑“外观”,要先思考你的页面内容的语义和结构。

外观并不是最重要的。一个结构良好的HTML页面可以以任何外观表现出来,CSS Zen Garden是一个典型的例子。CSS Zen Garden帮助我们最终认识到CSS的强大力量。

HTML不仅仅只在电脑屏幕上阅读。你用photoshop精心设计的画面可能不能显示在PDA、移动电话和屏幕阅读机上。但是一个结构良好的HTML页面可以通过CSS的不同定义,显示在任何地方,任何网络设备上。

开始思考

首先要学习什么是"结构",一些作家也称之为"语义"。这个术语的意思是你需要分析你的内容块,以及每块内容服务的目的,然后再根据这些内容目的建立起相应的HTML结构。

如果你坐下来仔细分析和规划你的页面结构,你可能得到类似这样的几块:

  • 标志和站点名称
  • 主页面内容
  • 站点导航(主菜单)
  • 子菜单
  • 搜索框
  • 功能区(例如购物车、收银台)
  • 页脚(版权和有关法律声明)

我们通常采用DIV元素来将这些结构定义出来,类似这样:

<div id="header"></div>

<div id="content"></div>

<div id="globalnav"></div>

<div id="subnav"></div>

<div id="search"></div>

<div id="shop"></div>

<div id="footer"></div>

这不是布局,是结构。这是一个对内容块的语义说明。当你理解了你的结构,就可以加对应的ID在DIV上。DIV容器中可以包含任何内容块,也可以嵌套另一个DIV。内容块可以包含任意的HTML元素—标题、段落、图片、表格、列表等等。

根据上面讲述的,你已经知道如何结构化HTML,现在你可以进行布局和样式定义了。每一个内容块都可以放在页面上任何地方,再指定这个块的颜色、字体、边框、背景以及对齐属性等等。

使用选择器是件美妙的事

id的名称是控制某一内容块的手段,通过给这个内容块套上DIV并加上唯一的id,你就可以用CSS选择器来精确定义每一个页面元素的外观表现,包括标题、列表、图片、链接或者段落等等。例如你为#header写一个CSS规则,就可以完全不同于#content里的图片规则。

另外一个例子是:你可以通过不同规则来定义不同内容块里的链接样式。类似这样:#globalnav a:link或者 #subnav a:link或者#content a:link。你也可以定义不同内容块中相同元素的样式不一样。例如,通过#content p和#footer p分别定义#content和#footer中p的样式。从结构上讲,你的页面是由图片、链接、列表、段落等组成的,这些元素本身并不会对显示在什么网络设备中(PDA还是手机或者网络电视)有影响,它们可以被定义为任何的表现外观。

一个仔细结构化的HTML页面非常简单,每一个元素都被用于结构目的。当你想缩进一个段落,不需要使用blockquote标签,只要使用p标签,并对p加一个CSS的margin规则就可以实现缩进目的。p是结构化标签,margin是表现属性,前者属于HTML,后者属于CSS。(这就是结构于表现的相分离.)

良好结构的HTML页面内几乎没有表现属性的标签。代码非常干净简洁。例如,原先的代码<table width="80%" cellpadding="3" border="2" align="left">,现在可以只在HTML中写<table>,所有控制表现的东西都写到CSS中去,在结构化的HTML中,table就是表格,而不是其他什么(比如被用来布局和定位)。

亲自实践一下结构化

上面说的只是最基本的结构,实际应用中,你可以根据需要来调整内容块。常常会出现DIV嵌套的情况,你会看到"container"层中又有其它层,结构类似这样:

<div id="navcontainer">

<div id="globalnav">

<ul>a list</ul>

</div>

<div id="subnav">

<ul>another list</ul>

</div>

</div>

嵌套的div元素允许你定义更多的CSS规则来控制表现,例如:你可以给#navcontainer一个规则让列表居右,再给#globalnav一个规则让列表居左,而给#subnav的list另一个完全不同的表现。

用CSS替换传统方法

下面的列表将帮助你用CSS替换传统方法:

HTML属性以及相对应的CSS方法

HTML属性 CSS方法 说明
align="left"

align="right"
float: left;

float: right;

使用CSS可以浮动 任何元素:图片、段落、div、标题、表格、列表等等

当你使用float属性,必须给这个浮动元素定义一个宽度。

marginwidth="0" leftmargin="0" marginheight="0" topmargin="0" margin: 0;

使用CSS, margin可以设置在任何元素上, 不仅仅是body元素.更重要的,你可以分别指定元素的top, right, bottom和left的margin值。

vlink="#333399" alink="#000000" link="#3333FF"

a:link #3ff;

a:visited: #339;

a:hover: #999;

a:active: #00f;

在HTML中,链接的颜色作为body的一个属性值定义。整个页面的链接风格都一样。使用CSS的选择器,页面不同部分的链接样式可以不一样。

bgcolor="#FFFFFF" background-color: #fff;

在CSS中,任何元素都可以定义背景颜色,不仅仅局限于body和table元素。

bordercolor="#FFFFFF" border-color: #fff;

任何元素都可以设置边框(boeder),你可以分别定义top, right, bottom和left

border="3"

cellspacing="3"
border-width: 3px;

用CSS,你可以定义table的边框为统一样式,也可以分别定义top, right, bottom and left边框的颜色、尺寸和样式。

你可以使用 table, td or th 这些选择器.

如果你需要设置无边框效果,可以使用CSS定义: border-collapse: collapse;

<br clear="left">

<br clear="right">

<br clear="all">

clear: left;

clear: right;

clear: both;

许多2列或者3列布局都使用 float属性来定位。如果你在浮动层中定义了背景颜色或者背景图片,你可以使用clear属性.

cellpadding="3"

vspace="3"

hspace="3"
padding: 3px;

用CSS,任何元素都可以设定padding属性,同样,padding可以分别设置top, right, bottom and left。padding是透明的。

align="center"

text-align: center;

margin-right: auto; margin-left: auto;

Text-align 只适用于文本.

象div,p这样的块级怨毒可以通过margin-right: auto; margin-left: auto;来水平居中

一些令人遗憾的技巧和工作环境

由于浏览器对CSS支持的不完善,我们有时候不得不采取一些技巧(hacks)或建立一种环境(Workarounds)来让CSS实现传统方法同样的效果。例如块级元素有时侯需要使用水平居中的技巧,盒模型bug的技巧等等。所有这些技巧都在Molly Holzschlag的文章《Integrated Web Design: Strategies for Long-Term CSS Hack Management》中有详细说明。

另外一个关于CSS技巧的资源站点是Big John和Holly Bergevin的“Position is Everything”。

理解浮动行为

Eric Meyer的《Containing Floats》将帮助你掌握如何使用float属性布局。float元素有时候需要清除(clear),阅读《How To Clear Floats Without Structural Markup》将非常有帮助。

更多帮助

已有的《CSS Discussion》列表是很好的资源,它收集了一个WiKiA讨论组的信息,其中包括CSS布局总结(css-discuss.incutio.com/?page=CssLayouts),CSS 技巧总结 (css-discuss.incutio.com/?page=CssHack) 以及更多

 

1.、DateTime 数字型
System.DateTime currentTime=new System.DateTime();
1.1 取当前年月日时分秒
currentTime=System.DateTime.Now;
1.2 取当前年
int 年=currentTime.Year;
1.3 取当前月
int 月=currentTime.Month;
1.4 取当前日
int 日=currentTime.Day;
1.5 取当前时
int 时=currentTime.Hour;
1.6 取当前分
int 分=currentTime.Minute;
1.7 取当前秒
int 秒=currentTime.Second;
1.8 取当前毫秒
int 毫秒=currentTime.Millisecond;
(变量可用中文) chinaitpower.comNJMNpKx60pHmoHa

1.9 取中文日期显示——年月日时分
string strY=currentTime.ToString("f"); //不显示秒 chinaitpower.comNJMNpKx60pHmoHa

1.10 取中文日期显示_年月
string strYM=currentTime.ToString("y"); chinaitpower.comNJMNpKx60pHmoHa

1.11 取中文日期显示_月日
string strMD=currentTime.ToString("m"); chinaitpower.comNJMNpKx60pHmoHa

1.12 取当前年月日,格式为:2003-9-23
string strYMD=currentTime.ToString("d"); chinaitpower.comNJMNpKx60pHmoHa

1.13 取当前时分,格式为:14:24
string strT=currentTime.ToString("t"); chinaitpower.comNJMNpKx60pHmoHa

2、Int32.Parse(变量) Int32.Parse("常量")
字符型转换 转为32位数字型 chinaitpower.comNJMNpKx60pHmoHa

3、 变量.ToString()
字符型转换 转为字符
12345.ToString("n"); //生成 12,345.00
12345.ToString("C"); //生成 ¥12,345.00
12345.ToString("e"); //生成 1.234500e+004
12345.ToString("f4"); //生成 12345.0000
12345.ToString("x"); //生成 3039 (16进制)
12345.ToString("p"); //生成 1,234,500.00% chinaitpower.comNJMNpKx60pHmoHa


4、变量.Length 数字型
取字串长度:
如: string str="中国";
int Len = str.Length ; //Len是自定义变量, str是求测的字串的变量名 chinaitpower.comNJMNpKx60pHmoHa

5、System.Text.Encoding.Default.GetBytes(变量)
字码转换 转为比特码
如:byte[] bytStr = System.Text.Encoding.Default.GetBytes(str);
然后可得到比特长度:
len = bytStr.Length; chinaitpower.comNJMNpKx60pHmoHa

6、System.Text.StringBuilder("")
字符串相加,(+号是不是也一样?)
如:System.Text.StringBuilder sb = new System.Text.StringBuilder("");
sb.Append("中华");
sb.Append("人民");
sb.Append("共和国"); chinaitpower.comNJMNpKx60pHmoHa

7、变量.Substring(参数1,参数2);
截取字串的一部分,参数1为左起始位数,参数2为截取几位。
如:string s1 = str.Substring(0,2); chinaitpower.comNJMNpKx60pHmoHa

8、String user_IP=Request.ServerVariables["REMOTE_ADDR"].ToString();
取远程用户IP地址 chinaitpower.comNJMNpKx60pHmoHa

9、穿过代理服务器取远程用户真实IP地址:
if(Request.ServerVariables["HTTP_VIA"]!=null){
string user_IP=Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
}else{
string user_IP=Request.ServerVariables["REMOTE_ADDR"].ToString();
} chinaitpower.comNJMNpKx60pHmoHa

10、 Session["变量"];
存取Session值;
如,赋值: Session["username"]="小布什"; chinaitpower.comNJMNpKx60pHmoHa

取值: Object objName=Session["username"];
String strName=objName.ToString();
清空: Session.RemoveAll(); chinaitpower.comNJMNpKx60pHmoHa

11、String str=Request.QueryString["变量"];
用超链接传送变量。
如在任一页中建超链接:<a href=Edit.
aspx?fbid=23>点击</a>
在Edit.
aspx页中取值:String str=Request.QueryString["fdid"]; chinaitpower.comNJMNpKx60pHmoHa

12、DOC对象.CreateElement("新建节点名");
创建XML文档新节点 chinaitpower.comNJMNpKx60pHmoHa

13、父节点.AppendChild(子节点);
将新建的子节点加到XML文档父节点下 chinaitpower.comNJMNpKx60pHmoHa

14、 父节点.RemoveChild(节点);
删除节点 chinaitpower.comNJMNpKx60pHmoHa

15、Response
Response.Write("字串");
Response.Write(变量);
向页面输出。 chinaitpower.comNJMNpKx60pHmoHa

Response.Redirect("URL地址");
跳转到URL指定的页面 chinaitpower.comNJMNpKx60pHmoHa

16、char.IsWhiteSpce(字串变量,位数)——逻辑型
查指定位置是否空
字符
如:
string str="中国 人民";
Response.Write(char.IsWhiteSpace(str,2)); //结果为:True, 第一个
字符是0位,2是第三个字符。 chinaitpower.comNJMNpKx60pHmoHa

17、char.IsPunctuation(”字符”) –逻辑型
字符是否是标点符号
如:Response.Write(char.IsPunctuation(”A”)); //返回:False chinaitpower.comNJMNpKx60pHmoHa

18、(int)”字符
字符转为数字,查代码点,注意是单引号。
如:
Response.Write((int)”中”); //结果为中字的代码:20013 chinaitpower.comNJMNpKx60pHmoHa

19、(char)代码
把数字转为
字符,查代码代表的字符
如:
Response.Write((char)22269); //返回“国”字。 chinaitpower.comNJMNpKx60pHmoHa

20、 Trim()
清除字串前后空格 chinaitpower.comNJMNpKx60pHmoHa

21 、字串变量.Replace("子字串","替换为")
字串替换
如:
string str="中国";
str=str.Replace("国","央"); //将国字换为央字
Response.Write(str); //输出结果为“中央” chinaitpower.comNJMNpKx60pHmoHa

再如:(这个非常实用) chinaitpower.comNJMNpKx60pHmoHa

string str="这是<script>脚本";
str=str.Replace("<","<font><</font>"); //将左尖括号替换为<font> 与 < 与 </font> (或换为<,但估计经XML存诸后,再提出仍会还原)
Response.Write(str); //显示为:“这是<script>脚本” chinaitpower.comNJMNpKx60pHmoHa

如果不替换,<script>将不显示,如果是一段脚本,将运行;而替换后,脚本将不运行。
这段代码的价值在于:你可以让一个文本中的所有HTML标签失效,全部显示出来,保护你的具有交互性的站点。
具体实现:将你的表单提交按钮脚本加上下面代码:
string strSubmit=label1.Text; //label1是你让用户提交数据的控件ID。
strSubmit=strSubmit.Replace("<","<font><</font>");
然后保存或输出strSubmit。
用此方法还可以简单实现UBB代码。 chinaitpower.comNJMNpKx60pHmoHa

22、Math.Max(i,j)
取i与j中的最大值
如 int x=Math.Max(5,10); // x将取值 10 chinaitpower.comNJMNpKx60pHmoHa

23、字串对比一般都用: if(str1==str2){ } , 但还有别的方法: chinaitpower.comNJMNpKx60pHmoHa

(1)、
string str1; str2
//语法: str1.EndsWith(str2); __检测字串str1是否以字串str2结尾,返回布尔值.如:
if(str1.EndsWith(str2)){ Response.Write("字串str1是以"+str2+"结束的"); } chinaitpower.comNJMNpKx60pHmoHa

(2)、
//语法:str1.Equals(str2); __检测字串str1是否与字串str2相等,返回布尔值,用法同上. chinaitpower.comNJMNpKx60pHmoHa

(3)、
//语法 Equals(str1,str2); __检测字串str1是否与字串str2相等,返回布尔值,用法同上. chinaitpower.comNJMNpKx60pHmoHa

24、IndexOf() 、LastIndexOf()
查找字串中指定
字符或字串首次(最后一次)出现的位置,返回索引值,如:
str1.IndexOf("字"); //查找“字”在str1中的索引值(位置)
str1.IndexOf("字串");//查找“字串”的第一个
字符在str1中的索引值(位置)
str1.IndexOf("字串",3,2);//从str1第4个
字符起,查找2个字符,查找“字串”的第一个字符在str1中的索引值(位置) chinaitpower.comNJMNpKx60pHmoHa

25、Insert()
在字串中指定索引位插入指定
字符。如:
str1.Insert(1,"字");在str1的第二个
字符处插入“字”,如果str1="中国",插入后为“中字国”; chinaitpower.comNJMNpKx60pHmoHa

26、PadLeft()、PadRight()
在字串左(或右)加空格或指定char
字符,使字串达到指定长度,如:
<%
string str1="中国人";
str1=str1.PadLeft(10,”1”); //无第二参数为加空格
Response.Write(str1); //结果为“1111111中国人” , 字串长为10
%> chinaitpower.comNJMNpKx60pHmoHa

27、Remove()
从指定位置开始删除指定数的
字符
字串对比一般都用: if(str1==str2){ } , 但还有别的方法: chinaitpower.comNJMNpKx60pHmoHa

1、
string str1; str2
//语法: str1.EndsWith(str2); __检测字串str1是否以字串str2结尾,返回布尔值.如:
if(str1.EndsWith(str2)){ Response.Write("字串str1是以"+str2+"结束的"); } chinaitpower.comNJMNpKx60pHmoHa

2、
//语法:str1.Equals(str2); __检测字串str1是否与字串str2相等,返回布尔值,用法同上. chinaitpower.comNJMNpKx60pHmoHa

3、
//语法 Equals(str1,str2); __检测字串str1是否与字串str2相等,返回布尔值,用法同上. chinaitpower.comNJMNpKx60pHmoHa

IndexOf()
查找字串中指定
字符或字串首次出现的位置,返首索引值,如:
str1.IndexOf("字"); //查找“字”在str1中的索引值(位置)
str1.IndexOf("字串");//查找“字串”的第一个
字符在str1中的索引值(位置)
str1.IndexOf("字串",3,2);//从str1第4个
字符起,查找2个字符,查找“字串”的第一个字符在str1中的索引值(位置)

1. 装箱、拆箱还是别名

  许多 C#.NET 的书上都有介绍 int -> Int32 是一个装箱的过程,反之则是拆箱的过程。许多其它变量类型也是如此,如:short <-> Int16,long <-> Int64 等。对于一般的程序员来说,大可不必去了解这一过程,因为这些装箱和拆箱的动作都是可以自动完成的,不需要写代码进行干预。但是我们需要记住这些类型之间的关系,所以,我们使用“别名”来记忆它们之间的关系。
C# 是全面向对象的语言,比 Java 的面向对象都还彻底——它把简单数据类型通过默认的装箱动作封装成了类。Int32、Int16、Int64 等就是相应的类名,而那些我们熟悉的、简单易记的名称,如 int、short、long 等,我们就可以把它称作是 Int32、Int16、Int64 等类型的别名。
  那么除了这三种类型之外,还有哪些类有“别名”呢?常用的有如下一些:

bool -> System.Boolean (布尔型,其值为 true 或者 false)
char -> System.Char (字符型,占有两个字节,表示 1 个 Unicode 字符)
byte -> System.Byte (字节型,占 1 字节,表示 8 位正整数,范围 0 ~ 255)
sbyte -> System.SByte (带符号字节型,占 1 字节,表示 8 位整数,范围 -128 ~ 127)
ushort -> System.UInt16 (无符号短整型,占 2 字节,表示 16 位正整数,范围 0 ~ 65,535)
uint -> System.UInt32 (无符号整型,占 4 字节,表示 32 位正整数,范围 0 ~ 4,294,967,295)
ulong -> System.UInt64 (无符号长整型,占 8 字节,表示 64 位正整数,范围 0 ~ 大约 10 的 20 次方)
short -> System.Int16 (短整型,占 2 字节,表示 16 位整数,范围 -32,768 ~ 32,767)
int -> System.Int32 (整型,占 4 字节,表示 32 位整数,范围 -2,147,483,648 到 2,147,483,647)
long -> System.Int64 (长整型,占 8 字节,表示 64 位整数,范围大约 -(10 的 19) 次方 到 10 的 19 次方)
float -> System.Single (单精度浮点型,占 4 个字节)
double -> System.Double (双精度浮点型,占 8 个字节)

  我们可以用下列代码做一个实验:

private void TestAlias() {
    // this.textBox1 是一个文本框,类型为 System.Windows.Forms.TextBox
    // 设计中已经将其 Multiline 属性设置为 true
    byte a = 1; char b = 'a'; short c = 1;
    int d = 2; long e = 3; uint f = 4; bool g = true;
    this.textBox1.Text = "";
    this.textBox1.AppendText("byte -> " + a.GetType().FullName + "\n");
    this.textBox1.AppendText("char -> " + b.GetType().FullName + "\n");
    this.textBox1.AppendText("short -> " + c.GetType().FullName + "\n");
    this.textBox1.AppendText("int -> " + d.GetType().FullName + "\n");
    this.textBox1.AppendText("long -> " + e.GetType().FullName + "\n");
    this.textBox1.AppendText("uint -> " + f.GetType().FullName + "\n");
    this.textBox1.AppendText("bool -> " + g.GetType().FullName + "\n");
}

  在窗体中新建一个按钮,并在它的单击事件中调用该 TestAlias() 函数,我们将看到运行结果如下:

byte -> System.Byte
char -> System.Char
short -> System.Int16
int -> System.Int32
long -> System.Int64
uint -> System.UInt32
bool -> System.Boolean

  这足以说明各别名对应的类!

2. 数值类型之间的相互转换

  这里所说的数值类型包括 byte, short, int, long, fload, double 等,根据这个排列顺序,各种类型的值依次可以向后自动进行转换。举个例来说,把一个 short 型的数据赋值给一个 int 型的变量,short 值会自动行转换成 int 型值,再赋给 int 型变量。如下例:

private void TestBasic() {
    byte a = 1; short b = a; int c = b;
    long d = c; float e = d; double f = e;
    this.textBox1.Text = "";
    this.textBox1.AppendText("byte a = " + a.ToString() + "\n");
    this.textBox1.AppendText("short b = " + b.ToString() + "\n");
    this.textBox1.AppendText("int c = " + c.ToString() + "\n");
    this.textBox1.AppendText("long d = " + d.ToString() + "\n");
    this.textBox1.AppendText("float e = " + e.ToString() + "\n");
    this.textBox1.AppendText("double f = " + f.ToString() + "\n");
}

  译顺利通过,运行结果是各变量的值均为 1;当然,它们的类型分别还是 System.Byte 型……System.Double 型。现在我们来试试,如果把赋值的顺序反过来会怎么样呢?在 TestBasic() 函数中追加如下语句:

int g = 1;
short h = g;
this.textBox1.AppendText("h = " + h.ToString() + "\n");

  结果编译报错:
  G:\Projects\Visual C#\Convert\Form1.cs(118): 无法将类型“int”隐式转换为“short”
  其中,Form1.cs 的 118 行即 short h = g 所在行。

  这个时候,如果我们坚持要进行转换,就应该使用强制类型转换,这在 C 语言中常有提及,就是使用“(类型名) 变量名”形式的语句来对数据进行强制转换。如上例修改如下:

short g = 1;
byte h = (byte) g; // 将 short 型的 g 的值强制转换成 short 型后再赋给变量 h
this.textBox1.AppendText("h = " + h.ToString() + "\n");

  编译通过,运行结果输出了 h = 1,转换成功。
  但是,如果我们使用强制转换,就不得不再考虑一个问题:short 型的范围是 -32768 ~ 23767,而 byte 型的范围是 0 ~ 255,那么,如果变量 g 的大小超过了 byte 型的范围又会出现什么样的情况呢?我们不妨再一次改写代码,将值改为 265,比 255 大 10

short g = 265; //265 = 255 + 10
byte h = (byte) g;
this.textBox1.AppendText("h = " + h.ToString() + "\n");

  编译没有出错,运行结果却不是 h = 265,而是 h = 9。
因此,我们在进行转换的时候,应当注意被转换的数据不能超出目标类型的范围。这不仅体现在多字节数据类型(相对,如上例的 short) 转换为少字节类型(相对,如上例的 byte) 时,也体现在字节数相同的有符号类型和无符号类型之间,如将 byte 的 129 转换为 sbyte 就会溢出。这方面的例子大同小异,就不详细说明了。

3. 字符的 ASCII 码和 Unicode 码

  很多时候我们需要得到一个英文字符的 ASCII 码,或者一个汉字字符的 Unicode 码,或者从相关的编码查询它是哪一个字符的编码。很多人,尤其是从 VB 程序序转过来学 C# 的人,会报怨 C# 里为什么没有提供现成的函数来做这个事情——因为在 VB 中有 Asc() 函数和 Chr() 函数用于这类转换。
但是如果你学过 C,你就会清楚,我们只需要将英文字符型数据强制转换成合适的数值型数据,就可以得到相应的 ASCII 码;反之,如果将一个合适的数值型数据强制转换成字符型数据,就可以得到相应的字符。
C# 中字符的范围扩大了,不仅包含了单字节字符,也可以包含双字节字符,如中文字符等。而在字符和编码之间的转换,则仍延用了 C 语言的做法——强制转换。不妨看看下面的例子

private void TestChar() {
    char ch = 'a'; short ii = 65;
    this.textBox1.Text = "";
    this.textBox1.AppendText("The ASCII code of \'" + ch + "\' is: " + (short) ch + "\n");
    this.textBox1.AppendText("ASCII is " + ii.ToString() + ", the char is: " + (char) ii + "\n");
    char cn = '中'; short uc = 22478;
    this.textBox1.AppendText("The Unicode of \'" + cn + "\' is: " + (short) cn + "\n");
    this.textBox1.AppendText("Unicode is " + uc.ToString() + ", the char is: " + (char) uc + "\n");
}

  它的运行结果是

The ASCII code of ‘a’ is: 97
ASCII is 65, the char is: A
The Unicode of ‘中’ is: 20013
Unicode is 22478, the char is: 城

  从这个例子中,我们便能非常清楚的了解——通过强制转换,可以得以字符的编码,或者得到编码表示的字符。如果你需要的不是 short 型的编码,请参考第 1 条进行转换,即可得到 int 等类型的编码值。

4. 数值字符串和数值之间的转换

  首先,我们得搞明白,什么是数值字符串。我们知道,在 C# 中,字符串是用一对双引号包含的若干字符来表示的,如 "123"。而 "123" 又相对特殊,因为组成该字符串的字符都是数字,这样的字符串,就是数值字符串。在我们的眼中,这即是一串字符,也是一个数,但计算机却只认为它是一个字符串,不是数。因此,我们在某些时候,比如输入数值的时候,把字符串转换成数值;而在另一些时候,我们需要相反的转换。
  将数值转换成字符串非常简单,因为每一个类都有一个 void ToString() 方法。所有数值型的 void ToString() 方法都能将数据转换为数值字符串。如 123.ToSting() 就将得到字符串 "123"。
那么反过来,将数值型字符串转换成数值又该怎么办呢?我们仔细查找一下,会发现 short, int, float 等数值类型均有一个 static Parse() 函数。这个函数就是用来将字符串转换为相应数值的。我们以一个 float 类型的转换为例: float f = float.Parse("543.21"); 其结果 f 的值为 543.21F。当然,其它的数值类型也可以使用同样的方法进行转换,下面的例子可以更明确的说明转换的方法:

private void TestStringValue() {
    float f = 54.321F;
    string str = "123";
    this.textBox1.Text = "";
    this.textBox1.AppendText("f = " + f.ToString() + "\n");
    if (int.Parse(str) == 123) {
        this.textBox1.AppendText("str convert to int successfully.");
    } else {
        this.textBox1.AppendText("str convert to int failed.");
    }
}

  运行结果:

f = 54.321
str convert to int successfully.

5. 字符串和字符数组之间的转换

  字符串类 System.String 提供了一个 void ToCharArray() 方法,该方法可以实现字符串到字符数组的转换。如下例:

private void TestStringChars() {
    string str = "mytest";
    char[] chars = str.ToCharArray();
    this.textBox1.Text = "";
    this.textBox1.AppendText("Length of \"mytest\" is " + str.Length + "\n");
    this.textBox1.AppendText("Length of char array is " + chars.Length + "\n");
    this.textBox1.AppendText("char[2] = " + chars[2] + "\n");
}

  例中以对转换转换到的字符数组长度和它的一个元素进行了测试,结果如下:

Length of "mytest" is 6
Length of char array is 6
char[2] = t

  可以看出,结果完全正确,这说明转换成功。那么反过来,要把字符数组转换成字符串又该如何呢?
  我们可以使用 System.String 类的构造函数来解决这个问题。System.String 类有两个构造函数是通过字符数组来构造的,即 String(char[]) 和 String[char[], int, int)。后者之所以多两个参数,是因为可以指定用字符数组中的哪一部分来构造字符串。而前者则是用字符数组的全部元素来构造字符串。我们以前者为例,在 TestStringChars() 函数中输入如下语句:

char[] tcs = {‘t’, ‘e’, ’s’, ‘t’, ‘ ‘, ‘m’, ‘e’};
string tstr = new String(tcs);
this.textBox1.AppendText("tstr = \"" + tstr + "\"\n");

  运行结果输入 tstr = "test me",测试说明转换成功。
  实际上,我们在很多时候需要把字符串转换成字符数组只是为了得到该字符串中的某个字符。如果只是为了这个目的,那大可不必兴师动众的去进行转换,我们只需要使用 System.String 的 [] 运算符就可以达到目的。请看下例,再在 TestStringChars() 函数中加入如如下语名:

char ch = tstr[3];
this.textBox1.AppendText("\"" + tstr + "\"[3] = " + ch.ToString());

  正确的输出是 "test me"[3] = t,经测试,输出正确。

6. 字符串和字节数组之间的转换

  如果还想从 System.String 类中找到方法进行字符串和字节数组之间的转换,恐怕你会失望了。为了进行这样的转换,我们不得不借助另一个类:System.Text.Encoding。该类提供了 bye[] GetBytes(string) 方法将字符串转换成字节数组,还提供了 string GetString(byte[]) 方法将字节数组转换成字符串。
  System.Text.Encoding 类似乎没有可用的构造函数,但我们可以找到几个默认的 Encoding,即 Encoding.Default(获取系统的当前 ANSI 代码页的编码)、Encoding.ASCII(获取 7 位 ASCII 字符集的编码)、Encoding.Unicode(获取采用 Little-Endian 字节顺序的 Unicode 格式的编码)、Encoding.UTF7(获取 UTF-7 格式的编码)、Encoding.UTF8(获取 UTF-8 格式的编码) 等。这里主要说说 Encoding.Default 和 Encoding.Unicode 用于转换的区别。
  在字符串转换到字节数组的过程中,Encoding.Default 会将每个单字节字符,如半角英文,转换成 1 个字节,而把每个双字节字符,如汉字,转换成 2 个字节。而 Encoding.Unicode 则会将它们都转换成两个字节。我们可以通过下列简单的了解一下转换的方法,以及使用 Encoding.Default 和 Encodeing.Unicode 的区别:

private void TestStringBytes() {
    string s = "C#语言";
    byte[] b1 = System.Text.Encoding.Default.GetBytes(s);
    byte[] b2 = System.Text.Encoding.Unicode.GetBytes(s);
    string t1 = "", t2 = "";
    foreach (byte b in b1) {
        t1 += b.ToString("") + " ";
    }
    foreach (byte b in b2) {
        t2 += b.ToString("") + " ";
    }
    this.textBox1.Text = "";
    this.textBox1.AppendText("b1.Length = " + b1.Length + "\n");
    this.textBox1.AppendText(t1 + "\n");
    this.textBox1.AppendText("b2.Length = " + b2.Length + "\n");
    this.textBox1.AppendText(t2 + "\n");
}

  运行结果如下,不说详述,相信大家已经明白了。

b1.Length = 6
67 35 211 239 209 212
b2.Length = 8
67 0 35 0 237 139 0 138

  将字节数组转换成字符串,使用 Encoding 类的 string GetString(byte[]) 或 string GetString(byte[], int, int) 方法,具体使用何种 Encoding 还是由编码决定。在 TestStringBytes() 函数中添加如下语句作为实例:

byte[] bs = {97, 98, 99, 100, 101, 102};
string ss = System.Text.Encoding.ASCII.GetString(bs);
this.textBox1.AppendText("The string is: " + ss + "\n");

  运行结果为:The string is: abcdef

7. 各种数值类型和字节数组之间的转换

  在第 1 条中我们可以查到各种数值型需要使用多少字节的空间来保存数据。将某种数值类型的数据转换成字节数组的时候,得到的一定是相应大小的字节数组;同样,需要把字节数组转换成数值类型,也需要这个字节数组大于相应数值类型的字节数。
  现在介绍此类转换的主角:System.BitConverter。该类提供了 byte[] GetBytes(…) 方法将各种数值类型转换成字节数组,也提供了 ToInt32、ToInt16、ToInt64、ToUInt32、ToSignle、ToBoolean 等方法将字节数组转换成相应的数值类型。

  由于这类转换通常只是在需要进行较细微的编码/解码操作时才会用到,所以这里就不详细叙述了,仅把 System.BitConverter 类介绍给大家。

8. 转换成十六进制

  任何数据在计算机内部都是以二进制保存的,所以进制与数据的存储无关,只与输入输出有关。所以,对于进制转换,我们只关心字符串中的结果。
  在上面的第 4 条中提到了 ToString() 方法可以将数值转换成字符串,不过在字符串中,结果是以十进制显示的。现在我们带给它加一些参数,就可以将其转换成十六进制——使用 ToString(string) 方法。
  这里需要一个 string 类型的参数,这就是格式说明符。十六进制的格式说明符是 "x" 或者 "X",使用这两种格式说明符的区别主要在于 A-F 六个数字:"x" 代表 a-f 使用小写字母表示,而 "X" 而表示 A-F 使用大字字母表示。如下例:

private void TestHex() {
    int a = 188;
    this.textBox1.Text = "";
    this.textBox1.AppendText("a(10) = " + a.ToString() + "\n");
    this.textBox1.AppendText("a(16) = " + a.ToString("x") + "\n");
    this.textBox1.AppendText("a(16) = " + a.ToString("X") + "\n");
}

  运行结果如下:

a(10) = 188
a(16) = bc
a(16) = BC

  这时候,我们可能有另一种需求,即为了显示结果的整齐,我们需要控制十六进制表示的长度,如果长度不够,用前导的 0 填补。解决这个问题,我们只需要在格式说明符“x”或者“X”后写上表示长度的数字就行了。比如,要限制在 4 个字符的长度,可以写成“X4”。在上例中追加一句:

this.textBox1.AppendText("a(16) = " + a.ToString("X4") + "\n");

  其结果将输出 a(16) = 00BC。
  现在,我们还要说一说如何将一个表示十六进制数的字符串转换成整型。这一转换,同样需要借助于 Parse() 方法。这里,我需要 Parse(string, System.Globalization.NumberStyles) 方法。第一个参数是表示十六进制数的字符串,如“AB”、“20”(表示十进制的 32) 等。第二个参数 System.Globalization.NumberStyles 是一个枚举类型,用来表示十六进制的枚举值是 HexNumber。因此,如果我们要将“AB”转换成整型,就应该这样写:int b = int.Parse("AB", System.Globalization.NumberStyles.HexNumber),最后得到的 b 的值是 171。

9. 日期型数据和长整型数据之间的转换

  为什么要将日期型数据转换为长整型数据呢?原因很多,但就我个人来说,经常将它用于数据库的日期存储。由于各种数据库对日期型的定义和处理是不一样的,各种语言对日期型数据的定义的处理也各不相同,因为,我宁愿将日期型数据转换成长整型再保存到数据库中。虽然也可以使用字符串来保存,但使用字符串也会涉及到许多问题,如区域等问题,而且,它需要比保存长整型数据更多的空间。
  日期型数据,在 C# 中的参与运算的时候,应该也是转换为长整型数据来运算的。它的长整型值是自 0001 年 1 月 1 日午夜 12:00 以来所经过时间以 100 毫微秒为间隔表示时的数字。这个数在 C# 的 DateTime 中被称为 Ticks(刻度)。DateTime 类型有一个名为 Ticks 的长整型只读属性,就保存着这个值。如此,要从一个 DataTime 型数据得到 long 型值就非常简单了,只需要读出 DataTime 对象的 Ticks 值即可,如:

long longDate = DateTime.Now.Ticks;

  DateTime 的构造函数中也提供了相应的,从长整型数据构造 DateTime 型数据的函数:DateTime(long)。如:

DateTime theDate = new DateTime(longDate);

  但这样对于很多 VB6 程序员来说,是给他们出了一道难题,因为 VB6 中的日期型数据内部是以 Double 型表示的,将其转换为长整型后得到的仅仅是日期,而没有时间。如何协调这两种日期类型呢?
System.DateTime 提供了 double ToOADate() 和 static DateTime FromOADate(double) 两个函数来解决这个问题。前者将当前对象按原来的 double 值输出,后者则从一个 double 值获得一个 System.DateTime 对象。举例如下:

private void TestDateTimeLong() {
    double doubleDate = DateTime.Now.ToOADate();
    DateTime theDate = DateTime.FromOADate(doubleDate);
    this.textBox1.Text = "";
    this.textBox1.AppendText("Double value of now: " + doubleDate.ToString() + "\n");
    this.textBox1.AppendText("DateTime from double value: " + theDate.ToString() + "\n");
}

  运行结果:

Double value of now: 37494.661541713
DateTime from double value: 2002-8-26 15:52:37

10. 格式化日期型数据

  编程的过程中,通常需要将日期型数据按照一定的格式输出,当然,输出结果肯定是字符串。为此,我们需要使用 System.DateTime 类的 ToString() 方法,并为其指定格式字符串。
  MSDN 中,System.Globalization.DateTimeFormatInfo 类的概述里对模式字符串有非常详细的说明,因此,这里我只对常用的一些格式进行说明,首先请看下表:

 

d

月中的某一天

一位数的日期没有前导零

dd

月中的某一天

一位数的日期有一个前导零

ddd

周中某天的缩写名称

AbbreviatedDayNames 中定义

dddd

周中某天的完整名称

DayNames 中定义

M

月份数字

一位数的月份没有前导零

MM

月份数字

一位数的月份有一个前导零

MMM

月份的缩写名称

AbbreviatedMonthNames 中定义

MMMM

月份的完整名称

MonthNames 中定义

y

不包含纪元的年份

如果不包含纪元的年份小于 10,则显示不具有前导零的年份

yy

不包含纪元的年份

如果不包含纪元的年份小于 10,则显示具有前导零的年份

yyyy

包括纪元的四位数的年份

h

12 小时制的小时

一位数的小时数没有前导零

hh

12 小时制的小时

一位数的小时数有前导零

H

24 小时制的小时

一位数的小时数没有前导零

HH

24 小时制的小时

一位数的小时数有前导零

m

分钟

一位数的分钟数没有前导零

mm

分钟

一位数的分钟数有一个前导零

s

一位数的秒数没有前导零

ss

一位数的秒数有一个前导零

  为了便于大家的理解,不妨试试下面的程序:

private void TestDateTimeToString() {
    DateTime now = DateTime.Now;
    string format;
    this.textBox1.Text = "";
    format = "yyyy-MM-dd HH:mm:ss";
    this.textBox1.AppendText(format + ": " + now.ToString(format) + "\n");
    format = "yy年M日d日";
    this.textBox1.AppendText(format + ": " + now.ToString(format) + "\n");
}

  这段程序将输出结果:

yyyy-MM-dd HH:mm:ss: 2002-08-26 17:03:04
yy年M日d日: 02年8日26日

  这时候,又出现一个问题,如果要输出的文本信息中包含格式字符怎么办?如

format = "year: yyyy, month: MM, day: dd";
this.textBox1.AppendText(now.ToString(format) + "\n");

  将输出:

2ear: 2002, 4on下5: 08, 26a2: 26

  这并不是我想要的结果,怎么办呢?有办法——

format = "\"year\": yyyy, \’month\’: MM, \’day\’: dd";
this.textBox1.AppendText(now.ToString(format) + "\n");

  看,这次运行结果对了:

year: 2002, month: 08, day: 26

  可以看出,只需要使用单引号或者双引号将文本信息括起来就好。

"^\d+$"  //非负整数(正整数 + 0)

"^[0-9]*[1-9][0-9]*$"  //正整数

"^((-\d+)|(0+))$"  //非正整数(负整数 + 0)

"^-[0-9]*[1-9][0-9]*$"  //负整数

"^-?\d+$"    //整数

"^\d+(\.\d+)?$"  //非负浮点数(正浮点数 + 0)

"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$"  //正浮点数

"^((-\d+(\.\d+)?)|(0+(\.0+)?))$"  //非正浮点数(负浮点数 + 0)

"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"  //负浮点数

"^(-?\d+)(\.\d+)?$"  //浮点数

"^[A-Za-z]+$"  //由26个英文字母组成的字符串

"^[A-Z]+$"  //由26个英文字母的大写组成的字符串

"^[a-z]+$"  //由26个英文字母的小写组成的字符串

"^[A-Za-z0-9]+$"  //由数字和26个英文字母组成的字符串

"^\w+$"  //由数字、26个英文字母或者下划线组成的字符串

"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"    //email地址

"^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$"  //url

2005年12月07日

一、什么是SQL注入式攻击?

  所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入域或页面请求的查询字符串,欺骗服务器执行恶意的SQL命令。在某些表单中,用户输入的内容直接用来构造(或者影响)动态SQL命令,或作为存储过程的输入参数,这类表单特别容易受到SQL注入式攻击。常见的SQL注入式攻击过程类如:

  ⑴ 某个ASP.NET Web应用有一个登录页面,这个登录页面控制着用户是否有权访问应用,它要求用户输入一个名称和密码。

  ⑵ 登录页面中输入的内容将直接用来构造动态的SQL命令,或者直接用作存储过程的参数。下面是ASP.NET应用构造查询的一个例子:

System.Text.StringBuilder query = new System.Text.StringBuilder(
  "SELECT * from Users WHERE login = ‘")
  .Append(txtLogin.Text).Append("’ AND password=’")
  .Append(txtPassword.Text).Append("’");


  ⑶ 攻击者在用户名字和密码输入框中输入"’或’1′=’1"之类的内容。

  ⑷ 用户输入的内容提交给服务器之后,服务器运行上面的ASP.NET代码构造出查询用户的SQL命令,但由于攻击者输入的内容非常特殊,所以最后得到的SQL命令变成:SELECT * from Users WHERE login = ” or ‘1′=’1′ AND password = ” or ‘1′=’1′。

  ⑸ 服务器执行查询或存储过程,将用户输入的身份信息和服务器中保存的身份信息进行对比。

  ⑹ 由于SQL命令实际上已被注入式攻击修改,已经不能真正验证用户身份,所以系统会错误地授权给攻击者。

  如果攻击者知道应用会将表单中输入的内容直接用于验证身份的查询,他就会尝试输入某些特殊的SQL字符串篡改查询改变其原来的功能,欺骗系统授予访问权限。

  系统环境不同,攻击者可能造成的损害也不同,这主要由应用访问数据库的安全权限决定。如果用户的帐户具有管理员或其他比较高级的权限,攻击者就可能对数据库的表执行各种他想要做的操作,包括添加、删除或更新数据,甚至可能直接删除表。

二、如何防范?

  好在要防止ASP.NET应用被SQL注入式攻击闯入并不是一件特别困难的事情,只要在利用表单输入的内容构造SQL命令之前,把所有输入内容过滤一番就可以了。过滤输入内容可以按多种方式进行。

  ⑴ 对于动态构造SQL查询的场合,可以使用下面的技术:

  第一:替换单引号,即把所有单独出现的单引号改成两个单引号,防止攻击者修改SQL命令的含义。再来看前面的例子,"SELECT * from Users WHERE login = ”’ or ”1”=”1′ AND password = ”’ or ”1”=”1′"显然会得到与"SELECT * from Users WHERE login = ” or ‘1′=’1′ AND password = ” or ‘1′=’1′"不同的结果。

  第二:删除用户输入内容中的所有连字符,防止攻击者构造出类如"SELECT * from Users WHERE login = ‘mas’ — AND password =”"之类的查询,因为这类查询的后半部分已经被注释掉,不再有效,攻击者只要知道一个合法的用户登录名称,根本不需要知道用户的密码就可以顺利获得访问权限。

  第三:对于用来执行查询的数据库帐户,限制其权限。用不同的用户帐户执行查询、插入、更新、删除操作。由于隔离了不同帐户可执行的操作,因而也就防止了原本用于执行SELECT命令的地方却被用于执行INSERT、UPDATE或DELETE命令。

  ⑵ 用存储过程来执行所有的查询。SQL参数的传递方式将防止攻击者利用单引号和连字符实施攻击。此外,它还使得数据库权限可以限制到只允许特定的存储过程执行,所有的用户输入必须遵从被调用的存储过程的安全上下文,这样就很难再发生注入式攻击了。

  ⑶ 限制表单或查询字符串输入的长度。如果用户的登录名字最多只有10个字符,那么不要认可表单中输入的10个以上的字符,这将大大增加攻击者在SQL命令中插入有害代码的难度。

  ⑷ 检查用户输入的合法性,确信输入的内容只包含合法的数据。数据检查应当在客户端和服务器端都执行——之所以要执行服务器端验证,是为了弥补客户端验证机制脆弱的安全性。

  在客户端,攻击者完全有可能获得网页的源代码,修改验证合法性的脚本(或者直接删除脚本),然后将非法内容通过修改后的表单提交给服务器。因此,要保证验证操作确实已经执行,唯一的办法就是在服务器端也执行验证。你可以使用许多内建的验证对象,例如RegularExpressionValidator,它们能够自动生成验证用的客户端脚本,当然你也可以插入服务器端的方法调用。如果找不到现成的验证对象,你可以通过CustomValidator自己创建一个。

  ⑸ 将用户登录名称、密码等数据加密保存。加密用户输入的数据,然后再将它与数据库中保存的数据比较,这相当于对用户输入的数据进行了"消毒"处理,用户输入的数据不再对数据库有任何特殊的意义,从而也就防止了攻击者注入SQL命令。System.Web.Security.FormsAuthentication类有一个HashPasswordForStoringInConfigFile,非常适合于对输入数据进行消毒处理。

  ⑹ 检查提取数据的查询所返回的记录数量。如果程序只要求返回一个记录,但实际返回的记录却超过一行,那就当作出错处理。

一、程序功能:为Repeater实现分页

  二、窗体设计:

  1、新建ASP.NET Web应用程序,命名为Repeater2,保存路径为http://192.168.0.1/Repeater2(注:我机子上的网站的IP是192.168.0.1的主目录是D:\web文件夹)然后点击确定。

  2、向窗体添加一个3行一列的表,向表的第一行中添加一个Repeater控件,向表的第二行中添加两个Label控件向表的第三行中添加四个Button按钮。

  3、切换到HTML代码窗口,在<asp:Repeater id="Repeater1" runat="server">和</asp:Repeater>之间添加以下代码:

<ItemTemplate>
<table id="Table2" style="FONT-SIZE: x-small" width="498">
 <tr>
  <td><%#DataBinder.Eval(Container,"DataItem.employeeid")%></td>
  <td><%#DataBinder.Eval(Container,"DataItem.lastname")%></td>
 </tr>
</table>
</ItemTemplate>

  三、代码设计:

Imports System.Data.SqlClient
Public Class WebForm1
Inherits System.Web.UI.Page

 Dim scon As New SqlConnection("server=localhost;database=northwind;uid=sa;pwd=123")
 Dim sDA As SqlDataAdapter
 Dim ds As DataSet
 Dim currentPage As Integer ‘记录着目前在哪一页上
 Dim maxPage As Integer ‘总共有多少页
 Const rowCount As Integer = 3 ‘一页有多少行
 Dim rowSum As Integer ‘总共有多少行

 ’窗体代码省略

 Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

 If Not Page.IsPostBack Then
  sDA = New SqlDataAdapter("select employeeid, lastname from employees order by employeeid", scon)
  ds = New DataSet
  Try
   sDA.Fill(ds, "employees")
   ’获取总共有多少行
   rowSum = ds.Tables(0).Rows.Count
  Catch ex As Exception
   rowSum = 0
  End Try

  ’如果没有数据,退出过程
  If rowSum = 0 Then Exit Sub
  ’计算出浏览数据的总页数
  If rowSum Mod rowCount > 0 Then
   ’有余数要加1
   maxPage = rowSum \ rowCount + 1
  Else
   ’正好除尽
   maxPage = rowSum \ rowCount
  End If

  currentPage = 1
  ’调用绑定数据过程
  readpage(currentPage)
  BindData()
  Label2.Text = maxPage
  ’首页和上一页按钮不可见
  Button1.Visible = False
  Button2.Visible = False
 End If
End Sub

‘创建一个绑定数据的过程
Sub BindData()
 Repeater1.DataSource = ds
 Repeater1.DataBind()
 Label1.Text = currentPage
End Sub

‘创建一个填充数据集的过程
Sub readpage(ByVal n As Integer)
 sDA = New SqlDataAdapter("select employeeid, lastname from employees order by employeeid", scon)
 ds = New DataSet
 ds.Clear()
 sDA.Fill(ds, (n – 1) * rowCount, rowCount, "employees")
End Sub

‘首页按钮
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

 currentPage = 1
 ’调用填充数据集过程
 readpage(currentPage)
 ’绑定数据
 BindData()
 ’设置首页、第一页按钮不可见,显示下一页尾页按钮
 Button1.Visible = False
 Button2.Visible = False
 Button3.Visible = True
 Button4.Visible = True

End Sub

‘上一页按钮
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
‘如果现在页是第二页,设置首页和上一页按钮不可见
 If Label1.Text > 2 Then
  Button3.Visible = True
  Button4.Visible = True
 Else
  Button1.Visible = False
  Button2.Visible = False
  Button3.Visible = True
  Button4.Visible = True
 End If
 currentPage = Label1.Text – 1
 readpage(currentPage)
 BindData()
End Sub

‘下一页按钮
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
‘如果现在页倒数第二页,设置最后页和下一页按钮不可见
 If Label1.Text < Label2.Text – 1 Then
  Button1.Visible = True
  Button2.Visible = True
 Else
  Button1.Visible = True
  Button2.Visible = True
  Button3.Visible = False
  Button4.Visible = False
 End If
  currentPage = Label1.Text + 1
  readpage(currentPage)
  BindData()
 End Sub

 ’尾页按钮
 Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
  ’设置当前页为最大页数
  currentPage = Label2.Text
  readpage(currentPage)
  BindData()
  Button1.Visible = True
  Button2.Visible = True
  Button3.Visible = False
  Button4.Visible = False
 End Sub
End Class

  窗体界面如下所示: