CS Code:
protected void ToExcel()
{
string sStr="";
/*省略組織sStr的代碼*/
...
Response.Clear();
Response.AppendHeader("Content-Disposition", "attachment;filename=TEST" + DateTime.Now.Date.ToString("yyyyMMdd") + ".xls");
Response.ContentType = "application/vnd.ms-excel";
Response.ContentEncoding = Encoding.Default;
Response.Write(sStr);
Response.Flush();
Response.Close();
}
22.我正在學習中的Delegate(轉載)
CS Code:
Delegate
delegate是C#中的一种类型,它实际上是一个能够持有对某个方法的引用的类。与其它的类不同,delegate类能够拥有一个签名(signature),并且它只能持有与它的签名相匹配的方法的引用。它所实现的功能与C/C++中的函数指针十分相似。它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m。但与函数指针相比,delegate有许多函数指针不具备的优点。首先,函数指针只能指向静态函数,而delegate既可以引用静态函数,又可以引用非静态成员函数。在引用非静态成员函数时,delegate不但保存了对此函数入口指针的引用,而且还保存了调用此函数的类实例的引用。其次,与函数指针相比,delegate是面向对象、类型安全、可靠的受控(managed)对象。也就是说,runtime能够保证delegate指向一个有效的方法,你无须担心delegate会指向无效地址或者越界地址。
实现一个delegate是很简单的,通过以下3个步骤即可实现一个delegate:
1.声明一个delegate对象,它应当与你想要传递的方法具有相同的参数和返回值类型。
2. 创建delegate对象,并将你想要传递的函数作为参数传入。
3. 在要实现异步调用的地方,通过上一步创建的对象来调用方法。
using System;
public class MyDelegateTest
{
// 步骤1,声明delegate对象
public delegate void MyDelegate(string name);
// 这是我们欲传递的方法,它与MyDelegate具有相同的参数和返回值类型
public static void MyDelegateFunc(string name)
{
Console.WriteLine("Hello, ", name);
}
public static void Main()
{
// 步骤2,创建delegate对象
MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc);
// 步骤3,调用delegate
md("sam1111");
}
}
输出结果是:Hello, sam1111
了解了delegate,下面我们来看看,在C#中对事件是如何处理的。
C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子:
public delegate void MyEventHandler(object sender, MyEventArgs e);
其中的两个参数,sender代表事件发送者,e是事件参数类。MyEventArgs类用来包含与事件相关的数据,所有的事件参数类都必须从System.EventArgs类派生。当然,如果你的事件不含参数,那么可以直接用System.EventArgs类作为参数。
就是这么简单,结合delegate的实现,我们可以将自定义事件的实现归结为以下几步:
1.定义delegate对象类型,它有两个参数,第一个参数是事件发送者对象,第二个参数是事件参数类对象。
2.定义事件参数类,此类应当从System.EventArgs类派生。如果事件不带参数,这一步可以省略。
3.定义事件处理方法,它应当与delegate对象具有相同的参数和返回值类型。
4. 用event关键字定义事件对象,它同时也是一个delegate对象。
5.用+=操作符添加事件到事件队列中(-=操作符能够将事件从队列中删除)。
6.在需要触发事件的地方用调用delegate的方式写事件触发方法。一般来说,此方法应为protected访问限制,既不能以public方式调用,但可以被子类继承。名字是OnEventName。
7. 在适当的地方调用事件触发方法触发事件。
下面是一个简单的例子:
using System;
public class EventTest
{
// 步骤1,定义delegate对象
public delegate void MyEventHandler(object sender, System.EventArgs e);
// 步骤2省略
public class MyEventCls
{
// 步骤3,定义事件处理方法,它与delegate对象具有相同的参数和返回值类// 型
public void MyEventFunc(object sender, System.EventArgs e)
{
Console.WriteLine("My event is ok!");
}
}
// 步骤4,用event关键字定义事件对象
private event MyEventHandler myevent;
private MyEventCls myecls;
public EventTest()
{
myecls = new MyEventCls();
: // 步骤5,用+=操作符将事件添加到队列中
this.myevent += new MyEventHandler(myecls.MyEventFunc);
}
// 步骤6,以调用delegate的方式写事件触发函数
protected void OnMyEvent(System.EventArgs e)
{
if(myevent != null)
myevent(this, e);
}
public void RaiseEvent()
{
EventArgs e = new EventArgs();
: // 步骤7,触发事件
OnMyEvent(e);
}
public static void Main()
{
EventTest et = new EventTest();
Console.Write("Please input ''a'':");
string s = Console.ReadLine();
if(s == "a")
{
et.RaiseEvent();
}
else
{
Console.WriteLine("Error");
}
}
}
输出结果如下,红色为用户的输入:
Please input ‘a’: a
My event is ok!
23.存储过程学习(转载)
存储过程 包含三部分: 声明,执行部分,异常。
可以有无参数程序和带参数存储过程。
无参程序语法
2 as ;
3 begin
4 ;
5 exception
6 ;
7 end;
8
带参存储过程实例
2 sName emp.ename%type;
3 sjob emp.job%type;
4 begin
5 ....
7 exception
....
14 end;
15
带参数存储过程含赋值方式
sname out varchar,sjob in out varchar)
2 as icount number;
3 begin
4 select count(*) into icount from emp where sal>isal and job=sjob;
5 if icount=1 then
6 ....
9 else
10 ....
12 end if;
13 exception
14 when too_many_rows then
15 DBMS_OUTPUT.PUT_LINE('返回值多于1行');
16 when others then
17 DBMS_OUTPUT.PUT_LINE('在RUNBYPARMETERS过程中出错!');
18 end;
19
过程调用
方式一
2 realsal emp.sal%type;
3 realname varchar(40);
4 realjob varchar(40);
5 begin
6 realsal:=1100;
7 realname:='';
8 realjob:='CLERK';
9 runbyparmeters(realsal,realname,realjob); --必须按顺序
10 DBMS_OUTPUT.PUT_LINE(REALNAME||' '||REALJOB);
11 END;
12
方式二
2 realsal emp.sal%type;
3 realname varchar(40);
4 realjob varchar(40);
5 begin
6 realsal:=1100;
7 realname:='';
8 realjob:='CLERK';
9 runbyparmeters(sname=>realname,isal=>realsal,sjob=>realjob); --指定值对应变量顺序可变
10 DBMS_OUTPUT.PUT_LINE(REALNAME||' '||REALJOB);
11 END;
12
24.泛型的FindAll()方法
我在工作中遇到要像DataSet一样过滤数据集中的数据,但是数据返回类型是泛型,因此要用List.FindAll()方法.
CS Code:
//List<Model> listModel已经有值,listModelNew为过滤后所要的数据集
List<Model> listModelNew=listModel.FindAll(delegate(Model m)
{
return m.UserId==9527;
});
25.如何將DataSet中的數據導出為Excel?
CS Code:
Response.Clear();
Response.Charset = "big5";//繁體
Response.ContentType = "application/vnd.ms-excel";
System.IO.StringWriter oSW = new System.IO.StringWriter();
HtmlTextWriter oHW = new HtmlTextWriter(oSW);
DataGrid oDG = new DataGrid();
oDG.DataSource = oDS.Tables[0];
oDG.DataBind();
oDG.RenderControl(oHW);
Response.Write(oSW.ToString());
Response.Flush();
Response.Close();
26.如何画柏拉图?
CS Code:
public void Render(string title, string subTitle, int width, int height,
string XDesc, string YLeftDesc, string YRightDesc,
DataTable DT, Stream target)
{
int CHART_TOP = 80; //圖距頂段
int CHART_HEIGHT = height - 180; //圖高
int CHART_LEFT = 70; //圖距左邊
int CHART_WIDTH = width - 140; //圖寬
//計算最高點
int highPoint = 0;
foreach (DataRow dr in DT.Rows)
{
highPoint += int.Parse(dr[0].ToString());
}
//建立一個Graphics對象實例
Bitmap bm = new Bitmap(width, height);
Graphics g = Graphics.FromImage(bm);
//設置條型圖形和文字屬性
g.SmoothingMode = SmoothingMode.Default;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
//設定畫布和邊框
g.Clear(Color.LightSkyBlue);
g.FillRectangle(Brushes.LightYellow, CHART_LEFT - 1, CHART_TOP, CHART_WIDTH + 2, CHART_HEIGHT + 2);
//添主圖背景為淡黃色
//畫座標*********************************************
float sCale = float.Parse(highPoint.ToString()) / 4;
float tempPoint = 0;
for (int i = CHART_TOP + CHART_HEIGHT; i >= CHART_TOP; i -= CHART_HEIGHT / 4)
{
g.DrawLine(Pens.Black, new Point(CHART_LEFT, i), new Point(CHART_LEFT + CHART_WIDTH, i));
g.DrawString(tempPoint.ToString(), new Font("Arial", 9, FontStyle.Regular), Brushes.Black, new Point(CHART_LEFT - 25, i - 6));
tempPoint += sCale;
}//畫橫線和左邊刻度
g.DrawLine(Pens.Black, new Point(CHART_LEFT, CHART_TOP), new Point(CHART_LEFT, CHART_TOP + CHART_HEIGHT));
//左座標
g.DrawString(YLeftDesc, new Font("Arial", 9, FontStyle.Regular), Brushes.Black, new Point(CHART_LEFT - 65, CHART_TOP + CHART_HEIGHT / 2));
//左座標描述
g.DrawLine(Pens.Black, new Point(CHART_LEFT + CHART_WIDTH, CHART_TOP), new Point(CHART_LEFT + CHART_WIDTH, CHART_TOP + CHART_HEIGHT));
//右座標
g.DrawString(YRightDesc, new Font("Arial", 9, FontStyle.Regular), Brushes.Black, new Point(CHART_LEFT + CHART_WIDTH + 35, CHART_TOP + CHART_HEIGHT / 2));
//右座標描述
g.DrawString(XDesc, new Font("Arial", 9, FontStyle.Regular), Brushes.Black, new Point(CHART_LEFT + CHART_WIDTH / 2 - 40, CHART_TOP + CHART_HEIGHT + 30));
//底座標描述
int sCaleR = CHART_HEIGHT / 10;
tempPoint = CHART_TOP;
for (int i = 10; i >= 0; i--)
{
g.DrawLine(Pens.Black, new Point(CHART_LEFT + CHART_WIDTH, int.Parse(tempPoint.ToString())), new PointF(float.Parse((CHART_LEFT + CHART_WIDTH + 5).ToString()), tempPoint));
g.DrawString((i * 10).ToString(), new Font("Arial", 9, FontStyle.Regular), Brushes.Black, new PointF(float.Parse((CHART_LEFT + CHART_WIDTH + 12).ToString()), tempPoint - 5));
tempPoint += sCaleR;
}//右座標刻度
//畫大標題
g.DrawString(title, new Font("Arial", 14), Brushes.Black, new PointF(width / 2 - 150, 15));
//畫小標題
g.DrawString(subTitle, new Font("Arial", 12), Brushes.Black, new PointF(width / 2 - 40, 45));
//畫條型圖
float barWidth = CHART_WIDTH / (DT.Rows.Count * 2);
PointF barOrigin = new PointF(CHART_LEFT + (barWidth / 2), 0);
float barHeight = 0;
PointF[] linePoints = new PointF[DT.Rows.Count]; //描點個數陣列
float Percents = 0;
for (int i = 0; i < DT.Rows.Count; i++)
{
barHeight = Convert.ToSingle(DT.Rows[i][0]) * CHART_HEIGHT / highPoint;
barOrigin.Y = CHART_TOP + CHART_HEIGHT - barHeight;
g.FillRectangle(new SolidBrush(ChartUtil.GetChartItemColor(i)), barOrigin.X, barOrigin.Y, barWidth, barHeight);
//畫矩形
g.DrawString(Convert.ToString(DT.Rows[i][1]), new Font("Arial", 8, FontStyle.Regular), Brushes.Black, new PointF(barOrigin.X, CHART_TOP + CHART_HEIGHT + 5), new StringFormat(StringFormatFlags.DirectionVertical));
//畫條形描述
Percents += Convert.ToSingle(DT.Rows[i][0]) / highPoint;
g.DrawString(Percents.ToString("0.00%"), new Font("Arial", 8, FontStyle.Regular), Brushes.Black, new PointF(barOrigin.X - 5, CHART_TOP + (1 - Percents) * CHART_HEIGHT - 15));
//畫白份比
linePoints[i] = new PointF(barOrigin.X + barWidth / 2, CHART_TOP + (1 - Percents) * CHART_HEIGHT);
//畫連線點
barOrigin.X = barOrigin.X + (barWidth * 2);
}
g.DrawLines(Pens.Red, linePoints);//連線
//輸出圖像
bm.Save(target, ImageFormat.Gif);
//回收資源
bm.Dispose();
g.Dispose();
}
27.HAVING的使用
把 HAVING 加入 SQL 的原因是,WHERE 无法应用于合计函数,而如果没有 HAVING,就无法测试结果条件。
example:
表 "Sales":
Company | Amount |
---|---|
W3Schools | 5500 |
IBM | 4500 |
W3Schools | 7100 |
SELECT Company,SUM(Amount) FROM Sales
GROUP BY Company
HAVING SUM(Amount)>10000
结果:
Company | SUM(Amount) |
---|---|
W3Schools | 12600 |
28.C#操作文件(转载)
C# 操作文件
在.NET Framework中进行的所有的输入和输出工作都要使用到流。流是串行化设备的抽象串行化设备可以以线性方式存储数据,并可以以同样的方式访问:一次访问—个字节。此设备可以是磁盘文件、打印机、内存位置和或任何其他支持以线性方式读写的对象。
当向某些外部目标写数据时,就要用到输出流,这可以是物理磁盘文件、网络位置、打印机或其他程序。
常用的类:
File------实用类,提供许多静态方法,用于移动、删除、和复制文件。
Directory------实用类,提供许多静态方法,用于移动、删除和复制目录。
Path------ 实用类,用于处理路径名称。
FileInfo------表示磁盘上的物理文件,具有可以处理此文件的方法,要完成对文件的读写工作,就必须创建Stream对像。
DirectoryInfo------表示磁盘上的物理目录,具有可以处理此目录的方法
FileStream-------表示可以被写或被读,或二者都可的文件,此文件可以同步或异步读和写
StreamReader------从流中读取字符数据,并可通过使用FileStream被创建为基类。
StreamWriter------向流写字符数据,可通过使用FileStream被创建为基类。
FileSystemWatcher---- FileSystemWatcher是用于监控文件和目录,并在这些位置发生变化时,给出应用程序可以捕获的事件。
◆File和Directory类
作为实用类,File和Directory类都提供了许多方法,用于处理文件系统以及其中的文件和目录。这些是静态方法,涉及移动文件、查询和更新属性并创建FileStream对象。
File类一些最常用的静态方法:
Copy()------将文件复制到规定的位置
Create()------在规定的位置上创建文件
Delete()------删除文件
Open()-------在规定的路径上返回FileStream对像
Move()------将规定的文件移动到新位置,可以在新位置给文件规定不同的名字
Directory类的一些常用的静态方法
CreateDirectory()------创建具有规定路径的目录
Delete()------删除规定的目录以及其中的所有文件
GetDirectories()------返回表示当前目录之下的目录的Directory对像的数组
GetFiles()-------返回在当前目录中的File对像的数组
Move()------将规定的目录移动到新位置。可以在新位置为文件夹规定一个新名称
FileInfo 类
FileInfo类不像File类,它没有静态方法,仅可用于实例化的对像。FileInfo对像表示在磁盘或网络位置的文件,注意它不是流,为了读写文件,必须创建Stream对像。
fileInfo类提供了下面的关于基础性的文件的属性,这些属性可能用来更新文件。
Attributes-----获取或设置当前文件的属性
CreationTime------获取当前文件的创建日期和时间
DirectoryName------获取文件目录的路径
Exists------判断是否存在文件
FullName------检索文件的完整路径
Length------获取文件的容量
Name------仅仅返回文件的名称,而不是完整的文件位置路径、
当在.NET代码中规定路径名时,您可以使用绝对路径名,也可以使用相对路行名。绝对路径名显式地规定文件或目录来自于哪—个己知的位置——比如是c:驱动器。它的—个范例是C:\work\LogFile.txt。注意它淮确地定义了其位置。
相对路径名相对于应用程序在文件系统上运行的位置。通过使用相对路径名称,无需规定已知的驱动器或位置;当前的目录就是起点。例如,如果应用程序运行在c:\DeVelopment\FileDemo目录上(这里的应用程序是指代码生成后的exe文件),并使用了相对路径“LogFile.txt,”,则该文件就位于C:\DeVelopment\FileDemo\LogFile.txt中。为了上移目录,则使用.. 字符。这样,在同一个应用程中路径“../test.txt”是指向应用程序所在的目录的上一级目录里的文件test.txt。
◆FileStream对象
FileStream对象表示在磁盘或网络路径上指向文件的流。当类提供向文件读写字节的方法时,经常使用StreamReader或StreamWriter执行这些功能。这是因为FileStream类操作字节和字节数组,而Stream类操作字符数据。字符数据易于使用,但是有些操作比如随机文件访问,就必须由FileStream对象执行。
FileStream对象的构造函数:
FileStream aFile = new FileStream(“Log.txt”,FileMode.OpenOrCreate);
FileMode枚举具有几种成员:
Append------如果文件存在,就打开文件,将文件位置移动到文件的末尾,并创建一个新文件。FileMode.Append仅可以与枚举FileAccess.Write联合使用
Create------创建新文件;如果存在这样的文件,就破坏它。
CreateNew------创建新文件,但是如果已经存在此文件,则抛出异常
Open------打开现有的文件,但是不存在所指定的文件,则抛出异常
OpenOrCreate------如果文件存在,则规定打开文件,否则就创建新文件,如果文件已经存在,则保留在文件中的数据
Truncate------打开现有文件,清除其内容,然后我们可以向文件写入全新的数据,但是保留文件的初始创建日期,必须存在有文件,否则就抛出异常
访问级别
前面的构造函数默认以只读模式打开文件,需要一个附加参数规定不同的访问级别,此参数是FileAccess参数。
FileStream aFile=new FileStream(”Log.txt”,fileMode.OpenOrCreate,FileAccess.Write)
FileAccess枚举有三种类型:Read、Write、ReadWrite.此属性的作用是:基于用户的身份验证级别改变用户对文件的访问
读取文件的位置用seek:public long Seek(long offset,SeekOrigin origin)
Long offset是规定文件指针以字节为单位的移动距离;SeekOrigin origin是规定开始计算的起始位置,此枚举包含3个值:Begin,Current和End。
例:aFile.Seek(8,SeekOrigin.Begin);// SeekOrigin.Begin指得是文件指针从文件的第一个字节起;而参数‘8‘指得是移动到文件的第8个字节
例2:afile.Seek(2,SeekOrigin.Current)//在当前位置开始,再移动2个字节。
例3:aFile.Seek(-5,SeekOrigin.End)//在文件末端位置开始,倒数5个字节。
读取数据
使用FileStream类读取数据不像使用StreamReader和StreamWriter类读取数据那么容易,这是因为FileStream类只能处理原始字节(raw byey),这使得FileStream类可以用于任何数据文件,而不仅仅是文本文件,通过读取字节数据就可以读取类似图像和声音的文件。这种灵活性的代价是不能使用它直接读入字符串,而使用StreamWriter和StreaMeader类却可以这样处理,从是有几种转换类可以很容易地将字节数组转换为字符数组,或者进行相反的操作。
Read()方法是从FileStream对象所指向的文件访问数据的主要手段:
Public int Read(byte[] array,int offset, int count)//第一个参数是被传输进来的字节数组,用以接受FileStream对象中的数据。第二个参数是字节数组中开始写入数据的位置,它通常是0,表示从数组的开端的文件中向数组写数据,最后一个参数是规定从文件中读出多少字节。
写入数据
写入数据的流程是先获取字节数组,再把字节数据转换为字符数组,然后把这个字符数组用Write()方法写入到文件中,当然在写入的过程中,可以确定在文件的什么位置写入,写多少字符等等。
文件读写的范例:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace myFile
{
class Program
{
static void Main(string[] args)
{
byte[] byData = new byte[100];//建立一个FileStream要用的字节组
char[] charData = new char[100];//建立一个字符组
try
{
FileStream aFile = new FileStream("http://www.cnblogs.com/http://www.cnblogs.com/Data.txt", FileMode.Open);//实例化一个FileStream对象,用来操作data.txt文件,操作类型是
aFile.Seek(55, SeekOrigin.Begin);//把文件指针指向,从文件开始位置向前55位字节所指的字节
aFile.Read(byData, 0, 100);//读取FileStream对象所指的文件到字节数组里
}
catch (IOException e)
{
Console.WriteLine("close");
return;
}
Decoder d = Encoding.UTF8.GetDecoder();//
d.GetChars(byData, 0, byData.Length, charData, 0);//将编码字节数组转换为字符数组
Console.WriteLine(charData);
Console.ReadLine();
return;
}
}
}
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace myFile
{
class Program
{
static void Main(string[] args)
{
byte[] byData = new byte[100];//建立一个FileStream要用的字节组
char[] charData = new char[100];//建立一个字符组
try
{
FileStream aFile = new FileStream("http://www.cnblogs.com/http://www.cnblogs.com/Data.txt", FileMode.Open);//实例化一个FileStream对象,用来操作data.txt文件,操作类型是
charData = "我是谁?111?".ToCharArray();//将字符串内的字符复制到字符组里
aFile.Seek(0, SeekOrigin.End);
Encoder el = Encoding.UTF8.GetEncoder();//编码器
el.GetBytes(charData, 0, charData.Length, byData, 0, true);
aFile.Write(byData, 0, byData.Length);
}
catch (IOException e)
{
Console.WriteLine("close");
return;
}
}
}
}
◆StreamWriter对像
用FileWriter来随机读取文件是个好主意,而用StreamWriter可以直接把字符串写入文件中,它处理重要的转换和向FileStream对像写入工作。创建StreamWriter有很多方法:
FileStream aFile = new FileStream(“Log.txt”,FileMode.CreatcNew);
StreamWriter sw = new StreamWriter(aFile);
也可直接从文件中创建StreamWriter对象:
StreamWriter sw = new StreamWriter(“Log.txt”,true);
后面这个Boolean值规定是附加文件还是创建新文件,如果此值为false,则就创建一个新文件,或者截取现有文件并打开它。如果此值设置为true,则打开文件,保留原来的数据,如果找不到文件,则创建一个新文件。注意:当创建FileStream对象时,您无法得到选项的范围。除了使用Boolean值附加或创建新文件外,我们根本就无法像使用FileStream类时那样规定FileMode属性;而且,您也无法设置FileAccess属性.因此您总是具有对文件的读写特权,为了使用任何高级参数,您必须在FileStream构造函数中规定这些参数,然后在FileStream对象中创建StreamWriter。
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace StreamWriterFile
{
class Program
{
static void Main(string[] args)
{
try
{
FileStream aFile = new FileStream("data1.txt", FileMode.OpenOrCreate);//建立一个fileStream对象
StreamWriter sw = new StreamWriter(aFile);//用FileStream对像实例一个StreamWriter对象
sw.Write("first.");
sw.WriteLine("hello world!!!");//写入字符串,方法WriteLine写入时后面跟一个换行符
sw.Write("This is a");//写入字符串,方法Write写入时没有换行符
sw.Write("string of characters.");
sw.Close();//用完后必须关闭对像
}
catch (IOException e)
{
Console.WriteLine(e.ToString());
}
}
}
}
◆StreamReader对象
1.读取文件
输入流用于从外部源读取数据,在很多情况下,数据源可以是磁盘上的文件或网络的某些位置,任何可能发送数据的位置都可以是数据源,比如网络应用程序,web服务,甚至是控制台。StreamReader是一个通用类,可以用于任何流;StreamReader对象的创建方式非常类似于StreamWriter对象的创建方式。
StreamWriter类有两个基本的方法read和readLine
Read()方法将流的下一个字符作为正整数值返回,如果到达了流的结尾处,则返回-1
ReadLing()方法是读取并返回一行字符,如果返回为空,那么就是到达了流的结尾。
ReadEnd()方法读小文件最好,它直接读取完整的文件并作为字符串返回。
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace StreamReaderTest
{
class Program
{
static void Main(string[] args)
{
string strLine;
try
{
Console.Write("请输入文件路径及文件名:");
string mess = Console.ReadLine();
FileStream aFile = new FileStream(mess, FileMode.Open);
StreamReader sr = new StreamReader(aFile);//用FileStream对象实例化一个StreamReader对象
//strLine = sr.ReadToEnd();//读取完整的文件,如果用这个方法,就可以不用下面的while循环
strLine = sr.ReadLine();// 读取一行字符并返回
while (strLine != null)
{
Console.WriteLine(strLine);
strLine = sr.ReadLine();
}
sr.Close();
Console.ReadLine();
}
catch (IOException e)
{
Console.WriteLine("an IOexception has been thrown!");
Console.WriteLine(e.ToString());
return;
}
return;
}
}
}
2.分隔文件
读取使用逗号分隔的文件,string类提供了一种称为Split()的方法,可以用于将字符串按照提供的分隔符分隔成字符组.
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace CommaValues
{
class Program
{
static void Main(string[] args)
{
while (true)
{
string strLine;
string[] strArray;
char[] charArray = new Char[] { ',' };
Console.Write("请输入文件内容以逗号分隔的文件路径及文件名:");
string name = Console.ReadLine();
try
{
FileStream aFile = new FileStream(name, FileMode.Open);
StreamReader sr = new StreamReader(aFile);
strLine = sr.ReadLine();
while (strLine != null)
{
strArray = strLine.Split(charArray);
for (int x = 0; x <= strArray.GetUpperBound(0); x++)
{
Console.WriteLine(strArray[x].Trim());
}
strLine = sr.ReadLine();
}
sr.Close();
//Console.ReadLine();
}
catch (IOException e)
{
Console.WriteLine(e.ToString());
return;
}
//return;
}
}
}
}
29.在应用程序启动目录下创建XML文件
protected void createXML(string xmlFileName)
{
try
{
XmlTextWriter writer = new XmlTextWriter(".\\" + xmlFileName + ".xml", System.Text.Encoding.GetEncoding("utf-8"));
//使用自动缩进便于阅读
writer.Formatting = Formatting.Indented;
writer.WriteRaw("<?xml version=" + "\"1.0" + "\" encoding=" + "\"utf-8" + "\" ?>");
//书写根元素
writer.WriteStartElement("OnlineMonXML");
writer.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
writer.WriteAttributeString("version", "0.09.0005");
//添加次级元素
writer.WriteStartElement("OnlineMonData");
//添加次级元素
writer.WriteStartElement("Stations");
//添加次级元素
writer.WriteStartElement("Station");
writer.WriteAttributeString("strStatuinType", "污染源自动监测");
writer.WriteAttributeString("strAreaID", "440100");
writer.WriteAttributeString("nStationID", "1");
//添加次级元素
writer.WriteStartElement("Points");
//添加次级元素
writer.WriteStartElement("Point");
writer.WriteAttributeString("strAreaID", "440100");
writer.WriteAttributeString("nStationID", "1");
writer.WriteAttributeString("nPointID", "1");
//添加次级元素
writer.WriteStartElement("MonDatas");
//添加次级元素
writer.WriteStartElement("MonData");
writer.WriteAttributeString("dMontime", "2004-03-02T00:50.0000000+08:00");
writer.WriteAttributeString("dDura", "POYOMODTOH5MOS");
//添加次级元素
writer.WriteStartElement("ItemDatas");
//添加子元素
writer.WriteStartElement("ItemData");
writer.WriteAttributeString("strItem", "COD");
writer.WriteAttributeString("fValue", "2.5");
writer.WriteAttributeString("strUnit", "mg/m3");
writer.WriteAttributeString("bChecked", "true");
//关闭次级元素DatabaseSetting
writer.WriteEndElement();
writer.WriteStartElement("ItemData");
writer.WriteAttributeString("strItem", "水流量");
writer.WriteAttributeString("fValue", "30");
writer.WriteAttributeString("strUnit", "m3/s");
writer.WriteAttributeString("bChecked", "true");
//关闭次级元素DatabaseSetting
writer.WriteEndElement();
//关闭根元素
writer.WriteFullEndElement();
//将XML写入文件并关闭writer
writer.Close();
}
catch (Exception ex)
{
Response.Write("<script language='javascript'>alert('"+ ex.Message +"')</script>");
}
}
30.ASP.NET中防止用户多次登录的方法
在web开发时,有的系统要求同一个用户在同一时间只能登录一次,也就是如果一个用户已经登录了,在退出之前如果再次登录的话需要报错。
常见的处理方法是,在用户登录时,判断此用户是否已经在Application中存在,如果存在就报错,不存在的话就加到Application中(Application是所有Session共有的,整个web应用程序唯一的一个对象):
string strUserId = txtUser.Text;
ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList;
if (list == null)
{
list = new ArrayList();
}
for (int i = 0; i < list.Count; i++)
{
if (strUserId == (list[i] as string))
{
//已经登录了,提示错误信息
lblError.Text = "此用户已经登录";
return;
}
}
list.Add(strUserId);
Application.Add("GLOBAL_USER_LIST", list);
当然这里使用Cache等保存也可以。
接下来就是要在用户退出的时候将此用户从Application中去除,我们可以在Global.asax的Session_End事件中处理:
void Session_End(object sender, EventArgs e)
{
// 在会话结束时运行的代码。
// 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
// InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer
// 或 SQLServer,则不会引发该事件。
string strUserId = Session["SESSION_USER"] as string;
ArrayList list = Application.Get("GLOBAL_USER_LIST") as ArrayList;
if (strUserId != null && list != null)
{
list.Remove(strUserId);
Application.Add("GLOBAL_USER_LIST", list);
}
}
这些都没有问题,有问题的就是当用户直接点浏览器右上角的关闭按钮时就有问题了。因为直接关闭的话,并不会立即触发Session过期事件,也就是关闭浏览器后再来登录就登不进去了。
这里有两种处理方式:
1、使用Javascript方式
在每一个页面中加入一段javascript代码:
function window.onbeforeunload()
{
if (event.clientX>document.body.clientWidth && event.clientY<0||event.altKey){
window.open("logout.aspx");
}
}
由于onbeforeunload方法在浏览器关闭、刷新、页面调转等情况下都会被执行,所以需要判断是点击了关闭按钮或是按下Alt+F4时才执行真正的关闭操作。
然后在logout.aspx的Page_Load中写和Session_End相同的方法,同时在logout.aspx中加入事件:onload="javascript:window.close()"
但是这样还是有问题,javascript在不同的浏览器中可能有不同的行为,还有就是当通过文件->关闭时没有判断到。
2、使用xmlhttp方法(这种方法测试下来没有问题)
在每个页面中加入如下的javascript(这些javascript也可以写在共通里,每个页面引入就可以了)
var x=0;
function myRefresh()
{
var httpRequest = new ActiveXObject("microsoft.xmlhttp");
httpRequest.open("GET", "test.aspx", false);
httpRequest.send(null);
x++;
if(x<60) //60次,也就是Session真正的过期时间是30分钟
{
setTimeout("myRefresh()",30*1000); //30秒
}
}
myRefresh();
在web.config中设置
<sessionState mode="InProc" timeout="1"></sessionState>
test.aspx页面就是一个空页面,只不过需要在Page_Load中加入:
Response.Expires = -1;
保证不使用缓存,每次都能调用到这个页面。
原理就是:设置Session的过期时间是一分钟,然后在每个页面上定时每30秒连接一次测试页面,保持Session有效,总共连60次,也就是30分钟。如果30分钟后用户还没有操作,Session就会过期。当然,如果用户直接关闭浏览器,那么一分钟后Session也会过期。这样就可以满足要求了。