Luben Park

Java Ben 成长之路

2005年12月12日 #

表名作为参数传递的存储过程写法

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

 

--=================================================================
-- 描述:~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- 作者:鲁湘
-- @tableName   该模板对应的数据库表
-- @RecordID    业务处理需要寻找表中记录的ID号码
--=================================================================

ALTER    PROCEDURE WF_QingJia
   (@tableName varchar(50),@recordID varchar(50))
AS
-- 获取表中的业务数据值
DECLARE @money varchar(100),  -- 业务逻辑需要的值
 @sqls nvarchar(4000)  -- 保存组合SQL语句

SET @sqls='SELECT @a=Money FROM '+@tableName +' WHERE ID ='+@recordID

EXECUTE sp_executesql @sqls,N'@a varchar(50) output',@money output

-- 根据值进行相应的业务处理
print @money
UPDATE WF_FormBill SET [Money]='真的被处理了' WHERE [ID]=@recordID

 

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

posted @ 2006-11-16 16:49 Ben 阅读(933) | 评论 (0)编辑 收藏

[转]经典SQL语句--收藏 http://blog.ourtw.com/article.php?tid_600.html

经典SQL语句--收藏
[个人收藏]经典SQL语句.值得收藏
精典的SQL语句,推荐收藏
在网上经常转,常常看到有些人为了求得某些SQL语句而焦头烂额,现在我特别把自己收藏的一些比较精典的SQL拿出来和大家分享一下

1. 行列转换--普通

假设有张学生成绩表(CJ)如下
Name   Subject   Result
张三   语文     80
张三   数学     90
张三   物理     85
李四   语文     85
李四   数学     92
李四   物理     82

想变成  
姓名   语文   数学   物理
张三   80   90   85
李四   85   92   82

declare @sql varchar(4000)
set @sql = ''select Name''
select @sql = @sql + '',sum(case Subject when ''''''+Subject+'''''' then Result end) [''+Subject+'']''
from (select distinct Subject from CJ) as a
select @sql = @sql+'' from test group by name''
exec(@sql)

2. 行列转换--合并

有表A,
id pid
1   1
1   2
1   3
2   1
2   2
3   1
如何化成表B:
id pid
1 1,2,3
2 1,2
3 1

创建一个合并的函数
create function fmerg(@id int)
returns varchar(8000)
as
begin
declare @str varchar(8000)
set @str=''''
select @str=@str+'',''+cast(pid as varchar) from 表A where id=@id set @str=right(@str,len(@str)-1)
return(@str)
End
go

--调用自定义函数得到结果
select distinct id,dbo.fmerg(id) from 表A

3. 如何取得一个数据表的所有列名

方法如下:先从SYSTEMOBJECT系统表中取得数据表的SYSTEMID,然后再SYSCOLUMN表中取得该数据表的所有列名。
SQL语句如下:
declare @objid int,@objname char(40)
set @objname = ''tablename''
select @objid = id from sysobjects where id = object_id(@objname)
select ''Column_name'' = name from syscolumns where id = @objid order by colid

是不是太简单了? 呵呵 不过经常用阿.

4. 通过SQL语句来更改用户的密码

修改别人的,需要sysadmin role  
EXEC sp_password NULL, ''newpassword'', ''User''

如果帐号为SA执行EXEC sp_password NULL, ''newpassword'', sa

5. 怎么判断出一个表的哪些字段不允许为空?

select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where IS_NULLABLE=''NO'' and TABLE_NAME=tablename

6. 如何在数据库里找到含有相同字段的表?
a. 查已知列名的情况
SELECT b.name as TableName,a.name as columnname
From syscolumns   a INNER JOIN   sysobjects b  
ON a.id=b.id  
AND b.type=''U''  
AND a.name=''你的字段名字''

b. 未知列名查所有在不同表出现过的列名
Select o.name As tablename,s1.name As columnname
From syscolumns s1, sysobjects o
Where s1.id = o.id
  And o.type = ''U''
  And Exists (
    Select 1 From syscolumns s2  
    Where s1.name = s2.name  
    And s1.id <> s2.id
    )

7. 查询第xxx行数据

假设id是主键:
select *
from (select top xxx * from yourtable) aa
where not exists(select 1 from (select top xxx-1 * from yourtable) bb where aa.id=bb.id)

如果使用游标也是可以的
fetch absolute [number] from [cursor_name]
行数为绝对行数

8. SQL Server日期计算
a. 一个月的第一天
SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)
b. 本周的星期一
SELECT DATEADD(wk, DATEDIFF(wk,0,getdate()), 0)
c. 一年的第一天
SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)
d. 季度的第一天
SELECT DATEADD(qq, DATEDIFF(qq,0,getdate()), 0)
e. 上个月的最后一天
SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()), 0))
f. 去年的最后一天
SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))
g. 本月的最后一天
SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0))
h. 本月的第一个星期一
select DATEADD(wk, DATEDIFF(wk,0,                                      
                    dateadd(dd,6-datepart(day,getdate()),getdate())    
                                                                ), 0)    
i. 本年的最后一天
SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))。
-----------------------------------------------------------------------
1.按姓氏笔画排序:
Select * From TableName Order By CustomerName Collate Chinese_PRC_Stroke_ci_as

2.数据库加密:
select encrypt(''原始密码'')
select pwdencrypt(''原始密码'')
select pwdcompare(''原始密码'',''加密后密码'') = 1--相同;否则不相同 encrypt(''原始密码'')
select pwdencrypt(''原始密码'')
select pwdcompare(''原始密码'',''加密后密码'') = 1--相同;否则不相同

3.取回表中字段:
declare @list varchar(1000),@sql nvarchar(1000)
select @list=@list+'',''+b.name from sysobjects a,syscolumns b where a.id=b.id and a.name=''表A''
set @sql=''select ''+right(@list,len(@list)-1)+'' from 表A''
exec (@sql)

4.查看硬盘分区:
EXEC master..xp_fixeddrives

5.比较A,B表是否相等:
if (select checksum_agg(binary_checksum(*)) from A)
  =
  (select checksum_agg(binary_checksum(*)) from B)
print ''相等''
else
print ''不相等''

6.杀掉所有的事件探察器进程:
DECLARE hcforeach CURSOR GLOBAL FOR SELECT ''kill ''+RTRIM(spid) FROM master.dbo.sysprocesses
WHERE program_name IN(''SQL profiler'',N''SQL 事件探查器'')
EXEC sp_msforeach_worker ''?''

7.记录搜索:
开头到N条记录
Select Top N * From 表
-------------------------------
N到M条记录(要有主索引ID)
Select Top M-N * From 表 Where ID in (Select Top M ID From 表) Order by ID Desc
----------------------------------
N到结尾记录
Select Top N * From 表 Order by ID Desc

8.如何修改数据库的名称:
sp_renamedb ''old_name'', ''new_name''

9:获取当前数据库中的所有用户表
select Name from sysobjects where xtype=''u'' and status>=0

10:获取某一个表的所有字段
select name from syscolumns where id=object_id(''表名'')

11:查看与某一个表相关的视图、存储过程、函数
select a.* from sysobjects a, syscomments b where a.id = b.id and b.text like ''%表名%''

12:查看当前数据库中所有存储过程
select name as 存储过程名称 from sysobjects where xtype=''P''

13:查询用户创建的所有数据库
select * from master..sysdatabases D where sid not in(select sid from master..syslogins where name=''sa'')
或者
select dbid, name AS DB_NAME from master..sysdatabases where sid <> 0x01

14:查询某一个表的字段和数据类型
select column_name,data_type from information_schema.columns
where table_name = ''表名''

[n].[标题]:
Select * From TableName Order By CustomerName

[n].[标题]:
Select * From TableName Order By CustomerName

posted @ 2006-04-06 15:01 Ben 阅读(850) | 评论 (0)编辑 收藏

vs2003 和vs2005下的发送SMTP邮件 (downmoon原创) 选择自 downmoon 的 Blog

vs2003 和vs2005下的发送SMTP邮件 (downmoon原创)
一、vs2003
引用 System.Web.Mail命名空间

 private void SenMail2003()
    {
        MailMessage mailObj = new MailMessage();
        mailObj.To = this.txtTo.Text;
        mailObj.From = this.txtFrom.Text;
       
        mailObj.Subject = "精采笑话";
        mailObj.Body = "猪!你已中毒! 哈哈 ";
       
        mailObj.BodyFormat = MailFormat.Html;
        mailObj.BodyEncoding = MailFormat.Base64;
        mailObj.Priority = MailPriority.High;
        mailObj.Attachments.Add(new MailAttachment("c:\\swf\\000.bmp"));
        SmtpMail.Send(mailObj);
        Response.Write("发送邮件成功!");
    }

二、vs2005
引用 System.Net.Mail命名空间,安全性得到了增强

 public static void SendWebMailAndAttach(string server)
    {
         string file = "e:\\inetpub\\wwwroot\\Test2005All\\TestXML\\testXML.xml";
         System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage("Test@126.com", "Test@126.com", "text message for you.", "Test Title");
         System.Net.Mail.Attachment data = new System.Net.Mail.Attachment(file, System.Net.Mime.MediaTypeNames.Application.Octet);
         System.Net.Mime.ContentDisposition disposition = data.ContentDisposition;
         disposition.CreationDate = System.IO.File.GetCreationTime(file);
         disposition.ModificationDate = System.IO.File.GetLastWriteTime(file);
         disposition.ReadDate = System.IO.File.GetLastAccessTime(file);
         message.Attachments.Add(data);
        System.Net.Mail.SmtpClient client = new System.Net.Mail.SmtpClient(server);
        client.Credentials = new NetworkCredential("用户名", "密码");
        client.Send(message);
        data.Dispose();
    }
引用示例
SendWebMailAndAttach("smtp.126.com");

posted @ 2006-04-06 14:18 Ben 阅读(444) | 评论 (0)编辑 收藏

SQL中CONVERT转化函数, Concat , COALESCE的用法

SQL中CONVERT转化函数的用法

CONVERT的使用方法:

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

格式:
CONVERT(data_type,expression[,style])

说明:
此样式一般在时间类型(datetime,smalldatetime)与字符串类型(nchar,nvarchar,char,varchar)
相互转换的时候才用到.

例子:
SELECT CONVERT(varchar(30),getdate(),101) now
结果为
now
---------------------------------------
09/15/2001

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

style数字在转换时间时的含义如下

-------------------------------------------------------------------------------------------------
Style(2位表示年份) | Style(4位表示年份) | 输入输出格式
-------------------------------------------------------------------------------------------------
- | 0 or 100 | mon dd yyyy hh:miAM(或PM)
-------------------------------------------------------------------------------------------------
1 | 101 | mm/dd/yy
-------------------------------------------------------------------------------------------------
2 | 102 | yy-mm-dd
-------------------------------------------------------------------------------------------------
3 | 103 | dd/mm/yy
-------------------------------------------------------------------------------------------------
4 | 104 | dd-mm-yy
-------------------------------------------------------------------------------------------------
5 | 105 | dd-mm-yy
-------------------------------------------------------------------------------------------------
6 | 106 | dd mon yy
-------------------------------------------------------------------------------------------------
7 | 107 | mon dd,yy
-------------------------------------------------------------------------------------------------
8 | 108 | hh:mm:ss
-------------------------------------------------------------------------------------------------
- | 9 or 109 | mon dd yyyy hh:mi:ss:mmmmAM(或PM)
-------------------------------------------------------------------------------------------------
10 | 110 | mm-dd-yy
-------------------------------------------------------------------------------------------------
11 | 111 | yy/mm/dd
-------------------------------------------------------------------------------------------------
12 | 112 | yymmdd
-------------------------------------------------------------------------------------------------
- | 13 or 113 | dd mon yyyy hh:mi:ss:mmm(24小时制)
-------------------------------------------------------------------------------------------------
14 | 114 | hh:mi:ss:mmm(24小时制)
-------------------------------------------------------------------------------------------------
- | 20 or 120 | yyyy-mm-dd hh:mi:ss(24小时制)
-------------------------------------------------------------------------------------------------
- | 21 or 121 | yyyy-mm-dd hh:mi:ss:mmm(24小时制)
-------------------------------------------------------------------------------------------------

concat
方法的结果等于:result = string1 + string2 + string3 + … + stringN

COALESCE 返回其参数中第一个非空表达式

posted @ 2006-04-06 14:15 Ben 阅读(1942) | 评论 (0)编辑 收藏

[转].NET(C#)连接各类数据库-集锦

1.C#连接连接Access
程序代码:
-------------------------------------------------------------------------------

using System.Data;
using System.Data.OleDb;

......

string strConnection="Provider=Microsoft.Jet.OleDb.4.0;";
strConnection+=@"Data Source=C:\BegASPNET\Northwind.mdb";

OleDbConnection objConnection=new OleDbConnection(strConnection);

......

objConnection.Open();
objConnection.Close();

......

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

解释:

 连接Access数据库需要导入额外的命名空间,所以有了最前面的两条using命令,这是必不可少的!

 strConnection这个变量里存放的是连接数据库所需要的连接字符串,他指定了要使用的数据提供者和要使用的数据源.

 "Provider=Microsoft.Jet.OleDb.4.0;"是指数据提供者,这里使用的是Microsoft Jet引擎,也就是Access中的数据引擎,asp.net就是靠这个和Access的数据库连接的.

 "Data Source=C:\BegASPNET\Northwind.mdb"是指明数据源的位置,他的标准形式是"Data Source=MyDrive:MyPath\MyFile.MDB".

PS:
 1."+="后面的"@"符号是防止将后面字符串中的"\"解析为转义字符.
 2.如果要连接的数据库文件和当前文件在同一个目录下,还可以使用如下的方法连接:
  strConnection+="Data Source=";
  strConnection+=MapPath("Northwind.mdb");
  这样就可以省得你写一大堆东西了!
 3.要注意连接字符串中的参数之间要用分号来分隔.

 "OleDbConnection objConnection=new OleDbConnection(strConnection);"这一句是利用定义好的连接字符串来建立了一个链接对象,以后对数据库的操作我们都要和这个对象打交道.

 "objConnection.Open();"这用来打开连接.至此,与Access数据库的连接完成.
--------------------------------------------------------------------------------

2.C#连接SQL Server
程序代码:
--------------------------------------------------------------------------------

using System.Data;
using System.Data.SqlClient;

...

string strConnection="user id=sa;password=;";
strConnection+="initial catalog=Northwind;Server=YourSQLServer;";
strConnection+="Connect Timeout=30";

SqlConnection objConnection=new SqlConnection(strConnection);

...

objConnection.Open();
objConnection.Close();

...

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

解释:

连接SQL Server数据库的机制与连接Access的机制没有什么太大的区别,只是改变了Connection对象和连接字符串中的不同参数.

首先,连接SQL Server使用的命名空间不是"System.Data.OleDb",而是"System.Data.SqlClient".

其次就是他的连接字符串了,我们一个一个参数来介绍(注意:参数间用分号分隔):
 "user id=sa":连接数据库的验证用户名为sa.他还有一个别名"uid",所以这句我们还可以写成"uid=sa".
 "password=":连接数据库的验证密码为空.他的别名为"pwd",所以我们可以写为"pwd=".
 这里注意,你的SQL Server必须已经设置了需要用户名和密码来登录,否则不能用这样的方式来登录.如果你的SQL Server设置为Windows登录,那么在这里就不需要使用"user id"和"password"这样的方式来登录,而需要使用"Trusted_Connection=SSPI"来进行登录.
 "initial catalog=Northwind":使用的数据源为"Northwind"这个数据库.他的别名为"Database",本句可以写成"Database=Northwind".
 "Server=YourSQLServer":使用名为"YourSQLServer"的服务器.他的别名为"Data Source","Address","Addr".如果使用的是本地数据库且定义了实例名,则可以写为"Server=(local)\实例名";如果是远程服务器,则将"(local)"替换为远程服务器的名称或IP地址.
 "Connect Timeout=30":连接超时时间为30秒.

 在这里,建立连接对象用的构造函数为:SqlConnection.
--------------------------------------------------------------------------------

3.C#连接Oracle
程序代码:
--------------------------------------------------------------------------------

using System.Data.OracleClient;
using System.Data;

//在窗体上添加一个按钮,叫Button1,双击Button1,输入以下代码
private void Button1_Click(object sender, System.EventArgs e)
{
string ConnectionString="Data Source=sky;user=system;password=manager;";//写连接串
OracleConnection conn=new OracleConnection(ConnectionString);//创建一个新连接
try
{
conn.Open();
OracleCommand cmd=conn.CreateCommand();

cmd.CommandText="select * from MyTable";//在这儿写sql语句
OracleDataReader odr=cmd.ExecuteReader();//创建一个OracleDateReader对象
while(odr.Read())//读取数据,如果odr.Read()返回为false的话,就说明到记录集的尾部了               
{
Response.Write(odr.GetOracleString(1).ToString());//输出字段1,这个数是字段索引,具体怎么使用字段名还有待研究
}
odr.Close();
}
catch(Exception ee)
{
Response.Write(ee.Message); //如果有错误,输出错误信息
}
finally
{
conn.Close(); //关闭连接
}
}

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

4.C#连接MySQL
程序代码:
--------------------------------------------------------------------------------

using MySQLDriverCS;

// 建立数据库连接
MySQLConnection DBConn;
DBConn = new MySQLConnection(new MySQLConnectionString("localhost","mysql","root","",3306).AsString);
DBConn.Open();

// 执行查询语句
MySQLCommand DBComm;
DBComm = new MySQLCommand("select Host,User from user",DBConn);

// 读取数据
MySQLDataReader DBReader = DBComm.ExecuteReaderEx();

// 显示数据
try
{
while (DBReader.Read())
{
Console.WriteLine("Host = {0} and User = {1}", DBReader.GetString(0),DBReader.GetString(1));
}
}
finally
{
DBReader.Close();
DBConn.Close();
}

//关闭数据库连接
DBConn.Close();

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

5.C#连接IBM DB2
程序代码:
--------------------------------------------------------------------------------

OleDbConnection1.Open();
//打开数据库连接
OleDbDataAdapter1.Fill(dataSet1,"Address");
//将得来的数据填入dataSet
DataGrid1.DataBind();
//绑定数据
OleDbConnection1.Close();
//关闭连接

//增加数据库数据
在Web Form上新增对应字段数量个数的TextBox,及一个button,为该按键增加Click响应事件代码如下:

this.OleDbInsertCommand1.CommandText = "INSERTsintosADDRESS(NAME,
EMAIL, AGE, ADDRESS) VALUES
('"+TextBox1.Text+"','"+TextBox2.Text+"','"+TextBox3.Text+"','"+TextBox4.Text+"')";
OleDbInsertCommand1.Connection.Open();
//打开连接
OleDbInsertCommand1.ExecuteNonQuery();
//执行该SQL语句
OleDbInsertCommand1.Connection.Close();
//关闭连接

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

6.C#连接SyBase
程序代码: (OleDb)
--------------------------------------------------------------------------------

Provider=Sybase.ASEOLEDBProvider.2;Initial Catalog=数据库名;User ID=用户名;Data Source=数据源;Extended Properties="";Server Name=ip地址;Network Protocol=Winsock;Server Port Address=5000;

posted @ 2006-04-05 14:07 Ben 阅读(285) | 评论 (0)编辑 收藏

[转帖]SQL Server - [分布式查询/事务]

分布式查询
    OPENROWSET
    从Excel取数据
    SELECT * FROM OPENROWSET('Microsoft.Jet.OLEDB.4.0','Excel 8.0;Database=d:\1.xls',[Sheet1$])
    从Oracle取数据
    SELECT * FROM OPENROWSET('MSDAORA.1','NetServiceName';'User';'Password','SELECT * FROM OracleTalbe')
 
    Linked Server(for Oracle)
    建立Linked Server
    sp_addlinkedserver'Allies', 'Oracle', 'MSDAORA.1', 'NetServiceName'
    Oracle的Login
    sp_addlinkedsrvlogin'Allies', FALSE, 'SQLServerLogin', 'OracleUser', 'OraclePassword'
    从Oracle查询数据
    SELECT*FROM OPENQUERY( Allies, 'SELECT * FROM OracleTalbe'),或者
    SELECT*FROM Allies..OracleUser.OracleTalbe
    修改Linked Server的Server Option
     sp_serveroption'Allies', 'Option Name', 'Option Value'
    例如
    sp_serveroption'OraDC', 'rpc out', 'true'
    sp_serveroption'OraDC', 'rpc', 'true'
    向Oracle插入数据(还没有用过)
    INSERT INTO OPENQUERY(Allies, 'SELECT ... FROM OracleTalbe WHERE 1=2') VALUES ( ... )
    删除Linked Server
    sp_dropserver'Allies', 'droplogins'
 
    注意:使用OPENROWSET、OPENQUERY时,SQL Server不对提交的SQL语句做任何检查,直接将语句提交给Linked Server进行处理;使用四部分命名法时,SQL Server可能从Linked Server上读取被引用表的数据到SQL Server,然后在SQL Server上来完成其它操作。
 
    设置SQL Server到Oracle的Linked Server,可参考以下KB文章:
    How to set up and troubleshoot a linked server to Oracle in SQL Server
    Limitations of Microsoft Oracle ODBC Driver and OLEDB Provider
    Techniques to Debug Connectivity Issues to an Oracle Server Using the ODBC Driver and OLE DB Provider
    Supportability of the Microsoft ODBC Driver/ OLE DB Provider for Oracle w.r.t Oracle 8.x
 
    分布式事务中的OPENROWSET、OPENQUERY、OPENDATASOURCE
    如果在事务,或是一些隐含使用事务的情况下,例如TRIGGER中,使用OPENROWSET、OPENQUERY、OPENDATASOURCE时,就需要使用分布式事务来处理。
    在分布式事务中使用OPENROWSET、OPENQUERY、OPENDATASOURCE或Linked Server时,需要注意:
    1. 必须启动MSDTC服务。
    Service Name为Distributed Transaction Coodinator。
    2. 所涉及的Server之间如果存在网关、防火墙,需要开启TCP 135端口。
    分布式事务需要使用这个端口通讯。
    3. 如果Server之间跨网段,则Server之间需要能互相PING到机器名(而不是IP地址)。
    如果相互PING机器名有问题,修改system32/driver/etc目录下的hosts文件。
 
    上面的设置不正确时,会出现类似如下的错误:
    该操作未能执行,因为 OLE DB 提供程序 'SQLOLEDB' 无法启动分布式事务。
[OLE/DB provider returned message: 新事务不能登记到指定的事务处理器中。 ]
OLE DB 错误跟踪[OLE/DB Provider 'SQLOLEDB' ITransactionJoin::JoinTransaction returned 0x8004d00a]。
 
 
    分布式事务可以查询下列KB文章:
    Failed to Enlist on Calling Object's Transaction
    How to troubleshoot MS DTC firewall issues
    You receive error 7391 when you run a distributed transaction against a linked server
 
    使用分布式查询,可以参考:Chapter 25 - Distributed Queries: OLE DB Connectivity
    关于ORAOLEDB提供程序的详细说明,可以参考:Oracle Provider for OLE DB Developer's Guide - Release 9.2

posted @ 2006-03-29 16:35 Ben 阅读(1179) | 评论 (0)编辑 收藏

[转]揭开正则表达式的神秘面纱

[原创文章,转载请保留或注明出处:http://www.regexlab.com/zh/regref.htm]

引言

    正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来:(1)检查一个串中是否含有符合某个规则的子串,并且可以得到这个子串;(2)根据匹配规则对字符串进行灵活的替换操作。

    正则表达式学习起来其实是很简单的,不多的几个较为抽象的概念也很容易理解。之所以很多人感觉正则表达式比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难;另一方面,各种引擎自带的文档一般都要介绍它特有的功能,然而这部分特有的功能并不是我们首先要理解的。

    文章中的每一个举例,都可以点击进入到测试页面进行测试。闲话少说,开始。


1. 正则表达式规则

1.1 普通字符

    字母、数字、汉字、下划线、以及后边章节中没有特殊定义的标点符号,都是"普通字符"。表达式中的普通字符,在匹配一个字符串的时候,匹配与之相同的一个字符。

    举例1:表达式 "c",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"c";匹配到的位置是:开始于2,结束于3。(注:下标从0开始还是从1开始,因当前编程语言的不同而可能不同)

    举例2:表达式 "bcd",在匹配字符串 "abcde" 时,匹配结果是:成功;匹配到的内容是:"bcd";匹配到的位置是:开始于1,结束于4。


1.2 简单的转义字符

    一些不便书写的字符,采用在前面加 "\" 的方法。这些字符其实我们都已经熟知了。

表达式

可匹配

\r, \n

代表回车和换行符

\t

制表符

\\

代表 "\" 本身

    还有其他一些在后边章节中有特殊用处的标点符号,在前面加 "\" 后,就代表该符号本身。比如:^, $ 都有特殊意义,如果要想匹配字符串中 "^" 和 "$" 字符,则表达式就需要写成 "\^" 和 "\$"。

表达式

可匹配

\^

匹配 ^ 符号本身

\$

匹配 $ 符号本身

\.

匹配小数点(.)本身

    这些转义字符的匹配方法与 "普通字符" 是类似的。也是匹配与之相同的一个字符。

    举例1:表达式 "\$d",在匹配字符串 "abc$de" 时,匹配结果是:成功;匹配到的内容是:"$d";匹配到的位置是:开始于3,结束于5。


1.3 能够与 '多种字符' 匹配的表达式

    正则表达式中的一些表示方法,可以匹配 '多种字符' 其中的任意一个字符。比如,表达式 "\d" 可以匹配任意一个数字。虽然可以匹配其中任意字符,但是只能是一个,不是多个。这就好比玩扑克牌时候,大小王可以代替任意一张牌,但是只能代替一张牌。

表达式

可匹配

\d

任意一个数字,0~9 中的任意一个

\w

任意一个字母或数字或下划线,也就是 A~Z,a~z,0~9,_ 中任意一个

\s

包括空格、制表符、换页符等空白字符的其中任意一个

.

小数点可以匹配除了换行符(\n)以外的任意一个字符

    举例1:表达式 "\d\d",在匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"12";匹配到的位置是:开始于3,结束于5。

    举例2:表达式 "a.\d",在匹配 "aaa100" 时,匹配的结果是:成功;匹配到的内容是:"aa1";匹配到的位置是:开始于1,结束于4。


1.4 自定义能够匹配 '多种字符' 的表达式

    使用方括号 [ ] 包含一系列字符,能够匹配其中任意一个字符。用 [^ ] 包含一系列字符,则能够匹配其中字符之外的任意一个字符。同样的道理,虽然可以匹配其中任意一个,但是只能是一个,不是多个。

表达式

可匹配

[ab5@]

匹配 "a" 或 "b" 或 "5" 或 "@"

[^abc]

匹配 "a","b","c" 之外的任意一个字符

[f-k]

匹配 "f"~"k" 之间的任意一个字母

[^A-F0-3]

匹配 "A"~"F","0"~"3" 之外的任意一个字符

    举例1:表达式 "[bcd][bcd]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"bc";匹配到的位置是:开始于1,结束于3。

    举例2:表达式 "[^abc]" 匹配 "abc123" 时,匹配的结果是:成功;匹配到的内容是:"1";匹配到的位置是:开始于3,结束于4。


1.5 修饰匹配次数的特殊符号

    前面章节中讲到的表达式,无论是只能匹配一种字符的表达式,还是可以匹配多种字符其中任意一个的表达式,都只能匹配一次。如果使用表达式再加上修饰匹配次数的特殊符号,那么不用重复书写表达式就可以重复匹配。

    使用方法是:"次数修饰"放在"被修饰的表达式"后边。比如:"[bcd][bcd]" 可以写成 "[bcd]{2}"。

表达式

作用

{n}

表达式重复n次,比如:"\w{2}" 相当于 "\w\w""a{5}" 相当于 "aaaaa"

{m,n}

表达式至少重复m次,最多重复n次,比如:"ba{1,3}"可以匹配 "ba"或"baa"或"baaa"

{m,}

表达式至少重复m次,比如:"\w\d{2,}"可以匹配 "a12","_456","M12344"...

?

匹配表达式0次或者1次,相当于 {0,1},比如:"a[cd]?"可以匹配 "a","ac","ad"

+

表达式至少出现1次,相当于 {1,},比如:"a+b"可以匹配 "ab","aab","aaab"...

*

表达式不出现或出现任意次,相当于 {0,},比如:"\^*b"可以匹配 "b","^^^b"...

    举例1:表达式 "\d+\.?\d*" 在匹配 "It costs $12.5" 时,匹配的结果是:成功;匹配到的内容是:"12.5";匹配到的位置是:开始于10,结束于14。

    举例2:表达式 "go{2,8}gle" 在匹配 "Ads by goooooogle" 时,匹配的结果是:成功;匹配到的内容是:"goooooogle";匹配到的位置是:开始于7,结束于17。


1.6 其他一些代表抽象意义的特殊符号

    一些符号在表达式中代表抽象的特殊意义:

表达式

作用

^

与字符串开始的地方匹配,不匹配任何字符

$

与字符串结束的地方匹配,不匹配任何字符

\b

匹配一个单词边界,也就是单词和空格之间的位置,不匹配任何字符

    进一步的文字说明仍然比较抽象,因此,举例帮助大家理解。

    举例1:表达式 "^aaa" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "^" 要求与字符串开始的地方匹配,因此,只有当 "aaa" 位于字符串的开头的时候,"^aaa" 才能匹配,比如:"aaa xxx xxx"

    举例2:表达式 "aaa$" 在匹配 "xxx aaa xxx" 时,匹配结果是:失败。因为 "$" 要求与字符串结束的地方匹配,因此,只有当 "aaa" 位于字符串的结尾的时候,"aaa$" 才能匹配,比如:"xxx xxx aaa"

    举例3:表达式 ".\b." 在匹配 "@@@abc" 时,匹配结果是:成功;匹配到的内容是:"@a";匹配到的位置是:开始于2,结束于4。
    进一步说明:"\b" 与 "^" 和 "$" 类似,本身不匹配任何字符,但是它要求它在匹配结果中所处位置的左右两边,其中一边是 "\w" 范围,另一边是 非"\w" 的范围。

    举例4:表达式 "\bend\b" 在匹配 "weekend,endfor,end" 时,匹配结果是:成功;匹配到的内容是:"end";匹配到的位置是:开始于15,结束于18。

    一些符号可以影响表达式内部的子表达式之间的关系:

表达式

作用

|

左右两边表达式之间 "或" 关系,匹配左边或者右边

( )

(1). 在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰
(2). 取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到

    举例5:表达式 "Tom|Jack" 在匹配字符串 "I'm Tom, he is Jack" 时,匹配结果是:成功;匹配到的内容是:"Tom";匹配到的位置是:开始于4,结束于7。匹配下一个时,匹配结果是:成功;匹配到的内容是:"Jack";匹配到的位置时:开始于15,结束于19。

    举例6:表达式 "(go\s*)+" 在匹配 "Let's go go go!" 时,匹配结果是:成功;匹配到内容是:"go go go";匹配到的位置是:开始于6,结束于14。

    举例7:表达式 "¥(\d+\.?\d*)" 在匹配 "$10.9,¥20.5" 时,匹配的结果是:成功;匹配到的内容是:"¥20.5";匹配到的位置是:开始于6,结束于10。单独获取括号范围匹配到的内容是:"20.5"。


2. 正则表达式中的一些高级规则

2.1 匹配次数中的贪婪与非贪婪

    在使用修饰匹配次数的特殊符号时,有几种表示方法可以使同一个表达式能够匹配不同的次数,比如:"{m,n}", "{m,}", "?", "*", "+",具体匹配的次数随被匹配的字符串而定。这种重复匹配不定次数的表达式在匹配过程中,总是尽可能多的匹配。比如,针对文本 "dxxxdxxxd",举例如下:

表达式

匹配结果

(d)(\w+)

"\w+" 将匹配第一个 "d" 之后的所有字符 "xxxdxxxd"

(d)(\w+)(d)

"\w+" 将匹配第一个 "d" 和最后一个 "d" 之间的所有字符 "xxxdxxx"。虽然 "\w+" 也能够匹配上最后一个 "d",但是为了使整个表达式匹配成功,"\w+" 可以 "让出" 它本来能够匹配的最后一个 "d"

    由此可见,"\w+" 在匹配的时候,总是尽可能多的匹配符合它规则的字符。虽然第二个举例中,它没有匹配最后一个 "d",但那也是为了让整个表达式能够匹配成功。同理,带 "*" 和 "{m,n}" 的表达式都是尽可能地多匹配,带 "?" 的表达式在可匹配可不匹配的时候,也是尽可能的 "要匹配"。这 种匹配原则就叫作 "贪婪" 模式 。

    非贪婪模式:

    在修饰匹配次数的特殊符号后再加上一个 "?" 号,则可以使匹配次数不定的表达式尽可能少的匹配,使可匹配可不匹配的表达式,尽可能的 "不匹配"。这种匹配原则叫作 "非贪婪" 模式,也叫作 "勉强" 模式。如果少匹配就会导致整个表达式匹配失败的时候,与贪婪模式类似,非贪婪模式会最小限度的再匹配一些,以使整个表达式匹配成功。举例如下,针对文本 "dxxxdxxxd" 举例:

表达式

匹配结果

(d)(\w+?)

"\w+?" 将尽可能少的匹配第一个 "d" 之后的字符,结果是:"\w+?" 只匹配了一个 "x"

(d)(\w+?)(d)

为了让整个表达式匹配成功,"\w+?" 不得不匹配 "xxx" 才可以让后边的 "d" 匹配,从而使整个表达式匹配成功。因此,结果是:"\w+?" 匹配 "xxx"

    更多的情况,举例如下:

    举例1:表达式 "<td>(.*)</td>" 与字符串 "<td><p>aa</p></td> <td><p>bb</p></td>" 匹配时,匹配的结果是:成功;匹配到的内容是 "<td><p>aa</p></td> <td><p>bb</p></td>" 整个字符串, 表达式中的 "</td>" 将与字符串中最后一个 "</td>" 匹配。

    举例2:相比之下,表达式 "<td>(.*?)</td>" 匹配举例1中同样的字符串时,将只得到 "<td><p>aa</p></td>", 再次匹配下一个时,可以得到第二个 "<td><p>bb</p></td>"。


2.2 反向引用 \1, \2...

    表达式在匹配时,表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取。这一点,在前面的举例中,已经多次展示了。在实际应用场合中,当用某种边界来查找,而所要获取的内容又不包含边界时,必须使用小括号来指定所要的范围。比如前面的 "<td>(.*?)</td>"。

    其实,"小括号包含的表达式所匹配到的字符串" 不仅是在匹配结束后才可以使用,在匹配过程中也可以使用。表达式后边的部分,可以引用前面 "括号内的子匹配已经匹配到的字符串"。引用方法是 "\" 加上一个数字。"\1" 引用第1对括号内匹配到的字符串,"\2" 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 "(" 在前,那这一对就先排序号。

    举例如下:

    举例1:表达式 "('|")(.*?)(\1)" 在匹配 " 'Hello', "World" " 时,匹配结果是:成功;匹配到的内容是:" 'Hello' "。再次匹配下一个时,可以匹配到 " "World" "。

    举例2:表达式 "(\w)\1{4,}" 在匹配 "aa bbbb abcdefg ccccc 111121111 999999999" 时,匹配结果是:成功;匹配到的内容是 "ccccc"。再次匹配下一个时,将得到 999999999。这个表达式要求 "\w" 范围的字符至少重复5次,注意与 "\w{5,}" 之间的区别

    举例3:表达式 "<(\w+)\s*(\w+(=('|").*?\4)?\s*)*>.*?</\1>" 在匹配 "<td id='td1' style="bgcolor:white"></td>" 时,匹配结果是成功。如果 "<td>" 与 "</td>" 不配对,则会匹配失败;如果改成其他配对,也可以匹配成功。


2.3 预搜索,不匹配;反向预搜索,不匹配

    前面的章节中,我讲到了几个代表抽象意义的特殊符号:"^","$","\b"。它们都有一个共同点,那就是:它们本身不匹配任何字符,只是对 "字符串的两头" 或者 "字符之间的缝隙" 附加了一个条件。理解到这个概念以后,本节将继续介绍另外一种对 "两头" 或者 "缝隙" 附加条件的,更加灵活的表示方法。

    正向预搜索:"(?=xxxxx)","(?!xxxxx)"

    格式:"(?=xxxxx)",在被匹配的字符串中,它对所处的 "缝隙" 或者 "两头" 附加的条件是:所在缝隙的右侧,必须能够匹配上 xxxxx 这部分的表达式。因为它只是在此作为这个缝隙上附加的条件,所以它并不影响后边的表达式去真正匹配这个缝隙之后的字符。这就类似 "\b",本身不匹配任何字符。"\b" 只是将所在缝隙之前、之后的字符取来进行了一下判断,不会影响后边的表达式来真正的匹配。

    举例1:表达式 "Windows (?=NT|XP)" 在匹配 "Windows 98, Windows NT, Windows 2000" 时,将只匹配 "Windows NT" 中的 "Windows ",其他的 "Windows " 字样则不被匹配。

    举例2:表达式 "(\w)((?=\1\1\1)(\1))+" 在匹配字符串 "aaa ffffff 999999999" 时,将可以匹配6个"f"的前4个,可以匹配9个"9"的前7个。这个表达式可以读解成:重复4次以上的字母数字,则匹配其剩下最后2位之前的部分。当然,这个表达式可以不这样写,在此的目的是作为演示之用。

    格式:"(?!xxxxx)",所在缝隙的右侧,必须不能匹配 xxxxx 这部分表达式。

    举例3:表达式 "((?!\bstop\b).)+" 在匹配 "fdjka ljfdl stop fjdsla fdj" 时,将从头一直匹配到 "stop" 之前的位置,如果字符串中没有 "stop",则匹配整个字符串。

    举例4:表达式 "do(?!\w)" 在匹配字符串 "done, do, dog" 时,只能匹配 "do"。在本条举例中,"do" 后边使用 "(?!\w)" 和使用 "\b" 效果是一样的。

    反向预搜索:"(?<=xxxxx)","(?<!xxxxx)"

    这两种格式的概念和正向预搜索是类似的,反向预搜索要求的条件是:所在缝隙的 "左侧",两种格式分别要求必须能够匹配和必须不能够匹配指定表达式,而不是去判断右侧。与 "正向预搜索" 一样的是:它们都是对所在缝隙的一种附加条件,本身都不匹配任何字符。

    举例5:表达式 "(?<=\d{4})\d+(?=\d{4})" 在匹配 "1234567890123456" 时,将匹配除了前4个数字和后4个数字之外的中间8个数字。由于 JScript.RegExp 不支持反向预搜索,因此,本条举例不能够进行演示。很多其他的引擎可以支持反向预搜索,比如:Java 1.4 以上的 java.util.regex 包,.NET 中System.Text.RegularExpressions 命名空间,boost::regex 以及 GRETA 正则表达式库等。


3. 其他通用规则

    还有一些在各个正则表达式引擎之间比较通用的规则,在前面的讲解过程中没有提到。

3.1 表达式中,可以使用 "\xXX" 和 "\uXXXX" 表示一个字符("X" 表示一个十六进制数)

形式

字符范围

\xXX

编号在 0 ~ 255 范围的字符,比如:空格可以使用 "\x20" 表示

\uXXXX

任何字符可以使用 "\u" 再加上其编号的4位十六进制数表示,比如:"\u4E2D"

3.2 在表达式 "\s","\d","\w","\b" 表示特殊意义的同时,对应的大写字母表示相反的意义

表达式

可匹配

\S

匹配所有非空白字符("\s" 可匹配各个空白字符)

\D

匹配所有的非数字字符

\W

匹配所有的字母、数字、下划线以外的字符

\B

匹配非单词边界,即左右两边都是 "\w" 范围或者左右两边都不是 "\w" 范围时的字符缝隙

3.3 在表达式中有特殊意义,需要添加 "\" 才能匹配该字符本身的字符汇总

字符

说明

^

匹配输入字符串的开始位置。要匹配 "^" 字符本身,请使用 "\^"

$

匹配输入字符串的结尾位置。要匹配 "$" 字符本身,请使用 "\$"

( )

标记一个子表达式的开始和结束位置。要匹配小括号,请使用 "\(" 和 "\)"

[ ]

用来自定义能够匹配 '多种字符' 的表达式。要匹配中括号,请使用 "\[" 和 "\]"

{ }

修饰匹配次数的符号。要匹配大括号,请使用 "\{" 和 "\}"

.

匹配除了换行符(\n)以外的任意一个字符。要匹配小数点本身,请使用 "\."

?

修饰匹配次数为 0 次或 1 次。要匹配 "?" 字符本身,请使用 "\?"

+

修饰匹配次数为至少 1 次。要匹配 "+" 字符本身,请使用 "\+"

*

修饰匹配次数为 0 次或任意次。要匹配 "*" 字符本身,请使用 "\*"

|

左右两边表达式之间 "或" 关系。匹配 "|" 本身,请使用 "\|"

3.4 括号 "( )" 内的子表达式,如果希望匹配结果不进行记录供以后使用,可以使用 "(?:xxxxx)" 格式

    举例1:表达式 "(?:(\w)\1)+" 匹配 "a bbccdd efg" 时,结果是 "bbccdd"。括号 "(?:)" 范围的匹配结果不进行记录,因此 "(\w)" 使用 "\1" 来引用。

3.5 常用的表达式属性设置简介:Ignorecase,Singleline,Multiline,Global

表达式属性

说明

Ignorecase

默认情况下,表达式中的字母是要区分大小写的。配置为 Ignorecase 可使匹配时不区分大小写。有的表达式引擎,把 "大小写" 概念延伸至 UNICODE 范围的大小写。

Singleline

默认情况下,小数点 "." 匹配除了换行符(\n)以外的字符。配置为 Singleline 可使小数点可匹配包括换行符在内的所有字符。

Multiline

默认情况下,表达式 "^" 和 "$" 只匹配字符串的开始 ① 和结尾 ④ 位置。如:

①xxxxxxxxx②\n
③xxxxxxxxx④

配置为 Multiline 可以使 "^" 还可以匹配换行符之后,下一行开始前 ③ 的位置,使 "$" 还可以匹配换行符之前,一行结束 ② 的位置。

Global

主要在将表达式用来替换时起作用,配置为 Global 表示替换所有的匹配。


4. 综合提示

4.1 如果要要求表达式所匹配的内容是整个字符串,而不是从字符串中找一部分,那么可以在表达式的首尾使用 "^" 和 "$",比如:"^\d+$" 要求整个字符串只有数字。

4.2 如果要求匹配的内容是一个完整的单词,而不会是单词的一部分,那么在表达式首尾使用 "\b",比如:使用 "\b(if|while|else|void|int……)\b" 来匹配程序中的关键字

4.3 表达式不要匹配空字符串。否则会一直得到匹配成功,而结果什么都没有匹配到。比如:准备写一个匹配 "123"、"123."、"123.5"、".5" 这几种形式的表达式时,整数、小数点、小数数字都可以省略,但是不要将表达式写成:"\d*\.?\d*",因为如果什么都没有,这个表达式也可以匹配成功。更好的写法是:"\d+\.?\d*|\.\d+"

4.4 能匹配空字符串的子匹配不要循环无限次。如果括号内的子表达式中的每一部分都可以匹配 0 次,而这个括号整体又可以匹配无限次,那么情况可能比上一条所说的更严重,匹配过程中可能死循环。虽然现在有些正则表达式引擎已经通过办法避免了这种情况出现死循环了,比如 .NET 的正则表达式,但是我们仍然应该尽量避免出现这种情况。如果我们在写表达式时遇到了死循环,也可以从这一点入手,查找一下是否是本条所说的原因。

4.5 合理选择贪婪模式与非贪婪模式。

4.6 或 "|" 的左右两边,对某个字符最好只有一边可以匹配,这样,不会因为 "|" 两边的表达式因为交换位置而有所不同。


5. 搜索更多正则表达式支持

在以下搜索字段中输入关键字,查找问题的答案。

posted @ 2006-02-22 10:47 Ben 阅读(386) | 评论 (0)编辑 收藏

了解DLL

一、从DLL技术说起

要了解DLL木马,就必须知道这个“DLL”是什么意思,所以,让我们追溯到几年前,DOS系统大行其道的日子里。在那时候,写程序是一件繁琐的事情,因为每个程序的代码都是独立的,有时候为了实现一个功能,就要为此写很多代码,后来随着编程技术发展,程序员们把很多常用的代码集合(通用代码)放进一个独立的文件里,并把这个文件称为Library),在写程序的时候,把这个库文件加入编译器,就能使用这个库包含的所有功能而不必自己再去写一大堆代码,这个技术被称为静态链接Static Link)。静态链接技术让劳累的程序员松了口气,一切似乎都很美好。可是事实证明,美好的事物不会存在太久,因为静态链接就像一个粗鲁的推销员,不管你想不想要宣传单,他都全部塞到你的手上来。写一个程序只想用到一个库文件包含的某个图形效果,就因为这个,你不得不把这个库文件携带的所有的图形效果都加入程序,留着它们当花瓶摆设,这倒没什么重要,可是这些花瓶却把道路都阻塞了——静态链接技术让最终的程序成了大块头,因为编译器把整个库文件也算进去了。

时代在发展,静态链接技术由于天生的弊端,不能满足程序员的愿望,人们开始寻找一种更好的方法来解决代码重复的难题。后来,Windows系统出现了,时代的分水岭终于出现。Windows系统使用一种新的链接技术,这种被称为动态链接Dynamic Link)的新技术同样也是使用库文件,微软称它们为动态链接库”——Dynamic Link LibraryDLL的名字就是这样来的。动态链接本身和静态链接没什么区别,也是把通用代码写进一些独立文件里,但是在编译方面,微软绕了个圈子,并没有采取把库文件加进程序的方法,而是把库文件做成已经编译好的程序文件,给它们开个交换数据的接口,程序员写程序的时候,一旦要使用某个库文件的一个功能函数,系统就把这个库文件调入内存,连接上这个程序占有的任务进程,然后执行程序要用的功能函数,并把结果返回给程序显示出来,在我们看来,就像是程序自己带有的功能一样。完成需要的功能后,这个DLL停止运行,整个调用过程结束。微软让这些库文件能被多个程序调用,实现了比较完美的共享,程序员无论要写什么程序,只要在代码里加入对相关DLL的调用声明就能使用它的全部功能。最重要的是,DLL绝对不会让你多拿一个花瓶,你要什么它就给你什么,你不要的东西它才不会给你。这样,写出来的程序就不能再携带一大堆垃圾了——绝对不会让你把吃剩的东西带回家,否则罚款,这是自助餐。

DLL
技术的诞生,使编写程序变成一件简单的事情,Windows为我们提供了几千个函数接口,足以满足大多数程序员的需要。而且,Windows系统自身就是由几千个DLL文件组成,这些DLL相互扶持,组成了强大的Windows系统。如果Windows使用静态链接技术,它的体积会有多大?我不敢想。

二、应用程序接口API

上面我们对DLL技术做了个大概分析,在里面我提到了接口,这又是什么呢?因为DLL不能像静态库文件那样塞进程序里,所以,如何让程序知道实现功能的代码和文件成了问题,微软就为DLL技术做了标准规范,让一个DLL文件像奶酪一样开了许多小洞,每个洞口都注明里面存放的功能的名字,程序只要根据标准规范找到相关洞口就可以取得它要的美味了,这个洞口就是应用程序接口Application Programming Interface),每个DLL带的接口都不相同,尽最大可能的减少了代码的重复。用Steven的一句话:API就是一个工具箱,你根据需要取出螺丝刀、扳手,用完后再把它们放回原处。在Windows里,最基本的3DLL文件是kernel32.dlluser32.dllgdi32.dll。它们共同构成了基本的系统框架。

posted @ 2006-02-17 11:25 Ben 阅读(233) | 评论 (0)编辑 收藏

Google的技巧(特辑)

1:网络摄像头

在Google中输入“inurl:"ViewerFrame?Mode="”或者“inurl:"MultiCameraFrame?Mode="”、“inurl:"view/index.shtml"”(输入时不带外面的双引号,在英文状态下输入),你会获得无数个未经加密的网络摄像机监视到的画面。无聊的时候玩玩,可以满足一下我们的好奇心。此外,打开这个站点:www.opentopia.com/hiddencam.php,在“from”中选择“China”,你还可以看到国内的某处网络摄像机画面。

*******************

2:中英文字典

  Google提供了一个中英文字典,很方便使用。用户可以按照下列方法查找词义查找英文的中文词义则输入
fy computer
查找中文的英文词义则输入 翻译 计算机

3:条形码查询

  用户输入一个商品的条形码就可以找到有关该产品的说明。

4:汉语拼音输入检索
  为了方便使用中文的用户在网上搜索,Google允许用户直接在键盘上输入汉语拼音来检索相关事物,例如:
  输入 shanghaishikebiao
  检索结果提示:您是不是要找: 上海时刻表 
  这正是我们需要查找的关键词,用户可以据此浏览相关结果,这包括上海地区的各种交通工具的时刻表。如果需要查找更详细的资料"上海飞机航班时刻表 ",则只要在原来的检索结果"上海时刻表"中间输入feijihangban ,例如:
  上海feijihangban时刻表
  Google的这项新功能,可以免除用户在中文和拼音输入方面的互相转换。用户在输入拼音时,不要留有空格,否则Google会误认为英文。Google把拼音与常用的字或者词组一一对应,因此,过于生僻的字或词组不适合于用这个方法查找
 
5。 汉语拼音输入检索
  为了方便使用中文的用户在网上搜索,Google允许用户直接在键盘上输入汉语拼音来检索相关事物,例如:
  输入 shanghaishikebiao
  检索结果提示:您是不是要找: 上海时刻表 
  这正是我们需要查找的关键词,用户可以据此浏览相关结果,这包括上海地区的各种交通工具的时刻表。如果需要查找更详细的资料"上海飞机航班时刻表 ",则只要在原来的检索结果"上海时刻表"中间输入feijihangban ,例如:
  上海feijihangban时刻表
  Google的这项新功能,可以免除用户在中文和拼音输入方面的互相转换。用户在输入拼音时,不要留有空格,否则Google会误认为英文。Google把拼音与常用的字或者词组一一对应,因此,过于生僻的字或词组不适合于用这个方法查找。

  6。 中英文字典
  经常使用计算机的用户手头上自然会有一、两个字典软件,用于查找和翻译中英文的词义。作为一种使用频率较高的工具,Google也提供了一个中英文字典,很方便使用。用户可以按照下列方法查找词义查找英文的中文词义则输入  fy  computer 查找中文的英文词义则输入  翻译  计算机

  7。 天气查询
  天气情况也是人们经常要查询的信息之一,Google 提供的天气查询来自于一个更新及时的中文气象网站,适合中国人使用。用户输入中文和英文都可以查询,例如要了解奥运会期间雅典的天气情况,可以按照下列方法输入:
  雅典 天气  athens tq 返回的查询结果中会在第一条出现一个 "雅典天气预报",用户点击后就可以看到当天雅典的天气情况。如果地名相同者,用户还需要进行一次选择。

  8。 股票查询
  查询股票的网站已经很多了,Google提供的股票查询只是更方便一些而已,用户可以按照股票名称、股票代码或者股票名称的声母字母查询,下列为查询"中国联通"股票行情的举例。
  中国联通 股票 zglt gp
  gp 600050

  9。 邮政编码和区号查询
  人们时常需要查询邮政编码和电话区号,Google提供了这样一个实用的功能,用户据此能够获得所要查询的省市名称,邮政编码及长途电话区号,下面为查询举例:
  邮编 杭州       
  区号 绍兴       
  yb  杭州 
  qh  绍兴
  需要注意的是用户只能查询到城市级别的邮政编码和区号,而无法进一步查询区县的具体信息。

  10。 手机归属地查询
  用户在输入手机号码后可以获得号码段、归属地、卡类型、邮政编码和电话区号的信息,但是从实用的角度看,其中只有手机归属地的信息较为有用。

  11。 计算器使用
  Google有计算器的功能,例如在google检索框中输入45*86+35/7,就会得到结果:
  (45 * 86) + (35 / 7) = 3 875
  有兴趣的用户,或者经常在计算机上进行运算的用户不妨可以试一试。

  12。 购物检索
  Google新开设的购物检索称之为Froogle,网址为http://froogle。google。com/
  用户只要输入商品的名称,就可以看到该商品的图片和价格,用户还可以限定一种商品的价格进行检索,并且将检索结果按需要从高价到低价排序列出,许多商品可以直接在网上订购,这种图文并茂的检索购物方式较受用户青睐。

  13。 美国实用生活信息查询
  如果用户生活在美国或者短期去美国出差和学习,下面的查询功能或许能对他们又帮助,因为这些检索服务目前仅限于美国。
  14 地区代码查询
  用户输入美国的地区代码,在返回的检索结果中的第一项就是该地区的地图,用户可以通过不断的点击来找到一条具体的大街。 

   15 飞机航班查询
  用户输入一家航空公司的名称和航班号,即可获得该航班的出发地和目的地,起飞和到达时间,以及实际航行情况,目前是否开始检票,抵达目的地候机大楼的舱门号。
  16 车牌号查询
  用户输入车牌号,可以获得一辆车的名称、型号、出厂年份,车身和发动机情况。
  17 邮件查询
  用户输入一个邮件的号码,可以获悉该邮件目前的状况,譬如邮件已经抵达或者正在路途上等。

  18。 检索工具栏
  Google的检索工具栏功能强大,有拖放和右击检索功能,新闻阅读,广告拦截,网站排名显示和搜索字词标明等,工具栏可以附在浏览器下,使用更加方便。用户可以首先在Google网站下载并安装一个检索工具栏,然后根据需要在工具栏的选项中进行设置,我们推荐用户使用这个检索工具栏,它将给用户带来许多意想不到的方便。

  10.1 Google 新闻
  Google 的新闻来源于4500家报刊杂志和通讯社,在精选以后持续播出世界各国的新闻,每条新闻都有更新的时间,并联接相关的新闻。用户可以使用免费的新闻通知服务,通过电子邮件收到自己感兴趣的新闻。
  10.2 网站排名
  Google 通过对 Web 链接结构和许多其它变量自动计算,对网页的重要程度进行评定。网站排名根据这个评定能够显示用户正在访问的网站的重要程度,用一根绿色线条显示,直观而明确。
  10.3 搜索字词标明
  搜索字词标明通过鲜艳的色彩标明用户所检索的字词在每个网页上的位置,便于用户查阅,单击"搜索字词标明"按钮可以打开和关闭标明状态。
  10.4 拖放和右击检索
  拖放检索功能使检索更为方便,用户可以把在网页上所选取的字词直接拖放到检索框中,Google会自动进行检索。对于与 Web浏览器同时运行的许多文字处理应用程序中的文字,也可以使用此功能。右击检索是指用户可以在网页上选取文字后,右击鼠标,然后从弹出式菜单中选择"Google 搜索"便可以自动检索。

  Google搜索引擎为我们提供了搜索的方便,她正在不断推出新的服务功能,例如为移动电话特别设计的无线搜寻等,相信随着技术的不断发展,我们会从中享受更多的搜索乐趣。

 

posted @ 2006-02-15 15:22 Ben 阅读(429) | 评论 (0)编辑 收藏

[转]TCP/IP协议介绍

[以太网接口(毕业设计)]TCP/IP协议介绍
yzy1102 发表于 2006-1-16 19:33:00

    TCP/IP协议,或称为TCP/IP协议栈,或互联网协议系列。

TCP/IP协议栈
(按TCP/IP参考模型划分)

应用层 FTP SMTP HTTP ...
传输层 TCP UDP
网络层 IP ICMP ARP
链路层 以太网 令牌环 FDDI ...

    包含了一系列构成互联网基础的网络协议。这些协议最早发源于美国国防部的DARPA互联网项目。TCP/IP字面上代表了两个协议:TCP传输控制协议和IP互联网协议。

    时间回放到1983年1月1日,在这天,互联网的前身Arpanet中,TCP/IP协议取代了旧的网络核心协议NCP(Network Core Protocol),从而成为今天的互联网的基石。最早的的TCP/IP由Vinton Cerf和Robert Kahn两位开发,慢慢地通过竞争战胜了其它一些网络协议的方案,比如国际标准化组织ISO的OSI模型。TCP/IP的蓬勃发展发生在上世纪的90年代中期。当时一些重要而可靠的工具的出世,例如页面描述语言HTML和浏览器Mosaic,导致了互联网应用的飞束发展。

    随着互联网的发展,目前流行的IPv4协议(IP Version 4,IP版本四)已经接近它的功能上限。IPv4最致命的两个缺陷在与:

  • 地址只有32位,IP地址空间有限;
  • 不支持服务等级(Quality of Service, Qos)的想法,无法管理带宽和优先级,故而不能很好的支持现今越来越多的实时的语音和视频应用。因此IPv6 (IP Version 6, IP版本六) 浮出海面,用以取代IPv4。

    TCP/IP成功的另一个因素在与对为数众多的低层协议的支持。这些低层协议对应与OSI模型 中的第一层(物理层)和第二层(数据链路层)。每层的所有协议几乎都有一半数量的支持TCP/IP,例如: 以太网(Ethernet),令牌环(Token Ring),光纤数据分布接口(FDDI),端对端协议( PPP),X.25,帧中继(Frame Relay),ATM,Sonet, SDH等。

目录
1 TCP/IP协议栈组成
2 必须协议
3 推荐协议
4 可选协议
5 范例: 不同计算机运行的不同协议
6 参考文献

   

 

 

 

    TCP/IP协议栈组成

    整个通信网络的任务,可以划分成不同的功能块,即抽象成所谓的 ” 层” 。用于互联网的协议可以比照TCP/IP参考模型进行分类。TCP/IP协议栈起始于第三层协议IP(互联网协议) 。所有这些协议都在相应的RFC文档中讨论及标准化。重要的协议在相应的RFC文档中均标记了状态: “必须“ (required) ,“推荐“ (recommended) ,“可选“ (elective) 。其它的协议还可能有“ 试验“(experimental) 或“ 历史“(historic) 的状态。

    必须协议

    所有的TCP/IP应用都必须实现IP和ICMP。对于一个路由器(router) 而言,有这两个协议就可以运作了,虽然从应用的角度来看,这样一个路由器 意义不大。实际的路由器一般还需要运行许多“推荐“使用的协议,以及一些其它的协议。

    在几乎所有连接到互联网上的计算机上都存在的IPv4 协议出生在1981年,今天的版本和最早的版本并没有多少改变。升级版IPv6 的工作始于1995年,目的在与取代IPv4。ICMP 协议主要用于收集有关网络的信息查找错误等工作。

    推荐协议

    每一个应用层(TCP/IP参考模型 的最高层) 一般都会使用到两个传输层协议之一: 面向连接的TCP传输控制协议和无连接的包传输的UDP用户数据报文协议 。 其它的一些推荐协议有:

  • TELNET (Teletype over the Network, 网络电传) ,通过一个终端(terminal)登陆到网络(运行在TCP协议上)。
  • FTP (File Transfer Protocol, 文件传输协议) ,由名知义(运行在TCP协议上) 。
  • SMTP (Simple Mail Transfer Protocol,简单邮件传输协议) ,用来发送电子邮件(运行在TCP协议上) 。
  • DNS (Domain Name Service,域名服务) ,用于完成地址查找,邮件转发等工作(运行在TCP和UDP协议上) 。
  • ECHO (Echo Protocol, 回绕协议) ,用于查错及测量应答时间(运行在TCP和UDP协议上) 。
  • NTP (Network Time Protocol,网络时间协议) ,用于网络同步(运行在UDP协议上) 。
  • SNMP (Simple Network Management Protocol, 简单网络管理协议) ,用于网络信息的收集和网络管理。
  • BOOTP (Boot Protocol,启动协议) ,应用于无盘设备(运行在UDP协议上)。

    可选协议

    最常用的一些有

  • 支撑万维网WWW的超文本传输协议HTTP,
  • 动态配置IP地址的DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),
  • 收邮件用的POP3 (Post Office Protocol, version 3, 邮局协议) ,
  • 用于加密安全登陆用的SSH (Secure Shell,用于替代安全性差的TELNET) ,
  • 用于动态解析以太网硬件地址的ARP (Address Resolution Protocol,地址解析协议) 。

    范例: 不同计算机运行的不同协议

  • 一个简单的路由器上可能会实现ARP, IP, ICMP, UDP, SNMP, RIP。
  • WWW用户端使用ARP, IP, ICMP, UDP, TCP, DNS, HTTP, FTP。
  • 一台用户电脑上还会运行如TELNET, SMTP, POP3, SNMP, ECHO, DHCP, SSH, NTP。
  • 无盘设备可能会在固件比如ROM中实现了ARP, IP, ICMP, UDP, BOOT, TFTP (均为面向数据报的协议,实现起来相对简单)。

TCP/IP基础讲座-1:1层,2层,3层?

    读过关于网络的课程的,都知道ISO-OSI 7层协议这个名词,许多书籍都会具体的画出那幅图,然后标注上物理层,数据链路层,网络层等等.背的大家要死.但是却又不知道具体这些层次干吗用的勒?

    其实在互联网中,由于实际使用的是TCP/IP模型,也就是DOD模型(现在不知道没关系,后面会说).所以7层模型在现实网络环境中只是一个理论上,学究派的东西.这个模型中,我们真正关心的是下面的3层.

1.物理层 .哦.是的.这个名词还算容易了解.网卡还有那些网线构成了这一层.那些在网线中传播的二进制数据流是这层的具体表象.也就是说,这一层上面没有什么协议(不是很精确的说法,但是你可以这么理解).有的都是电流而已.我们把两台机器用网线连起来.或者用HUB把机器都连起来,这些工作就是物理层的工作.

    有2个设备属于物理层的,一个是中继器,一个是HUB.大家知道.物理上面的连线距离一长就会产生电信号的衰减.为了重新加强这个信号,我们就需要在一定距离之后加上一个信号放大器,这就是中继器(repeater)

    恩...这个比较容易理解.repeater就是连接在2根网线之间的么.没有做任何处理.所以只是一个物理设备.属于1层的.

    那么集线器(HUB) 呢?这个怎么会是在1层???似乎非常难以理解.

    当我说出HUB的本质,大家就能够清楚了解了

    HUB的本质其实只是一个多口中继器(MULTI PORT REPEATER) .啊...这样大家能够理解了.HUB不叫多口中继器其实只是为了销售上面的策略.他的本质就是连接多根网线的一个物理设备.也是不对经过的电信号做任何逻辑处理的.

2.数据链路层

    欧~这个名词有些别扭了.DATA LINK层.英文似乎更加容易理解.

    这个层面上面的东西不再是电信号了.而是DATA了.对,既然是DATA就有了逻辑关系了.这个层面上面的基本单位是帧(Frame) .这层和物理层的接触是最紧密的.他是把从网线上面传输的电流转换成0和1的组合.

    物理层只是网卡对网线发出或者接受各种电平信号,那就是说物理层是无法判别电流的来源和目标的.那么把电流打成0和1的帧之后.里面就有逻辑数据了.有了数据,就可以判别数据从何而来,到何处去.所以也就可以真正的形成LINK.

    既然可以判别地址,那么地址是按照什么来判别的呢?

    那就是最重要的概念之一:MAC地址

    大家肯定都听说过我们的网卡都有MAC地址

    有些人可能也知道MAC地址都是唯一的.

    对.MAC地址是全球唯一的.也就是说你的网卡虽然便宜.但是他也是世界上独一无二的.

    有些人说他可以改MAC.那就不是唯一了.对.虽然可以更改,那只是欺骗上层对封包里面的MAC地址进行改写.你网卡真正的MAC地址是固化的.无法修改的.

    我们有了MAC地址了.这样就可以有针对性对所有连接在一起的计算机进行通讯了.是的.我们终于可以在一个局域网内通讯了.

    但是有个问题我们前面没有提到.就是既然物理层传输的是电信号.那么如果我有2台机器一起发电信号,信号岂不是混乱了么?

    非常正确.这个问题在网络里面成为"碰撞",所以协议里面规定了如果你需要往外发数据,一定需要先看看电缆里面有没有别的信号.如果没有,那就可以发.如果2者同时发送,检测到碰撞之后2者分别等待一个随机时间,然后重发.这个就是重要的"碰撞检测 ".

    哈.看来问题解决了.不是么.现在整个网络可以正常运行了.

    确实如此.但是如果连接在网络上的计算机越来越多,那么碰撞的现象会越来越频繁.这样效率一定很低了.恩.这里还有一个重要概念"冲突域 ".在同一个物理上连接的网络上的所有设备是属于同一个冲突域的.

    接着就需要引入我们的2层设备来分割冲突域了.

    网桥(Bridge) 就是连接2个不同的物理网络的.主要功能是在2个网络之间转发Frame.因为从实际中我们可以知道.其实很多时候并非整个网络都在相互通讯.最多相互通讯的一组计算机我们可以分在一个小的冲突域内.这样分割以后可以减少冲突域,也就相对的减少了冲突的机会.而之间使用网桥来桥接,由于网桥两边的通讯不是非常频繁,所以使用网桥来为2边作为"代言人".这样任意一个小网络里面产生冲突的机会就少了.

    交换机(Switch)是我们最熟悉的设备了,交换机的本质其实就是一个多口网桥(Multi port Bridge) .同理可得.交换机的每个口后面都是一个冲突域.我们都说交换机比HUB快,就是因为交换机分割了所有的冲突域.

    由于现在交换机非常便宜.所以一般我们都是直接在交换机的口上接计算机.这样每台计算机都是一个独立的冲突域.这样碰撞的问题就没有了.所以速度是比HUB快.

    而前面说过.2层设备主要是个转发的功能.交换机的主要功能就是转发包.而不是让所有的冲突域直接物理连接.所以交换机有CPU,有内存,可以对frame进行处理等等.这些也是交换机和HUB的区别.


3.网络层

    我们前面的一些技术就可以构建出局域网了.有了网络层以后.数据才能够真正的在整个世界间传送

    由于伦纳德?博萨卡(Leonard Bosack)和姗蒂?雷纳(Sandy Lerner)为了解决他们之间的通信问题(关于路由器发明的版本有很多.你听到的别的说法可能比这个说法更准确,但是谁知道呢.呵呵).路由器被发明用来解决"信息孤岛"问题.而且如果是由SWITCH来构建整个网络,那么整个网络将会有"中心节点",这样也不符合ARPANET的初衷.所以我们有了这一层.(这样说可能会感觉本末倒置,但是先这么理解吧.)

    这一层的基本单元是包(Packet) .所有的包都有一个IP头.啊.听起来很熟悉不是么.IP就是用来在这层上面标识包的来源和目的地址的.

    这层的一个主要概念就是"路由 ",也就是和switch一样,把包转发到其他的地方.不过有个不同的地方,switch只有知道具体的MAC在哪里的情况下才能够发送给指定的计算机,而路由则不需要知道最终IP所在的计算机在哪个位置,只要知道那个途径可以过去就可以工作.

    这3层构建了整个网络的基础.由于TCP/IP模型将最下面2层合并成为一层,所以在TCP/IP里面总共这2层也是整个构架最基础的内容.而网络方面要做的工作也都是针对于这2层做的.


2: TCP/IP.真实世界的模型

    上一讲里面我们说过OSI 7层模型只是一个理论模型,而实际中只需要保证7层的功能能够实现,实际分层无需按照7层来分.而且如果真的分7层.那么数据处理的速度便要慢许多.

    在实际应用中.使用最多的便是DoD模型.也成为TCP/IP协议簇

    DoD模型(Department Of Defanse Model 美国国防部模型) 顾名思义,是美国国防部设计的一个网络模型.最早用于ARPANET.这些话可能在许多教材的第一章就会讲了.但是一般教材对于DoD模型与OSI模型对应关系都没有讲到.或者很多是模糊或者错误的.

    在这里我就要描述一下2者对应关系.OSI模型有7层我们已经知道了,而DoD模型则只有4层.下面是对应关系

    OSI                                  DoD

    7.Application     ┐     

    6.Presentation   |->       4. Application/Process

    5.Session         ┘     

    4.Transport       --->       3. Host to Host

    3.Network        --->       2. Internet

    2.Data Link      ┬->       1. Network Access

    1.Physical        ┘


    由于我不会制表符.所以图有些难看.其实就是OSI的1.2层对应DoD的第1层

OSI的5.6.7对应DoD的第4层

    其实这个还是比较容易记忆的

    由于物理层和数据链路层非常密切.所以分为一个.然后上面依次对应,最上面的一大块成为应用层(处理层)

现在我们有了一个可用的实际模型了.不过一般我们在描述某个设备或者协议的时候.还是会使用OSI的模型,比如我们在讨论SWITCH的时候,就会说他是一个2层的设备.而路由器是一个3层的设备,还会有一些特殊的设备,比如3层交换机,4层交换机.这些都是使用OSI模型进行分类的.这点大家不要搞混淆了.


    我们一直听说TCP或者UDP.还有什么SMTP.POP3.这些协议到底是在哪一层定义的那?接下来的一张图会给大家一个非常清晰的概念了(不能算是图拉 :D ).


    4. APPLICATION

    HTTP,FTP,telnet,SNMP,SMTP,POP3,DNS 等等


    3.Host to Host

    TCP,UDP


    2.internet

    ICMP,ARP,RARP,IP


    1.Network Access

    Ethernet,FastEthernet,Token Ring 等等

    恩...这下清楚了.让我们从下至上来看看

    首先是最下层的.包括了以太网,快速以太网,还有现在的千M以太网等等的协议,这些协议规定了线缆的绞数.连接方式等等物理层的东西.还有底层使用MAC通讯的方式等等.


    接下来是IP.ARP这些.IP在OSI模型的时候也说过.通过IP地址.我们在转发包的时候无需知道具体目标机的位置.而路由器自然会根据路由表来转发.最后一站一站的慢慢传递.达到最终目标.而ARP协议就是在IP和MAC之间转换用的.

 我在上一章提过,由于有了路由器,IP,整个网络才真正能够覆盖全球.所以这一层叫做internet大家也应该容易记忆了.


    WOW.TCP,UDP是我们听说最多的了.他是属于控制网络连接的.在OSI称为Transport.传输层.在DoD内是Host to Host 端对端.意思其实是一样的.就是在在2台计算机之间构建出一个虚拟的通讯通道来.


    最上面一层就无穷无尽了.所有的最终应用层的东西都在这里,你甚至可以定义你自己的协议类型.这些都是完全可以的.因为本身这一层就是提供给开发人员自行发挥的.只是上面列举的都经过标准化了.


    TCP包头结构

    源端口 16位

    目标端口  16位

    序列号  32位

    回应序号  32位

    TCP头长度  4位

    reserved 6位

    控制代码 6位

    窗口大小 16位

    偏移量 16位

    校验和 16位

    选项   32位(可选)

    这样我们得出了TCP包头的最小大小.就是20字节.


    UDP包头结构

    源端口 16位

    目的端口 16位

    长度  16位

    校验和  16位

    恩...UDP的包小很多.确实如此.因为UDP是非可靠连接.设计初衷就是尽可能快的将数据包发送出去.所以UDP协议显得非常精简.

    有一个问题,似乎这些头里面怎么没有IP地址啊.没有IP地址这些包往哪里发送那?

    对.你观察的很仔细.TCP和UDP的头里面确实没有任何IP信息.我们回头想一下TCP和UDP是属于DoD的哪一层的? 对了!是第3层. 而IP则位于模型的第二层.也就是他们两者虽然有联系.但是不属于同一层.

    模型的一个重要规则就是.当发送端发送一个数据,上一层将数据传往下一层的时候.上一层的包就成为了下一层包的数据部分.

    而到接受端接受到数据.下一层将本层的头部信息去掉后交给上一层去处理.

那么我们来看看实际例子:

    假使我们通过SMTP协议发送数据AAA到另外一段.那么数据先会被加上SMTP的头.成为[SMTP]AAA.往下发送到TCP层.成为[TCP][SMTP]AAA.再往下送到internet层[IP][TCP][SMTP]AAA.然后成为[MAC][IP][TCP][SMTP]AAA

    这样通过enternet或者FastEnternet发送到路由器.路由器得到后替换自己的MAC地址上去.传到下一级的路由器.这样经过长途跋涉.最终这个数据流到达目标机.


    目标机先从下面一层开始.去掉MAC,成为[IP][TCP][SMTP]AAA往上到IP层,恩,比对后是发送给我这个IP的.去掉,成为[TCP][SMTP]AAA.TCP接到了查看校验和,没错.往上[SMTP]AAA.最后SMTP协议去解释.得到了AAA.


    万里长征终于结束.我们也将AAA发送到了目标机.大家也应该明白了为何TCP包头和UDP包头里面没有IP地址那?因为IP位于他们下面一层.TCP和UDP的包头信息是作为IP包的数据段来传送的.


    IP层可不管那许多.他只管他那层的协议,也就是管把从上面层来的数据加上自己的头,传到下面一层.把从下面一层来的数据去掉头.传到上面一层.


    每层都是这么干的.完美的契合完成了数据包的最终旅程.

TCP/IP的通讯协议

  这部分简要介绍一下TCP/IP的内部结构。TCP/IP协议组之所以流行,部分原因是因为它可以用在各种各样的信道和底层协议(例如T1和X.25、以太网以及RS-232串行接口)之上。确切地说,TCP/IP协议是一组包括TCP协议和IP协议,UDP(User Datagram Protocol)协议、ICMP(Internet Control Message Protocol)协议和其他一些协议的协议组。

TCP/IP整体构架概述

  TCP/IP协议并不完全符合OSI的七层参考模型。传统的开放式系统互连参考模型,是一种通信协议的7层抽象的参考模型,其中每一层执行某一特定任务。该模型的目的是使各种硬件在相同的层次上相互通信。这7层是:物理层、数据链路层、网路层、传输层、话路层、表示层和应用层。而TCP/IP通讯协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的网络来完成自己的需求。这4层分别为:

  应用层:应用程序间沟通的层,如简单电子邮件传输(SMTP)、文件传输协议(FTP)、网络远程访问协议(Telnet)等。

  传输层:在此层中,它提供了节点间的数据传送服务,如传输控制协议(TCP)、用户数据报协议(UDP)等,TCP和UDP给数据包加入传输数据并把它传输到下一层中,这一层负责传送数据,并且确定数据已被送达并接收。

  互连网络层:负责提供基本的数据封包传送功能,让每一块数据包都能够到达目的主机(但不检查是否被正确接收),如网际协议(IP)。

  网络接口层:对实际的网络媒体的管理,定义如何使用实际网络(如Ethernet、Serial Line等)来传送数据。

TCP/IP中的协议

  以下简单介绍TCP/IP中的协议都具备什么样的功能,都是如何工作的:

  1. IP

  网际协议IP是TCP/IP的心脏,也是网络层中最重要的协议。

  IP层接收由更低层(网络接口层例如以太网设备驱动程序)发来的数据包,并把该数据包发送到更高层---TCP或UDP层;相反,IP层也把从TCP或UDP层接收来的数据包传送到更低层。IP数据包是不可靠的,因为IP并没有做任何事情来确认数据包是按顺序发送的或者没有被破坏。IP数据包中含有发送它的主机的地址(源地址)和接收它的主机的地址(目的地址)。

  高层的TCP和UDP服务在接收数据包时,通常假设包中的源地址是有效的。也可以这样说,IP地址形成了许多服务的认证基础,这些服务相信数据包是从一个有效的主机发送来的。IP确认包含一个选项,叫作IP source routing,可以用来指定一条源地址和目的地址之间的直接路径。对于一些TCP和UDP的服务来说,使用了该选项的IP包好象是从路径上的最后一个系统传递过来的,而不是来自于它的真实地点。这个选项是为了测试而存在的,说明了它可以被用来欺骗系统来进行平常是被禁止的连接。那么,许多依靠IP源地址做确认的服务将产生问题并且会被非法入侵。

  2. TCP

  如果IP数据包中有已经封好的TCP数据包,那么IP将把它们向‘上’传送到TCP层。TCP将包排序并进行错误检查,同时实现虚电路间的连接。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。

  TCP将它的信息送到更高层的应用程序,例如Telnet的服务程序和客户程序。应用程序轮流将信息送回TCP层,TCP层便将它们向下传送到IP层,设备驱动程序和物理介质,最后到接收方。

  面向连接的服务(例如Telnet、FTP、rlogin、X Windows和SMTP)需要高度的可靠性,所以它们使用了TCP。DNS在某些情况下使用TCP(发送和接收域名数据库),但使用UDP传送有关单个主机的信息。

  3.UDP

  UDP与TCP位于同一层,但对于数据包的顺序错误或重发。因此,UDP不被应用于那些使用虚电路的面向连接的服务,UDP主要用于那些面向查询---应答的服务,例如NFS。相对于FTP或Telnet,这些服务需要交换的信息量较小。使用UDP的服务包括NTP(网落时间协议)和DNS(DNS也使用TCP)。

  欺骗UDP包比欺骗TCP包更容易,因为UDP没有建立初始化连接(也可以称为握手)(因为在两个系统间没有虚电路),也就是说,与UDP相关的服务面临着更大的危险。

  4.ICMP

  ICMP与IP位于同一层,它被用来传送IP的的控制信息。它主要是用来提供有关通向目的地址的路径信息。ICMP的‘Redirect’信息通知主机通向其他系统的更准确的路径,而‘Unreachable’信息则指出路径有问题。另外,如果路径不可用了,ICMP可以使TCP连接‘体面地’终止。PING是最常用的基于ICMP的服务。

  5. TCP和UDP的端口结构

  TCP和UDP服务通常有一个客户/服务器的关系,例如,一个Telnet服务进程开始在系统上处于空闲状态,等待着连接。用户使用Telnet客户程序与服务进程建立一个连接。客户程序向服务进程写入信息,服务进程读出信息并发出响应,客户程序读出响应并向用户报告。因而,这个连接是双工的,可以用来进行读写。

  两个系统间的多重Telnet连接是如何相互确认并协调一致呢?TCP或UDP连接唯一地使用每个信息中的如下四项进行确认:

  源IP地址  发送包的IP地址。

  目的IP地址 接收包的IP地址。

  源端口   源系统上的连接的端口。

  目的端口  目的系统上的连接的端口。

  端口是一个软件结构,被客户程序或服务进程用来发送和接收信息。一个端口对应一个16比特的数。服务进程通常使用一个固定的端口,例如,SMTP使用25、Xwindows使用6000。这些端口号是‘广为人知’的,因为在建立与特定的主机或服务的连接时,需要这些地址和目的地址进行通讯。


posted @ 2006-02-15 11:13 Ben 阅读(1384) | 评论 (0)编辑 收藏

RSS知识简介:什么是RSS以及RSS的历史及发展历程

[转]www.rising.com.cn  2005-4-11 16:37:00  信息源:瑞星编译
广告  

    一、什么是RSS?

    也许大家是第一次听到RSS这个概念,那什么是RSS呢?RSS是站点用来和其他站点之间共享内容的一种简易方式(也叫聚合内容),通常被用于新闻和其他按顺序排列的网站,例如Blog。一段项目的介绍可能包含新闻的全部介绍等。或者仅仅是额外的内容或者简短的介绍。这些项目的链接通常都能链接到全部的内容。网络用户可以在客户端借助于支持RSS的新闻聚合工具软件,在不打开网站内容页面的情况下阅读支持RSS输出的网站内容。

    说得更加简单一点,RSS就是一种用来分发和汇集网页内容的XML格式!如果你还是不太明白,没有关系,RSS是什么其实基本就不重要,重要的是RSS可以做什么,下面我们就来了解一下,RSS能给我们带来什么?

    小知识

    BLOG:BLOG是Web Log的简称。在国内,人们通常称它为博客。它是一种作者与读者以日记风格进行交互的中介。在软件社区,人们以博客形式来共享观念与思想变得越来越流行,人们开始以博客的形式互相学习,博客已经成了一个技术交流的场所!如:http://blogs.msdn.com 就是MSDN上的一个blogging。而在国内博客中国也已经越来越有名。http://www.blogchina.com。

    XML:XML是Extensible Markup Language的简写,一种扩展性标识语言。

    二、RSS的历史

    那么RSS究竟代表什么呢?比较普遍的有两种说法,一种是“Rich Site Summary”或“RDF Site Summary”,另一种是“Really Simple Syndication”,之所以有这些分歧,需要从RSS发展的历史说起。

    最初的0.90版本RSS是由Netscape公司设计的,目的是用来建立一个整合了各主要新闻站点内容的门户,但是0.90版本的RSS规范过于复杂,而一个简化的RSS 0.91版本也随着Netscape公司对该项目的放弃而于2000年暂停。

    不久,一家专门从事博客写作软件开发的公司UserLand接手了RSS 0.91版本的发展,并把它作为其博客写作软件的基础功能之一继续开发,逐步推出了0.92、0.93和0.94版本。随着网络博客的流行,RSS作为一种基本的功能也被越来越多的网站和博客软件支持。

    在UserLand公司接手并不断开发RSS的同时,很多的专业人士认识到需要通过一个第三方、非商业的组织,把RSS发展成为一个通用的规范,并进一步标准化。于是2001年一个联合小组在0.90版本RSS的开发原则下,以W3C新一代的语义网技术RDF(Resource Description Framework)为基础,对RSS进行了重新定义,发布RSS1.0,并将RSS定义为“RDF Site Summary”。但是这项工作没有与UserLand公司进行有效的沟通,UserLand公司也不承认RSS 1.0的有效性,并坚持按照自己的设想进一步开发出RSS的后续版本,到2002年9月发布了最新版本RSS 2.0,UserLand公司将RSS定义为“Really Simple Syndication”。

    目前RSS已经分化为RSS 0.9x/2.0和RSS 1.0两个阵营,由于分歧的存在和RSS 0.9x/2.0的广泛应用现状,RSS 1.0还没有成为标准化组织的真正标准。

    三、RSS可以干什么?

    1.订阅BLOG(BLOG上,你可以订阅你工作中所需的技术文章;也可以订阅与你有共同爱好的作者的日志,总之,BLOG上你对什么感兴趣你就可以订什么)

    2.订阅新闻(无论是奇闻怪事、明星消息、体坛风云,只要你想知道的,都可以订阅)

    你再也不用一个网站一个网站,一个网页一个网页去逛了。只要这将你需要的内容订阅在一个RSS阅读器中,这些内容就会自动出现你的阅读器里,你也不必为了一个急切想知道的消息而不断的刷新网页,因为一旦有了更新,RSS阅读器就会自己通知你!

    三、RSS阅读器

    目前,RSS阅读器基本可以分为两类。

    第一类大多数阅读器是运行在计算机桌面上的单机应用程序,通过所订阅网站和博客(blog)中的新闻供应,可自动、定时地更新新闻标题。在该类阅读器中,有Awasu、FeedDemon和RSSReader这三款流行的单机版阅读器都提供免费试用版和付费高级版,另外,新华网在不久前也推出了一款RSS阅读器,它不仅是完全是中文界面,而且目前还是完全的免费软件!(后面我们就将以这款软件为例,为大家介绍怎样来使用RSS阅读器)

    第二类新闻阅读器通常是内嵌于已在计算机中运行的应用程序中。例如,NewsGator内嵌在微软的Outlook中,所订阅的新闻标题位于Outlook的收件箱文件夹中。另外,Pluck内嵌在Internet Explorer浏览器中!

    四、RSS的联合(Syndication)和聚合(Aggregation)

    发布一个RSS文件(一般称为RSS Feed)后,这个RSS Feed中包含的信息就能直接被其他站点调用,而且由于这些数据都是标准的XML格式,所以也能在其他的终端和服务中使用,如PDA、手机、邮件列表等。而且一个网站联盟(比如专门讨论旅游的网站系列)也能通过互相调用彼此的RSS Feed,自动的显示网站联盟中其他站点上的最新信息,这就叫着RSS的联合。这种联合就导致一个站点的内容更新越及时、RSS Feed被调用的越多,该站点的知名度就会越高,从而形成一种良性循环。

    而所谓RSS聚合,就是通过软件工具的方法从网络上搜集各种RSS Feed并在一个界面中提供给读者进行阅读。这些软件可以是在线的WEB工具,如http://my.netscape.com ,http://my.userland.com , http://www.xmltree.com ,http://www.moreover.com ,http://www.oreillynet.com/meerkat 等,也可以是下载到客户端安装的工具

    五、RSS的未来发展

    随着越来越多的站点对RSS的支持,RSS已经成为目前最成功的XML应用。RSS搭建了信息迅速传播的一个技术平台,使得每个人都成为潜在的信息提供者。相信很快我们就会看到大量基于RSS的专业门户、聚合站点和更精确的搜索引擎。

posted @ 2006-02-14 08:46 Ben 阅读(171) | 评论 (0)编辑 收藏

有关webservice的一些介绍和调用方法

     摘要: [转]http://www.54bk.com/user1/8454/archives/2005/26611.html1. 什么是webservice   从表面上看,Web service 就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API。这就是说,你能够用编程的方法通过Web来调用这个应用程序。   对Web service 更精确的解释: Web services是建立可...  阅读全文

posted @ 2006-02-13 16:51 Ben 阅读(646) | 评论 (0)编辑 收藏

[转]使用XML的五种场合

使用XML的五种场合
主  题:  使用XML的五种场合[精华] 
作  者:  ChinaOk (蓝蝶[授人以鱼,不如授人以渔]) 
等  级: 
信 誉 值:  103 
所属论坛:  XML/SOAP 
问题点数:  1 
回复次数:  76 
发表时间:  2002-4-8 16:54:32 
在很多研讨会和培训班上我遇到过许多人,他们还不明白为什么要使用XML也不知道如何 
在他们的应用中使用XML。一些来自诸如Gartner公司的报告建议说,商业公司不能再做 
局外人了,不能对XML置之不理。如果你还不清楚XML到底有什么好处的话,你并不是唯 
一的人。 
我决定把与人们和媒体关于XML话题的交谈整理成文,列出XML在应用中的五个最令人喜 
爱的用法。尽管这些并不能包含XML的所有潜在应用,至少是些最重要的领域。 
1、数据交换 
用XML在应用程序和公司之间作数据交换已不是什么秘密了,毫无疑问应被列为第一位。 
那么为什么XML在这个领域里的地位这么重要呢?原因就是XML使用元素和属性来描述数 
据。在数据传送过程中,XML始终保留了诸如父/子关系这样的数据结构。几个应用程序 
可以共享和解析同一个XML文件,不必使用传统的字符串解析或拆解过程。 
相反,普通文件不对每个数据段做描述(除了在头文件中),也不保留数据关系结构。使 
用XML做数据交换可以使应用程序更具有弹性,因为可以用位置(与普通文件一样)或用元 
素名(从数据库)来存取XML数据。 
2、Web服务 
Web服务是最令人激动的革命之一,它让使用不同系统和不同编程语言的人们能够相互交 
流和分享数据。其基础在于Web服务器用XML在系统之间交换数据。交换数据通常用XML标 
记,能使协议取得规范一致,比如在简单对象处理协议(Simple Object Access Protoc 
ol, SOAP)平台上。 
SOAP可以在用不同编程语言构造的对象之间传递消息。这意味着一个C#对象能够与一个 
Java对象进行通讯。这种通讯甚至可以发生在运行于不同操作系统上的对象之间。DCOM 
, CORBA或Java RMI只能在紧密耦合的对象之间传递消息,SOAP则可在松耦合对象之间传 
递消息。 
3、内容管理 
XML只用元素和属性来描述数据,而不提供数据的显示方法。这样,XML就提供了一个优 
秀的方法来标记独立于平台和语言的内容。 
使用象XSLT这样的语言能够轻易地将XML文件转换成各种格式文件,比如HTML, WML, PD 
F, flat file, EDI, 等等。XML具有的能够运行于不同系统平台之间和转换成不同格式 
目标文件的能力使得它成为内容管理应用系统中的优秀选择。  
4、Web集成 
现在有越来越多的设备也支持XML了。使得Web开发商可以在个人电子助理和浏览器之间 
用XML来传递数据。 
为什么将XML文本直接送进这样的设备去呢?这样作的目的是让用户更多地自己掌握数据 
显示方式,更能体验到实践的快乐。常规的客户/服务(C/S)方式为了获得数据排序或更 
换显示格式,必须向服务器发出申请;而XML则可以直接处理数据,不必经过向服务器申 
请查询-返回结果这样的双向“旅程”,同时在设备也不需要配制数据库。 
甚至还可以对设备上的XML文件进行修改并将结果返回给服务器。想像一下,一台具有互 
联网功能并支持XML的电冰箱将会给市场带来多么大的冲击吧。你从此不必早起去取牛奶 
了! 
5、配制 
许多应用都将配制数据存储在各种文件里,比如.INI文件。虽然这样的文件格式已经使 
用多年并一直很好用,但是XML还是以更为优秀的方式为应用程序标记配制数据。使用. 
NET里的类,如XmlDocument和XmlTextReader,将配制数据标记为XML格式,能使其更具 
可读性,并能方便地集成到应用系统中去。使用XML配制文件的应用程序能够方便地处理 
所需数据,不用象其他应用那样要经过重新编译才能修改和维护应用系统。 
如前所述,这里提到的五种使用XML的途径不包括全部场合。

posted @ 2006-01-11 16:40 Ben 阅读(403) | 评论 (0)编辑 收藏

[转贴]使用jsp实现word、excel格式报表打印

使用jsp实现word、excel格式报表打印
转载 (evan 原创)
 

title: 使用JSP实现WORD、EXCEL格式报表打印

author: evan

email: maioto:evan_zhao@hotmail.com

date: 2003-08-21


因为ms word和excel的文档都支持html文本格式,因此可以先用word或excel做好模版,另存为Web页,然后将该html改成jsp,将数据部分动态填入即可,不用很辛苦的调整格式
 
word页面只要在jsp头设置如下指令:
<%@page contentType="application/msword;charset=GBK" %>
 
excel如下:
<%@page contentType="application/vnd.ms-excel;charset=GBK" %>

使用这种方式客户端必须安装有office软件,用户访问时将在ie中直接用word或excel打开该页面。

此方法优势是模板设计、调整方便,无需在服务器端使用复杂的POI或jxl技术,也无需在客户端使用ActiveX控件技术,更安全、方便,轻松实现较好的打印效果。 

microsoft关于服务器端动态创建office文档的资料(asp示例): 
http://support.microsoft.com/default.aspx?scid=KB;en-us;301044&
 
简单示例:

使用word建立一文档,画表格如下:
----------------------------
| 用户名 | 真实姓名 | 性别 |
----------------------------
| guest  | 路人甲   | 男   |
----------------------------
保存为Web页test.htm, 将test.htm改名为test.jsp,修改其中guest、路人甲、男为从数据库动态查询,如下:

<%@ page contentType="application/msword;charset=GBK" %>
<%@ page import="java.sql.*" %>
<html xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:w="urn:schemas-microsoft-com:office:word"
xmlns="http://www.w3.org/TR/REC-html40">

<head>
<meta http-equiv=Content-Type content="text/html; charset=GB2312">
<meta name=ProgId content=Word.Document>
<meta name=Generator content="Microsoft Word 9">
<meta name=Originator content="Microsoft Word 9">
<title>用户信息</title>
<!--[if gte mso 9]><xml>
 <o:DocumentProperties>
  <o:Author>evan zhao</o:Author>
  <o:LastAuthor>evan zhao</o:LastAuthor>
  <o:Revision>1</o:Revision>
  <o:TotalTime>1</o:TotalTime>
  <o:Created>2003-08-20T16:26:00Z</o:Created>
  <o:LastSaved>2003-08-20T16:27:00Z</o:LastSaved>
  <o:Pages>1</o:Pages>
  <o:Company>taiping</o:Company>
  <o:Lines>1</o:Lines>
  <o:Paragraphs>1</o:Paragraphs>
  <o:Version>9.2812</o:Version>
 </o:DocumentProperties>
</xml><![endif]--><!--[if gte mso 9]><xml>
 <w:WordDocument>
  <w:PunctuationKerning>
  <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
  <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
  <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
  <w:Compatibility>
   <w:SpaceForUL>
   <w:BalanceSingleByteDoubleByteWidth>
   <w:DoNotLeaveBackslashAlone>
   <w:ULTrailSpace>
   <w:DoNotExpandShiftReturn>
   <w:AdjustLineHeightInTable>
   <w:UseFELayout>
  </w:Compatibility>
 </w:WordDocument>
</xml><![endif]-->
<style>
<!--
 /* Font Definitions */
@font-face
    {font-family:宋体;
    panose-1:2 1 6 0 3 1 1 1 1 1;
    mso-font-alt:SimSun;
    mso-font-charset:134;
    mso-generic-font-family:auto;
    mso-font-pitch:variable;
    mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
    {font-family:"\@宋体";
    panose-1:2 1 6 0 3 1 1 1 1 1;
    mso-font-charset:134;
    mso-generic-font-family:auto;
    mso-font-pitch:variable;
    mso-font-signature:3 135135232 16 0 262145 0;}
 /* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
    {mso-style-parent:"";
    margin:0cm;
    margin-bottom:.0001pt;
    text-align:justify;
    text-justify:inter-ideograph;
    mso-pagination:none;
    font-size:10.5pt;
    mso-bidi-font-size:12.0pt;
    font-family:"Times New Roman";
    mso-fareast-font-family:宋体;
    mso-font-kerning:1.0pt;}
 /* Page Definitions */
@page
    {mso-page-border-surround-header:no;
    mso-page-border-surround-footer:no;}
@page Section1
    {size:595.3pt 841.9pt;
    margin:72.0pt 90.0pt 72.0pt 90.0pt;
    mso-header-margin:42.55pt;
    mso-footer-margin:49.6pt;
    mso-paper-source:0;
    layout-grid:15.6pt;}
div.Section1
    {page:Section1;}
-->
</style>
</head>

<body lang=ZH-CN style='tab-interval:21.0pt;text-justify-trim:punctuation'>

<div class=Section1 style='layout-grid:15.6pt'>


<table border=1 cellspacing=0 cellpadding=0 style='border-collapse:collapse;
 border:none;mso-border-alt:solid windowtext .5pt;mso-padding-alt:0cm 5.4pt 0cm 5.4pt'>
 <tr>
  <td width=189 valign=top style='width:142.0pt;border:solid windowtext .5pt;
  padding:0cm 5.4pt 0cm 5.4pt'>
  <p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
  mso-hansi-font-family:"Times New Roman"'>用户名</span></p>
  </td>
  <td width=189 valign=top style='width:142.05pt;border:solid windowtext .5pt;
  border-left:none;mso-border-left-alt:solid windowtext .5pt;padding:0cm 5.4pt 0cm 5.4pt'>
  <p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
  mso-hansi-font-family:"Times New Roman"'>真实姓名</span></p>
  </td>
  <td width=189 valign=top style='width:142.05pt;border:solid windowtext .5pt;
  border-left:none;mso-border-left-alt:solid windowtext .5pt;padding:0cm 5.4pt 0cm 5.4pt'>
  <p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
  mso-hansi-font-family:"Times New Roman"'>性别</span></p>
  </td>
 </tr>
<%
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); 

String url="jdbc:odbc:mydb";

//连接mydb数据库
Connection con=DriverManager.getConnection (url, "", ""); 

try{
  Statement stmt=con.createStatement(); 

  //查询employee表
  ResultSet rs=stmt.executeQuery("select user_name, real_name, gender from employee ");

  while(rs.next()){
%>

 <tr>
  <td width=189 valign=top style='width:142.0pt;border:solid windowtext .5pt;
  border-top:none;mso-border-top-alt:solid windowtext .5pt;padding:0cm 5.4pt 0cm 5.4pt'>
  <p class=MsoNormal><span lang=EN-US><%=rs.getString("user_name")%></span></p>
  </td>
  <td width=189 valign=top style='width:142.05pt;border-top:none;border-left:
  none;border-bottom:solid windowtext .5pt;border-right:solid windowtext .5pt;
  mso-border-top-alt:solid windowtext .5pt;mso-border-left-alt:solid windowtext .5pt;
  padding:0cm 5.4pt 0cm 5.4pt'>
  <p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
  mso-hansi-font-family:"Times New Roman"'><%=rs.getString("real_name")%></span></p>
  </td>
  <td width=189 valign=top style='width:142.05pt;border-top:none;border-left:
  none;border-bottom:solid windowtext .5pt;border-right:solid windowtext .5pt;
  mso-border-top-alt:solid windowtext .5pt;mso-border-left-alt:solid windowtext .5pt;
  padding:0cm 5.4pt 0cm 5.4pt'>
  <p class=MsoNormal><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
  mso-hansi-font-family:"Times New Roman"'><%=rs.getString("gender")%></span></p>
  </td>
 </tr>

<%
  } // end while
  
  rs.close();
  stmt.close();
} finally {
  con.close();
}
%> 
 
</table>

<p class=MsoNormal><span lang=EN-US><![if !supportEmptyParas]> <![endif]><o:p></o:p></span></p>

</div>

</body>

</html>

posted @ 2006-01-05 20:00 Ben 阅读(436) | 评论 (0)编辑 收藏

[转帖]XML轻松学习手册


转载自:http://www.knowsky.com/2991.html

XML轻松学习手册(1)XML快速入门

文章类别:XML教程   发表日期:2003-6-3  星期二  
--------------------------------------------------------------------------------
转自:动态网制作指南 www.knowsky.com
前言

XML越来越热,关于XML的基础教程网络上也随处可见。可是一大堆的概念和术语往往让人望而生畏,很多朋友问我:XML到底有什么用,我们是否需要学习它?我想就我个人学习过程的心得和经验,写一篇比较全面的介绍文章。首先有两点是需要肯定的: 

第一:XML肯定是未来的发展趋势,不论是网页设计师还是网络程序员,都应该及时学习和了解,等待只会让你失去机会; 

第二:新知识肯定会有很多新概念,尝试理解和接受,您才可能提高。不要害怕和逃避,毕竟我们还年轻。 

提纲

本文共分五大部分。分别是XML快速入门,XML的概念,XML的术语,XML的实现,XML的实例分析。最后附录介绍了XML的相关资源。作者站在普通网页设计人员的角度,用平实生动的语言,向您讲述XML的方方面面,帮助你拨开XML的神秘面纱,快速步入XML的新领域。 

第一章:XML快速入门

一. 什么是XML? 

二. XML是新概念吗? 

三. 使用XML有什么好处? 

四. XML很难学吗? 

五. XML和HTML的区别 

六. XML的严格格式 

七. 关于XML的更多 

一. 什么是XML?

 

这往往是第一个问题,也往往在第一个问题上你就会搞不明白,因为大多的教材上这样回答:

XML是Extensible Markup Language的简写,一种扩展性标识语言。 这是标准的定义。那么什么是标志语言,为什么叫扩展性?已经让人有些糊涂。我想我们这样来理解会好一些:

对HTML你已经非常熟悉了吧,它就是一种标记语言,记得它的全称吗:"Hypertext Markup Language" 超文本标记语言。明白了?同时,HTML里面有很多标签,类似,等,都是在HTML 
4.0里规范和定义,而XML里允许你自己创建这样的标签,所以叫做可扩展性。

这里有几个容易混淆的概念要提醒大家:

1.XML并不是标记语言。它只是用来创造标记语言(比如HTML)的元语言。天,又糊涂了!不要紧,你只要知道这一点:XML和HTML是不一样的,它的用处途比HTML广泛得多,我们将在后面仔细介绍。

2.XML并不是HTML的替代产品。XML不是HTML的升级,它只是HTML的补充,为HTML扩展更多功能。我们仍将在较长的一段时间里继续使用HTML。(但值得注意的是HTML的升级版本XHTML的确正在向适应XML靠拢。)

3.不能用XML来直接写网页。即便是包含了XML数据,依然要转换成HTML格式才能在浏览器上显示。

下面就是一段XML示例文档(例1),用来表示本文的信息:

<myfile>

<title>XML Quick Start</title>

<author>ajie</author>

<email>ajie@aolhoo.com</email>

<date>20010115</date>

</myfile> 

 

注意:

 

1.这段代码仅仅是代码,让你初步感性认识一下XML,并不能实现什么具体应用;

2.其中类似< title>,< author>的语句就是自己创建的标记(tags),它们和HTML标记不一样,例如这里的< title>是文章标题的意思,HTML里的< title>是页面标题。

二. XML是新概念吗? 

不是。XML来源于SGML,一种比HTML更早的标志语言标准。 

关于SGML,我们来简单了解一下,你只需要有个大致概念就可以。 

SGML全称是"Standard Generalized Markup Language"(通用标识语言标准)。看名称就知道:它是标志语言的标准,也就是说所有标志语言都是依照SGML制定的,当然包括HTML。SGML的覆盖面很广,凡是有一定格式的文件都属于SGML,比如报告,乐谱等等,HTML是SGML在网络上最常见的文件格式。因此,人们戏称SGML是HTML的"妈妈"。 


而XML就是SGML的简化版,只不过省略了其中复杂和不常用的部分。(哦,明白了!是HTML第二个"mother",难怪比HTML功能强大呢。),和SGML一样,XML也可以应用在金融,科研等各个领域,我们这里讲的,只是XML在web方面的运用而已。 


到这里,你应该有点明白了:XML是用来创建定义类似HTML的标记语言,然后再用这个标记语言来显示信息。 三. 使用XML有什么好处? 

有了HTML,为什么还需要用XML? 

因为现在网络应用越来越广泛,仅仅靠HTML单一文件类型来处理千变万化的文档和数据已经力不丛心,而且HTML本身语法十分不严密,严重影响网络信息传送和共享。(想想浏览器兼容的问题伤透多少设计师的脑细胞啊。)人们早已经开始探讨用什么方法来满足网络上各种应用的需要。使用SGML是可以的,但SGML太庞大,编程复杂,于是最终选择了"减肥"的SGML---XML作为下一代web运用的数据传输和交互的工具。 


使用XML有什么好处?来看w3c组织(XML标准制定者)的说明: 

XML使得在网络上使用SGML语言更加"简单和直接": 简化了定义文件类型的过程,简化了编程和处理SGML文件的过程,简化了在Web上的传送和共享。 


1.XML可以广泛的运用于web的任何地方; 

2.XML可以满足网络应用的需求; 

3.使用XML将使编程更加简单; 

4.XML便于学习和创建; 

5.XML代码将清晰和便于阅读理解; 

还是抽象了些。让我们在后面的实例教程中慢满体会XML的强大优势吧! 

四. XML很难学吗?

如果你有兴趣学习XML,不禁会问:XML难吗?学习XML需要什么样的基础?

XML非常简单,学习容易。如果你熟悉HTML,你会发现它的文档和HTML非常相似,看同样的示例文档(例1):

?xml version="1.0"?>

<myfile>

<title>XML Quick Start</title>

<author>ajie</author>

<email>ajie@aolhoo.com</email>

<date>20010115</date>

</myfile>

第一行是一个XML声明,表示文档遵循的是XML的1.0 版的规范。

第二行定义了文档里面的第一个元素(element),也称为根元素: < myfile>。这个就类似HTML里的< HTML>开头标记。注意,这个名称是自己随便定义的。

再下面定义了四个子元素:title,author,email,和date。分别说明文章的标题,作者,邮箱和日期。当然,你可以用中文来定义这些标签,看上去更便于理解: 
<?xml version="1.0" encoding="GB2312"?>

<文章>

<标题>XML轻松学习手册</标题>

<作者>ajie</作者>

<信箱>ajie@aolhoo.com</信箱>

<日期>20010115</日期>

</文章>

 

这就是XML的文档,任何掌握HTML的网友都可以直接写出这样简单的XML文档。

另外,学习XML还必须掌握一种页面脚本语言,常见的就是javascript和VB script。因为XML数据是使用script实现HTML中调用和交互的。我们看一个最简单的例子(例2):

1.将下面代码存为myfile.htm


<html>

<head>

<script language="javascript" for="window" event="onload">

var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");

xmlDoc.async="false";

xmlDoc.load("myfile.xml");

nodes = xmlDoc.documentElement.childNodes;

title.innerText = nodesitem(0).text;

author.innerText = nodes.item(1).text;

email.innerText = nodes.item(2).text;

date.innerText = nodes.item(3).text;

</script>

<title>在HTML中调用XML数据</title>

</head>

<body bgcolor="#FFFFFF">

<b>标题: </b>

<span id="title"> </span>

<b>作者: </b>>

<span id="author"></span>

<b>信箱: </b>

<span id="email"></span>

<b>日期:</b>

<span id="date"></span>

</body>

</html>


2.将下面代码存为myfile.xml


<?xml version="1.0" encoding="GB2312"?>

<myfile>

<title>XML轻松学习手册</title>

<author>ajie</author>

<email>ajie@aolhoo.com</email>

<date>20010115</date>

</myfile>


3.将它们放在同一个目录下,用IE5以上版本浏览器打开,可以看到效果。 学习并掌握一种script,你将真正了解到XML无比的强大的功能。

五. XML和HTML的区别 

 

XML和HTML都来自于SGML,它们都含有标记,有着相似的语法,HTML和XML的最大区别在于:HTML是一个定型的标记语言,它用固有的标记来描述,显示网页内容。比如< H1>表示首行标题,有固定的尺寸。相对的,XML则没有固定的标记,XML不能描述网页具体的外观,内容,它只是描述内容的数据形式和结构。 

 


这是一个质的区别:网页将数据和显示混在一起,而XML则将数据和显示分开来。 

 

我们看上面的例子,在myfile.htm中,我们只关心页面的显示方式,我们可以设计不同的界面,用不同的方式来排版页面,但数据是储存在myfile.xml中,不需要任何改变。 

 


(如果你是程序员,你会惊讶的发现,这与模块化面向对象编程的思想极其相似!其实网页何尝不是一种程序呢?) 

 

正是这种区别使得XML在网络应用和信息共享上方便,高效,可扩展。所以我们相信,XML做为一种先进的数据处理方法,将使网络跨越到一个新的境界。

 

六. XML的严格格式

 

吸取HTML松散格式带来的经验教训,XML一开始就坚持实行"良好的格式"。

我们先看HTML的一些语句,这些语句在HTML中随处可见:

1.

sample


2.< b>< i>sample< /b>< /i>


3.< td>sample< /TD>


4.< font color=red>samplar< /font>


在XML文档中,上述几种语句的语法都是错误的。因为:

1.所有的标记都必须要有一个相应的结束标记;

2.所有的XML标记都必须合理嵌套;

3.所有XML标记都区分大小写;

4.所有标记的属性必须用""括起来;

所以上列语句在XML中正确的写法是

1.
sample

2.< b>< i>sample< /i>< /b>
3.< td>sample< /td>
4.< font color="red">samplar< /font>

  另外,XML标记必须遵循下面的命名规则:

1.名字中可以包含字母、数字以及其它字母; 

2.名字不能以数字或"_" (下划线) 开头;

3.名字不能以字母 xml (或 XML 或 Xml ..) 开头;

4.名字中不能包含空格。

在XML文档中任何的差错,都会得到同一个结果:网页不能被显示。各浏览器开发商已经达成协议,对XML实行严格而挑剔的解析,任何细小的错误都会被报告。你可以将上面的myfile.xml修改一下,比如将< email>改为< Email>,然后用IE5直接打开myfile.xml,会得到一个出错信息页面:


<?xml version="1.0" encoding="GB2312"?>

<myfile>

<title>XML轻松学习手册</title>

<author>ajie</author>

<Email>ajie@aolhoo.com</email>

<date>20010115</date>

</myfile> 

七. 关于XML的更多 

好了,到现在你已经知道: 

1.什么是XML; 
2.XML,HTML,SGML之间的关系和区别; 
3.XML的简单应用。 

恭喜你!你已经不再对XML一无所知,并且已经走在了网络技术的前沿。整个学习过程好象并不很难哦:) 

如果你对XML有更多的兴趣,希望进一步了解XML的详细资料和其它的实际运用技术,欢迎继续浏览我们的下一章:XML的概念。
 
XML轻松学习手册(2)XML概念

第二章 XML概念

导言 

经过第一章的快速入门学习,你已经知道了XML是一种能够让你自己创造标识的语言,它可以将数据与格式从网页中分开,它可以储存数据和共享数据的特性使得XML无所不能。如果你希望深入学习XML,系统掌握XML的来龙去脉,那么我们首先还是要回到XML概念的问题上来。XML(Extensible Markup Language),一种扩展性标识语言。"扩展性""标识""语言"。每一个词都明确的点明了XML的重要特点和功能。我们来仔细分析: 

一. 扩展性 
二. 标识 
三. 语言 
四. 结构化 
五. Meta数据 
六. 显示 
七. DOM 

一.扩展性---使用XML,你可以为你的文档建立自己的标记(tags)。 

XML的第一个词是"扩展性",这正是XML强大的功能和弹性的原因。 
在HTML里,有许多固定的标记,我们必须记住然后使用它们,你不能使用HTML规范里没有的标记。而在XML中,你能建立任何你需要的标记。你可以充分发挥你的想象力,给你的文档起一些好记的标记名称。比如,你的文档里包含一些游戏的攻略,你可以建立一个名为<game>的标记,然后在<game>下再根据游戏类别建立<RPG>,<SLG>等标记。只要清晰,易于理解你可以建立任何数量的标记。 

一开始你也许会不适应,因为我们在学习HTML时,有固定的标记可以直接学习和使用;(很多人包括我自己都是边分析别人的代码和标识,边建立自己的网页),而XML却没有任何标记可以学,也很少有文档的标记是一模一样的。我们怎么办?呵呵,没有就自己创建呀。一旦你真正开始写XML文档,你会发现随心所欲的创造新标记也是一份很有趣的事。你可以建立有自己特色的标记,甚至建立你自己的HTML语言。 

扩展性使你有更多的选择和强大的能力,但同时也产生一个问题就是你必须学会规划。你自己要理解自己的文档,知道它由哪几部分组成,相互之间的关系和如何识别它们。 

关于建立标识还需要说明一点,标识是描述数据的类型或特性,比如<width>,年龄<age>,姓名<name>等,而不是数据的内容,比如:<10pxl>,<18>,<张三>,这些都是无用的标记。如果你学过数据库,你可以这样理解,标识就是一种字段名。 

二.标识---使用XML你可以识别文档中的元素。 

XML的第二个词是"标识",这表明了XML的目的是标识文档中的元素。 

不论你是HTML,还是XML,标识的本质在于便于理解,如果没有标识,你的文档在计算机看来只是一个很长的字符串,每个字看起来都一样,没有重点之分。 

通过标识,你的文档才便于阅读和理解,你可以划分段落,列明标题。XML中,你更可以利用其扩展性 来为文档建立更合适的标识。 

不过,有一点要提醒大家注意:标识仅仅是用来识别信息,它本身并不传达信息。例如这样的HTML代码: 

<b>frist step<b> 
这里<b>表示粗体,只用来说明是用粗体来显示"frist step"字符,<b>本身并不包含任何实际的信息,在页面上你看不到<b>,真正传达信息的是"frist step "。 

三.语言---使用XML你要遵循特定的语法来标识你的文档。 

XML第三个词是"语言"。这表明了作为一种语言XML必须遵循一定的规则。虽然XML的扩展性允许你创建新标识,但它仍然必须遵循特定的结构,语法和明确的定义。 

在计算机领域,语言常常表示一?quot;程序语言",用来编程实现一些功能和应用,但不是所有的"语言"都是用来编程的,XML就只是一种用来定义标识和描述信息的语言。 

下面我们来深入了解一下XML应用的其本原理,可能会很枯燥,但是对于整体的理解很重要,你可以先快速过一遍,心里有一个模糊的概念,具体精髓则需要在实践中慢慢领会。

四.结构化---XML促使文档结构化,所有的信息按某种关系排列。 

"结构化"听起来太抽象了,我们这样理解,结构化就是为你的文档建立一个框架,就象写文章先写一个提纲。结构化使你的文档看起来不会杂乱无章,每一部分都紧密联系,形成一个整体。 

结构化有两个原则: 
1.每一部分(每一个元素)都和其他元素有关联。关联的级数就形成了结构。 
2.标识本身的含义与它描述的信息相分离。 

我们来看一个简单的例子帮助理解: 
<?xml version="1.0" encoding="GB2312"?>
<myfile>
<title>XML轻松学习手册</title>
<chapter>XML快速入门
<para>什么是XML</para>
<para>使用XML的好处</para>
</chapter>
<chapter>XML的概念
<para>扩展性</para>
<para>标识</para>
</chapter>
</myfile>
这是本文的XML描述文档,可以看到标识分三级关联,非常清晰: 
<myfile>
<chapter>
<para>
...
</para>
</chapter>
</myfile>
上面这样的文档结构,我们又称之为"文档树",主干是父元素,如<myfile>,分支和页是子元素,如<chapter>和<para>。 

五.Meta数据(Metadata)---专业的XML使用者会使用meta数据来工作。 

在HTML中我们知道可以使用meta标识来定义网页的关键字,简介等,这些标识不会显示在网页中,但可以被搜索引擎搜索到,并影响搜索结果的排列顺序。 

XML对这一原理进行了深化和扩展,用XML,你可以描述你的信息在哪里,你可以通过meta来验证信息,执行搜索,强制显示,或者处理其他的数据。 

下面是一些XML metadata在实际应用中的用途: 

1.可以验证数字签名,使在线商务的提交动作(submission)有效。 
2.可以被方便的建立索引和进行更有效搜索。 
3.可以在不同语言之间传输数据。 

W3C组织正在研究一种名为RDF(Resource Description Framework)的metadata处理方法,可以自动交换信息,W3C宣称,使用RDF配合数字签名,将使网络中存在"真实可信"的电子商务。 

六.显示 

单独用XMl不能显示页面,我们使用格式化技术,比如CSS或者XSL,才能显示XML标记创建的文档。 

我们在前面第一章讲到XML是将数据和格式分离的。XML文档本身不知道如何来显示,必须有辅助文件来帮助实现。(XML取消了所有标识,包括font,color,p等风格样式定义标识,因此XML全部是采用类似DHTML中CSS的方法来定义文档风格样式。),XML中用来设定显示风格样式的文件类型有: 

1.XSL 

XSL全称是Extensible Stylesheet Language(可扩展样式语言), 是将来设计XML文档显示样式的主要文件类型。它本身也是基于XML语言的。使用XSL,你可以灵活的设置文档显示样式,文档将自动适应任何浏览器和PDA(掌上电脑)。 

XSL也可以将XML转化为HTML,那样,老的浏览器也可以浏览XML文档了。 

2.CSS 

CSS大家很熟悉了,全称是Cascading Style Sheets(层叠样式表),是目前用来在浏览器上显示XML文档的主要方法。 

3.Behaviors 

Behaviors现在还没有成为标准。它是微软的IE浏览器特有的功能,用它可以对XML标识设定一些有趣动作。 

七.DOM 

DOM全称是document object model(文档对象模型),DOM是用来干什么的呢?假设把你的文档看成一个单独的对象,DOM就是如何用HTML或者XML对这个对象进行操作和控制的标准。 

面向对象的思想方法已经非常流行了,在编程语言(例如java,js)中,都运用面向对象的编程思想。在XML中,就是要将网页也作为一个对象来操作和控制,我们可以建立自己的对象和模板。与对象进行交流,如何命令对象,就要用到API。API全称Application Programming Interface,它是访问和操作对象的规则。而DOM就是一种详细描述HTML/XML文档对象规则的API。它规定了HTML/XML文档对象的命名协定,程序模型,沟通规则等。在XML文档中,我们可以将每一个标识元素看作一个对象---它有自己的名称和属性。 

XML创建了标识,而DOM的作用就是告诉script如何在浏览器窗口中操作和显示这些标识 

上面我们已经简要的讲述了一些XML的基本原理,我们来看看它们之间的关联以及它们是如何工作的,先看这里一张图:


此主题相关图片如下:

1.XML描述数据类型。例如:"King lear"是一个标题元素; 
2.CSS储存并控制元素的显示样式。例如:标题将被以18pt字体显示 
3.script脚本控制元素如何动作。例如:当一个title元素"out of stock",将被用红色显示。 
4.DOM则为脚本和对象的交流提供一个公共平台,并将结果显示在浏览器窗口。 

如果任何一个部分发生错误,都不会得到正确结果。 

好了,看到这里,我们已经对XML是如何工作的有一个整体的大致的概念。通过这一章的学习,我们可能感觉到XML似乎更偏向数据处理,更方便程序员学习。实际情况也是这样的,XML设计的目的就是用来方便的共享和交互数据的。下一章,我们将系统的了解关于XML的各种术语。欢迎您继续浏览。

XML轻松学习手册(3)XML的术语

第三章 XML的术语

提纲: 


导言 

一.XML文档的有关术语 

二.DTD的有关术语 

导言 


初学XML最令人头疼的就是有一大堆新的术语概念要理解。由于XML本身也是一个崭新的技术,正在不断发展和变化,各组织和各大网络公司(微软,IBM,SUN等)都在不断推出自己的见解和标准,因此新概念漫天飞就不足为奇了。而国内又缺乏权威的机构或组织来对这些术语正式定名,你所看见的有关XML的中文教材大部分是靠作者本身的理解翻译过来的,有些是正确的,有些是错误的,更加妨碍了我们对这些概念的理解和学习。 

你下面将要看到的关于XML术语的解释,也是作者本身的理解和翻译。阿捷是以W3C组织发布的XML1.0标准规范和相关的正式说明文档为根据来讲述。可以确保这些理解是基本正确的,至少不是错误的。你如果想进一步阅读和了解,我在本文的最后部分列明了相关资源的出处和链接,你可以直接访问。好,我们转入正题:

一.XML文档的有关术语

什么是XML文档?知道HTML原代码文件吧,XML文档就是用XML标识写的XML原代码文件。XML文档也是ASCII的纯文本文件,你可以用Notepad创建和修改。XML文档的后缀名为.XML,例如myfile.xml。用IE5.0以上浏览器也可以直接打开.xml文件,但你看到的就是"XML原代码",而不会显示页面内容。你可以将下面代码存为myfile.xml试试:


<?xml version="1.0" encoding="GB2312"?>

<myfile>

<title>XML轻松学习手册</title>

<author>ajie</author>

<email>ajie@aolhoo.com</email>

<date>20010115</date>

</myfile>


XML文档包含三个部分:

1. 一个XML文档声明;

2. 一个关于文档类型的定义;

3. 用XML标识创建的内容。


举例说明:

<?xml version="1.0"?>

<!DOCTYPE filelist SYSTEM "filelist.dtd">

<filelist> 

<myfile>

<title>QUICK START OF XML</title>

<author>ajie</author>

</myfile>

......

</filelist> 

其中第一行<?xml version="1.0"?>就是一个XML文档的声明,第二行说明这个文档是用filelist.dtd来定义文档类型的,第三行以下就是内容主体部分。 
我们来了解XML文档中有关的术语:


1.Element(元素):

元素在HTML我们已经有所了解,它是组成HTML文档的最小单位,在XML中也一样。一个元素由一个标识来定义,包括开始和结束标识以及其中的内容,就象这样:<author>ajie</author> 


唯一不同的就是:在HTML中,标识是固定的,而在XML中,标识需要你自己创建。


2.Tag(标识) 

标识是用来定义元素的。在XML中,标识必须成对出现,将数据包围在中间。标识的名称和元素的名称是一样的。例如这样一个元素:

<author>ajie</author> 

其中<author>就是标识。


3.Attribute(属性): 

什么是属性?看这段HTML代码:<font color="red">word</font>。其中color就是font的属性之一。

属性是对标识进一步的描述和说明,一个标识可以有多个属性,例如font的属性还有size。XML中的属性与HTML中的属性是一样的,每个属性都有它自己的名字和数值,属性是标识的一部分。举例:

<author sex="female">ajie</author>

XML中属性也是自己定义的,我们建议你尽量不使用属性,而将属性改成子元素,例如上面的代码可以改成这样:

<author>ajie

<sex>female</sex>

</author>

原因是属性不易扩充和被程序操作。


4.Declaration(声明) 

在所有XML文档的第一行都有一个XML声明。这个声明表示这个文档是一个XML文档,它遵循的是哪个XML版本的规范。一个XML的声明语句就象这样:

<?xml version="1.0"?> 


5.DTD(文件类型定义) 

DTD是用来定义XML文档中元素,属性以及元素之间关系的。

通过DTD文件可以检测XML文档的结构是否正确。但建立XML文档并不一定需要DTD文件。关于DTD文件的详细说明我们将在下面单独列项。


6.Well-formed XML(良好格式的XML)

一个遵守XML语法规则,并遵守XML规范的文档称之为"良好格式"。如果你所有的标识都严格遵守XML规范,那么你的XML文档就不一定需要DTD文件来定义它。

良好格式的文档必须以一个XML声明开始,例如:

<?xml version="1.0" standalone="yes" encoding="UTF-8"?>

其中你必须说明文档遵守的XML版本,目前是1.0;其次说明文档是"独立的",它不需要DTD文件来验证其中的标识是否有效;第三,要说明文档所使用的语言编码。默认的是UTF-8,如果使用中文,你需要设置为GB2312。

良好格式的XML文档必须有一个根元素,就是紧接着声明后面建立的第一个元素,其它元素都是这个根元素的子元素,属于根元素一组。

良好格式的XML文档的内容书写时必须遵守XML语法。(有关XML语法我们将在下一章仔细讲解)


7.Valid XML(有效的XML)

一个遵守XML语法规则,并遵守相应DTD文件规范的XML文档称为有效的XML文档。注意我们比较"Well-formed XML"和"Valid 
XML",它们最大的差别在于一个完全遵守XML规范,一个则有自己的"文件类型定义(DTD)"。

将XML文档和它的DTD文件进行比较分析,看是否符合DTD规则的过程叫validation(确认)。这样的过程通常我们是通过一个名为parser的软件来处理的。

有效的XML文档也必须以一个XML声明开始,例如:

<?xml version="1.0" standalone="no" encode="UTF-8"?>

和上面例子不同的,在standalone(独立)属性中,这里设置的是"no",因为它必须和相应的DTD一起使用,DTD文件的定义方法如下:

<!DOCTYPE type-of-doc SYSTEM/PUBLIC "dtd-name"> 

其中:

"!DOCTYPE"是指你要定义一个DOCTYPE;

"type-of-doc"是文档类型的名称,由你自己定义,通常于DTD文件名相同;

"SYSTEM/PUBLIC"这两个参数只用其一。SYSTEM是指文档使用的私有DTD文件的网址,而PUBLIC则指文档调用一个公用的DTD文件的网址。

"dtd-name" 就是DTD文件的网址和名称。所有DTD文件的后缀名为".dtd"。

我们还是用上面的例子,应该写成这样:

<?xml version="1.0" standalone="no" encode="UTF-8"?>

<!DOCTYPE filelist SYSTEM "filelist.dtd"> 

二.DTD的有关术语

什么是DTD,我们上面已经简略提到。DTD是一种保证XML文档格式正确的有效方法,可以比较XML文档和DTD文件来看文档是否符合规范,元素和标签使用是否正确。一个DTD文档包含:元素的定义规则,元素间关系的定义规则,元素可使用的属性,可使用的实体或符号规则。

DTD文件也是一个ASCII的文本文件,后缀名为.dtd。例如:myfile.dtd。

为什么要用DTD文件呢?我的理解是它满足了网络共享和数据交互,使用DTD最大的好处在于DTD文件的共享。(就是上文DTD说明语句中的PUBLIC属性)。比如,两个相同行业不同地区的人使用同一个DTD文件来作为文档创建规范,那么他们的数据就很容易交换和共享。网上有其他人想补充数据,也只需要根据公用的DTD规范来建立文档,就立刻可以加入。

目前,已经有数量众多的写好的DTD文件可以利用。针对不同的行业和应用,这些DTD文件已经建立了通用的元素和标签规则。你不需要自己重新创建,只要在他们的基础上加入你需要的新标识。

当然,如果愿意,你可以创建自己的DTD,它可能和你的文档配合的更加完美。建立自己的DTD也是很简单的一件事,一般只需要定义4-5个元素就可以了。

调用DTD文件的方法有两种:

1.直接包含在XML文档内的DTD

你只要在DOCTYPE声明中插入一些特别的说明就可以了,象这样: 

我们有一个XML文档:

<?xml version="1.0" encoding="GB2312"?>

<myfile>

<title>XML轻松学习手册</title>

<author>ajie</author>

</myfile>

我们在第一行后面插入下面代码就可以:

<!DOCTYPE myfile [

<!ELEMENT title (#PCDATA)>

<!ELEMENT author (#PCDATA)>

<!ENTITY copyright "Copyright 2001, Ajie.">

]>
 

2.调用独立的DTD文件

将DTD文档存为.dtd的文件,然后在DOCTYPE声明行中调用,例如,将下面的代码存为myfile.dtd

<!ELEMENT myfile (title, author)>

<!ELEMENT title (#PCDATA)>

<!ELEMENT author (#PCDATA)>
 

然后在XML文档中调用,在第一行后插入:

<!DOCTYPE myfile SYSTEM "myfile.dtd">
 

我们可以看到DTD文档和HTML中js的调用是差不多的,关于DTD文档具体如何写,我们将在下一章和XML文档的语法一起介绍。 


下面我们来了解DTD有关的术语:

1.Schema(规划) 

schema是数据规则的描述。schema做两件事:

a.它定义元素数据类型和元素之间的关系;

b.它定义元素所能包含的内容类型。

DTD就是关于XML文档的一个schema。

2.Document Tree(文档树) 

"文档树"在前面第二章我们已经提到过,它是文档元素分级结构的形象表示。一个文档结构树包含根元素,根元素是最顶级的元素,(就是紧接着XML声明语句后的第一个元素)。看例子:

<?xml version="1.0"?>

<filelist> 

<myfile>

<title>...</title>

<author>...</author>

</myfile>

</filelist>

上面的例子分三级结构排列成"树"状,其中的<filelist>就是根元素。在XML和DTD文件中,第一个定义的都是根元素。
 

3.Parent Element(父元素)/Child Element(子元素)

父元素是指包含有其它元素的元素,被包含的元素称为它的子元素。看上面的"结构树",其中<myfile>是父元素,<title>,<author>是它的子元素,而<myfile>又是<filelist>的子元素。象<title>这样没有包含任何子元素的最后一级元素我们也称之为"页元素"。
4.Parser(解析软件) 

Parser是一种检查XML文档是否遵循DTD规范的工具软件。

XML的parser发展为两类:一种是"非确认类paeser",只检测文档是否遵守XML语法规则,是否用元素标识建立了文档树。另一种是"确认类paeser",它不但检测文档语法,结构树,而且比较解析你使用的元素标识是否遵守了相应DTD文件的规范。

Parser能独立使用,也可以成为编辑软件或浏览器的一部分。在后面的相关资源列表里,我列出了当前比较流行的一些parsers。


  好了,通过第三章的学习,我们已经了解了一些XML和DTD的基本术语,但是我们还不知道怎样来写这些文件,需要遵循什么样的语法,在下一章,将重点介绍有关撰写XML和DTD文档的语法。请继续浏览,谢谢!

XML轻松学习手册(4)XML语法

第四章 XML语法 

提纲: 

一.XML语法规则 
二.元素的语法 
三.注释的语法 
四.CDATA的语法 
五.Namespaces的语法 
六.entity的语法 
七.DTD的语法 

通过前面三章的学习,我们已经对什么是XML,它的实现原理以及相关的术语有所了解。接下来我们就开始学习XML的语法规范,动手写自己的XML文档。

一.XML语法规则

XML的文档和HTML的原代码类似,也是用标识来标识内容。创建XML文档必须遵守下列重要规则:
规则1:必须有XML声明语句
这一点我们在上一章学习时已经提到过。声明是XML文档的第一句,其格式如下:
<?xml version="1.0" standalone="yes/no" encoding="UTF-8"?> 
声明的作用是告诉浏览器或者其它处理程序:这个文档是XML文档。声明语句中的version表示文档遵守的XML规范的版本;standalone表示文档是否附带DTD文件,如果有,参数为no;encoding表示文档所用的语言编码,默认是UTF-8。

规则2:是否有DTD文件
如果文档是一个"有效的XML文档"(见上一章),那么文档一定要有相应DTD文件,并且严格遵守DTD文件制定的规范。DTD文件的声明语句紧跟在XML声明语句后面,格式如下:
<!DOCTYPE type-of-doc SYSTEM/PUBLIC "dtd-name"> 
其中:
"!DOCTYPE"是指你要定义一个DOCTYPE;
"type-of-doc"是文档类型的名称,由你自己定义,通常于DTD文件名相同;
"SYSTEM/PUBLIC"这两个参数只用其一。SYSTEM是指文档使用的私有DTD文件的网址,而PUBLIC则指文档调用一个公用的DTD文件的网址。
"dtd-name" 就是DTD文件的网址和名称。所有DTD文件的后缀名为".dtd"。
我们还是用上面的例子,应该写成这样:
<?xml version="1.0" standalone="no" encode="UTF-8"?>
<!DOCTYPE filelist SYSTEM "filelist.dtd">

规则3:注意你的大小写
在XML文档中,大小写是有区别的。<P>和<p>是不同的标识。注意在写元素时,前后标识大小写要保持一样。例如:<Author>ajie</Author>,写成<Author>ajie</author>是错误的。
你最好养成一种习惯,或者全部大写,或者全部小写,或者大写第一个字母。这样可以减少因为大小写不匹配产生的文档错误。

规则4:给属性值加引号
在HTML代码里面,属性值可以加引号,也可以不加。例如:<font color=red>word</font>和<font color="red">word</font>都可以被浏览器正确解释。
但是在XML中则规定,所有属性值必须加引号(可以是单引号,也可以是双引号),否则将被视为错误。

规则5:所有的标识必须有相应的结束标识
在HTML中,标识可能不是成对出现的,比?lt;br>。而在XML中规定,所有标识必须成对出现,有一个开始标识,就必须有一个结束标识。否则将被视为错误。

规则6:所有的空标识也必须被关闭
空标识就是标识对之间没有内容的标识。比如
,<img>等标识。在XML中,规定所有的标识必须有结束标识,针对这样的空标识,XML中处理的方法是在原标识最后加/,就可以了。例如:

应写为<br />;
<META name="keywords" content="XML, SGML, HTML">应写为<META name="keywords" content="XML, SGML, HTML" />;
<IMG src= "cool.gif">应写为<IMG src= "cool.gif" /> 


第四章 XML语法

二.元素的语法 

元素由一对标识以及其中的内容组成。就象这样:ajie。元素的名称和标识的名称是一样的。标识可以用属性来进一步描述。 

在XML中,没有任何保留字,所以你可以随心所欲的用任何词语来作为元素名称。但是也必须遵守下列规范: 

1.名称中可以包含字母、数字以及其它字母; 

2.名称不能以数字或"_" (下划线)开头; 

3.名称不能以字母 xml(或 XML 或 Xml ..)开头 

4.名称中不能包含空格 

5.名称中间不能包含":"(冒号) 

为了使元素更容易阅读理解和操作,我们还有一些建议: 

1.名称中不要使用"."。因为在很多程序语言中,"."是作为对象的属性,例如:font.color。同样的原因"-"也最好不要用,必须使用的,以"_"代替; 

2.名称尽量简短。 

3.名称的大小写尽量采用同一标准。 

4.名称可以使用非英文字符,比如用中文。但是有些软件可能不支持。(IE5目前是支持中文元素的。) 

另外,补充一点关于属性的说明。在HTML中,属性可以用来定义元素的显示格式,比如:<font color="red">word</font>将把word显示为红色。而在XML中,属性只是对标识的描述,与元素内容的显示无关。例如同样一句:<font color="red">word</font>,并不会将word显示为红色。(那么,有网友会问:如何在XML中将文字显示为红色呢?这就需要使用CSS或者XSL,我们在下面详细讲述。) 

三.注释的语法 

注释是为了便于阅读和理解,在XML文档添加的附加信息,将不会被程序解释或则浏览器显示。 

注释的语法如下: 

<!-- 这里是注释信息 --> 

可以看到,它和HTML中的注释语法是一样的,非常容易。养成良好的注释习惯将使你的文档更加便于维护,共享,看起来也更专业。 

四.CDATA的语法 

CDATA全称character data,翻译为字符数据。我们在写XML文档时,有时需要显示字母,数字和其它的符号本身,比如"<",而在XML中,这些字符已经有特殊的含义,我们怎么办呢?这就需要用到CDATA语法。语法格式如下: 

<![CDATA[这里放置需要显示的字符]]> 

例如: 

<![CDATA[<AUTHOR sex="female">ajie</AUTHOR>]]> 

在页面上显示的内容将是"<AUTHOR sex="female">ajie</AUTHOR>" 


第四章 XML语法

五.Namespaces的语法 

Namespaces翻译为名字空间。名字空间有什么作用呢?当我们在一个XML文档中使用他人的或者多个DTD文件,就会出现这样的矛盾:因为XML中标识都是自己创建的,在不同的DTD文件中,标识名可能相同但表示的含义不同,这就可能引起数据混乱。
比如在一个文档<table>wood table</table>中<table>表示桌子,
而在另一个文档<table>namelist</table>中<table>表示表格。如果我需要同时处理这两个文档,就会发生名字冲突。
了解决这个问题,我们引进了namespaces这个概念。namespaces通过给标识名称加一个网址(URL)定位的方法来区别这些名称相同的标识。 
Namespaces同样需要在XML文档的开头部分声明,声明的语法如下:
<document xmlns:yourname='URL'>
其中yourname是由你定义的namespaces的名称,URL就是名字空间的网址。
假设上面的"桌子<table>"文档来自http://www.zhuozi.com,我们就可以声明为
<document xmlns:zhuozi='http://www.zhuozi.com&#39;> 
然后在后面的标识中使用定义好的名字空间:
<zhuozi:table>wood table</table>
这样就将这两个<table>区分开来。注意的是:设置URL并不是说这个标识真的要到那个网址去读取,仅仅作为一种区别的标志而已。

六.entity的语法

entity翻译为"实体"。它的作用类似word中的"宏",也可以理解为DW中的摸板,你可以预先定义一个entity,然后在一个文档中多次调用,或者在多个文档中调用同一个entity。
entity可以包含字符,文字等等,使用entity的好处在于:1.它可以减少差错,文档中多个相同的部分只需要输入一遍就可以了。2.它提高维护效率。比如你有40个文档都包含copyright的entity,如果需要修改这个copyright,不需要所有的文件都修改,只要改最初定义的entity语句就可以了。
XML定义了两种类型的entity。一种是我们这里说的普通entity,在XML文档中使用;另一种是参数entity,在DTD文件中使用。
entity的定义语法为:
<!DOCTYPE filename [
<!ENTITY entity-name "entity-content"
]
>
例如我要定义一段版权信息:
<!DOCTYPE copyright [
<!ENTITY copyright "Copyright 2001, Ajie. All rights reserved"
]
>
如果我的版权信息内容和他人共享一个XML文件,也可以使用外部调用的方法,语法象这样:
<!DOCTYPE copyright [
<!ENTITY copyright SYSTEM "http://www.sample.com/copyright.xml"> 
]
>
定义好的entity在文档中的引用语法为:&entity-name;
例如,上面定义的版权信息,调用时写作?copyright;
完整的例子如下,你可以copy下来存为copyright.xml观看实例:
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE copyright [
<!ENTITY copyright "Copyright 2001, Ajie. All rights reserved">
]>
<myfile>
<title>XML</title>
<author>ajie</author>
<email>ajie@aolhoo.com</email>
<date>20010115</date>
©right;
</myfile> 


第四章 XML语法

七.DTD的语法 

DTD是"有效XML文档"的必须文件,我们通过DTD文件来定义文档中元素和标识的规则及相互关系。如何建立一个DTD文件呢?让我们一起来学习: 

1.设置元素 

元素是XML文档的基本组成部分。你要在DTD中定义一个元素,然后在XML文档中使用。元素的定义语法为:<!ELEMENT DESCRIPTION (#PCDATA, DEFINITION)*> 

说明: 

"<!ELEMENT" 是元素的声明,说明你要定义的是一个元素; 

声明后面的"DESCRIPTION",是元素的名称; 

"(#PCDATA, DEFINITION)*>"则是该元素的使用规则。规则定义了元素可以包含的内容以及相互的关系。下面的表格概要列出了元素的规则: 

2.元素规则表: 


此主题相关图片如下:

另外,我们还可以为元素定义属性,因为我们不推荐使用属性,在这里就不详细展开了。

 最后,我们来总结一些前四章学习的内容,写一个包含DTD,XML,以及Script的简单实例,便于读者理解:
1.将下面文件存为myfile.dtd
<!ELEMENT myfile (title, author)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>

2.然后建立XML文档myfile.xml:
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE myfile SYSTEM "myfile.dtd">
<myfile>
<title>XML轻松学习手册</title>
<author>ajie</author>
</myfile>

3.建立HTML文档myfile.html
<html>
<head>
<script language="javascript" for="window" event="onload">
var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.load("myfile.xml");
nodes = xmlDoc.documentElement.childNodes;
title.innerText = nodes.item(0).text;
author.innerText = nodes.item(1).text;
</script>
<title>在HTML中调用XML数据</title>
</head>
<body bgcolor="#FFFFFF">
<b>标题: </b>
<span id="title"></span><br>
<b>作者: </b>
<span id="author"></span><br>
</body>
</html>

4.用IE5.0以上浏览器打开myfile.html就可以看到效果了。

XML轻松学习手册(5)XML实例解析

第五章:XML实例解析 

提纲: 

一:实例效果 

二:实例解析 
  1.定义新标识。
  2.建立XML文档。
  3.建立相应的HTML文件。 

XML在不同领域有着广泛的应用,比如在科技领域的MathML,无线通信应用的WML,在网络图象方面的SVG等等,我们这里侧重讨论XML在web上的应用。XML在web上应用主要是利用其强大的数据操作能力。一般用XML配合javascript和asp等服务器端程序,可以实现网络上几乎所有的应用需求。 

考虑讲解方便,我们在下面介绍一个简单的实例,不包含服务器端程序。目的在于让您对XML的数据操作能力有一个感性的认识。 

好,我们首先[ 点击这里 ]来看实例的效果。(请用IE5.0以上版本浏览器打开) 

这是一个简单的CD唱片数据检索功能。你通过点击"上一张","下一张"可以看到单张CD的有关信息。这样的效果我们原来用两种方法可以实现: 

1.利用DHTML,将数据隐藏在不同的层中,通过鼠标事件依次显示; 

2.利用后台程序(如ASP,CGI,PHP,JSP等),调用服务器端的数据。 

但是在这个实例中,我们打开页面原代码可以看到,其中没有用DHTML的DIV,也没有表单的action,它完全是用XML来实现的。下面我们来分析它的制作过程:

第一步:定义新标识。
根据实际的CD数据,首先新建一个名为<CD>的标识;其次建立它相关的数据标识,分别是:CD名称<Title>,演唱者<Artist>,出版年代<Year>,国家<Country>,发行公司<Company>和价格<Price>;最后还要建立一个名为目录<CATALOG>的标识。为什么要再建立一个<CATALOG>标识呢?因为在XML文档中规定,必须且只能有一个根元素(标识),我们有多个CD数据,这些数据是并列的关系,所以需要为这些并列的元素建立一个根元素。
以上元素的定义和关系都完全符合XML标准,不需要特别的DTD文件来定义,所以可以省略DTD定义。如果我们想使用DTD来定义,以上过程可以表示为:

<!ELEMENT CATALOG (CD)*>
<!ELEMENT CD (Title,Artist,Year,Country,Company,Price)>
<!ELEMENT Title (#PCDATA)>
<!ELEMENT Artist (#PCDATA)>
<!ELEMENT Year (#PCDATA)>
<!ELEMENT Country (#PCDATA)>
<!ELEMENT Company (#PCDATA)>
<!ELEMENT Price (#PCDATA)>

这段代码表示:元素CATALOG包含多个CD子元素,而子元素CD又依次包含Title, Artist, Year, Country, Company, Price 六个子元素,它们的内容都定义为文本(字符,数字,文本)。(注:具体的语法说明可以看上一章关于DTD的介绍) 

第二步:建立XML文档。

<?xml version="1.0"?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tylor</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Greatest Hits</TITLE>
<ARTIST>Dolly Parton</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>RCA</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1982</YEAR>
</CD>
<CD>
<TITLE>Still got the blues</TITLE>
<ARTIST>Gary More</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>Virgin redords</COMPANY>
<PRICE>10.20</PRICE>
<YEAR>1990</YEAR>
</CD>
<CD>
<TITLE>Eros</TITLE>
<ARTIST>Eros Ramazzotti</ARTIST>
<COUNTRY>EU</COUNTRY>
<COMPANY>BMG</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1997</YEAR>
</CD>
</CATALOG> 

上面代码首先用<?xml version="1.0"?>声明语句表明这是一个XML文档,它的格式遵守XML 1.0标准规范。然后是文档内容,结构树非常清晰:
<CATALOG>
<CD>
...... 
</CD>
<CD>
...... 
</CD>

</CATALOG>
一共定义了5组数据。我们将上面的代码存为cd.xml文件,以备调用。 


第三步:建立相应的HTML文件。
1.导入XML数据。
我们知道,目前流行的浏览器中,暂时只有微软的IE5.0以上版本浏览器支持XML。IE是通过在HTML中的object物件来支持插入XML,并通过js的XMLDocument.load()方法来导入数据。我们看代码: <object WIDTH="0" HEIGHT="0"
CLASSID="clsid:550dda30-0541-11d2-9ca9-0060b0ec3d39" ID="xmldso">
</object>

定义一个object,ID名为xmldso。然后在head区用js引入xml数据:

<script for="window" event="onload">
xmldso.XMLDocument.load("cd.xml");
</script>

2.捆绑数据。
然后将用<SPAN>标识来将XML数据绑定在表格中。其中ID,DATASRC,DTATFLD都是<SPAN>的属性。代码如下:

<table>
<tr><td>Title:</td><td><SPAN ID="title" DATASRC=#xmldso DATAFLD="TITLE"></SPAN></td></tr>
<tr><td>Artist:</td><td><SPAN ID="artist" DATASRC=#xmldso DATAFLD="ARTIST"></SPAN></td></tr>
<tr><td>Year:</td><td><SPAN ID="year" DATASRC=#xmldso DATAFLD="YEAR"></SPAN></td></tr>
<tr><td>Country:</td><td><SPAN ID="country" DATASRC=#xmldso DATAFLD="COUNTRY"></SPAN></td></tr>
<tr><td>Company:</td><td><SPAN ID="company" DATASRC=#xmldso DATAFLD="COMPANY"></SPAN></td></tr>
<tr><td>Price:</td><td><SPAN ID="price" DATASRC=#xmldso DATAFLD="PRICE"></SPAN></td></tr>
</table>

3.动作操作。
最后,为数据提供浏览按钮:
<INPUT TYPE=button value="上一张CD" onCLICK="moveprevious()">
<INPUT TYPE=button value="下一张CD" onCLICK="movenext()">

并利用js来完成两个鼠标点击功能:movenext()和moveprevious()。在head区加入如下代码:

<script language="javascript">
function movenext()
{
if (xmldso.recordset.absoluteposition < xmldso.recordset.recordcount)
{
xmldso.recordset.movenext();
}
}
function moveprevious()
{
if (xmldso.recordset.absoluteposition > 1)
{
xmldso.recordset.moveprevious();
}
}
</script>

好,我们先看HTML文件的全部原代码:

<html>
<head>

<script for="window" event="onload">
xmldso.XMLDocument.load("cd.xml");
</script>

<script language="javascript">
function movenext()
{
if (xmldso.recordset.absoluteposition < xmldso.recordset.recordcount)
{
xmldso.recordset.movenext();
}
}
function moveprevious()
{
if (xmldso.recordset.absoluteposition > 1)
{
xmldso.recordset.moveprevious();
}
}
</script>

<TITLE>CD Navigate</TITLE>
</head>

<body>
<p>
<object WIDTH="0" HEIGHT="0"
CLASSID="clsid:550dda30-0541-11d2-9ca9-0060b0ec3d39" ID="xmldso">
</object>

<table>
<tr><td>Title:</td><td><SPAN ID="title" DATASRC=#xmldso DATAFLD="TITLE"></SPAN></td></tr>
<tr><td>Artist:</td><td><SPAN ID="artist" DATASRC=#xmldso DATAFLD="ARTIST"></SPAN></td></tr>
<tr><td>Year:</td><td><SPAN ID="year" DATASRC=#xmldso DATAFLD="YEAR"></SPAN></td></tr>
<tr><td>Country:</td><td><SPAN ID="country" DATASRC=#xmldso DATAFLD="COUNTRY"></SPAN></td></tr>
<tr><td>Company:</td><td><SPAN ID="company" DATASRC=#xmldso DATAFLD="COMPANY"></SPAN></td></tr>
<tr><td>Price:</td><td><SPAN ID="price" DATASRC=#xmldso DATAFLD="PRICE"></SPAN></td></tr>
</table>

<p>
<INPUT TYPE=button value="上一张CD" onCLICK="moveprevious()">
<INPUT TYPE=button value="下一张CD" onCLICK="movenext()">
</p>

</body>
</html>

将以上代码存为cd.htm文件,于第二步的cd.xml文件放在一起。打开cd.htm文件,你就看见和上面实例一样的效果了。

好,到今天为止,我们已经学习了关于XML的不少知识,我们来总结一下前面五个章节,分别是XML快速入门,XML的概念原理,XML的术语,XML的语法和本章的实例解析。到这里,教程部分就结束了。在写作过程中,阿捷尽最大努力将有关XML概念讲得通俗易懂,尽量把自己的理解告诉给大家,但因为本人学习XML时间也不长,对整个XML的技术把握还不够系统和深入,所以难免有疏漏的地方,请大家指正和谅解,谢谢!
<完>

posted @ 2006-01-05 19:46 Ben 阅读(276) | 评论 (0)编辑 收藏

金山词霸2000使用密技两则

金山词霸2000使用密技两则

loveaniu

    
 

  金山词霸这么好的软件相信大家都用过吧,可是小生在近日的使用过程中却遇到了两个棘手的问题,经过仔细分析,终于解决,呵呵,好东东当然不能独享,大家请看:

  (一)怎样解决金山词霸在win2000下不能正确显示音标的问题。

  在win2000下装过金山词霸的朋友可能都有词霸不能正确显示单词音标的问题,音标在win2000下被显示成了一堆乱码,这可怎么办呢,我抱着试一试的心理去到金山公司的技术支持那里看能不能找到解决办法,金山的技术支持人员的回答:“出现这类问题时,可能是安装出错或其他软件的字体驱动错误,建议重新安装词霸2000;重装后如果仍然出现问题,则是由于安装了过多的字体,请删掉一些字体再安装或重装Windows系统”。看来只能自己试了,我的win2000里并未装过任何其他的字体,应该不会出现冲突这类事情,那么一定是金山词霸无法调用自己的音标字体而误调用了WINGDING字体造成的,于是我便在金山词霸的安装目录下开始找起来,终于让我找到了那个音标字体——Ksphonet.ttf。呵呵,到这里就好解决了,我们只要把这个字体拷入win2000的fonts目录下就ok了,再开你的词霸试一试,是不是久违的音标又出来了呢?

  (二)怎样解决金山词霸不能在Acrobat中取词翻译的问题。

  许多朋友都希望能在看pdf文件时也能够用金山词霸的取词功能,可是你可能会发现你的金山词霸做不到,这可怎么办呢?呵呵,小生献上终极密技一条,包你随指随取随译,你就一边爽着吧:)方法如下:首先去http://ciba.kingsoft.net/download/acrbatup.zip下载这个补丁,打开后有AcrUpdate.exe和XDICPI32.API 两个文件,你所要做的只是运行AcrUpdate.exe,然后按它所说的一步一步做下去就行了,如果还是不行的话那就只好手工安装了,找到你的Acrobat安装目录,将XDICPI32.API拷入其reader\plug_ins目录下就行了。

硅谷动力eNet

posted @ 2005-12-27 16:57 Ben 阅读(277) | 评论 (0)编辑 收藏

Java 技巧 101:applet 间通信的替代方法

作者 Tobias Hill



摘要
您可能认为能让 applet 彼此通信的唯一选择就是使用 getApplet。不幸的是,getApplet 方法仅返回与发出调用的 applet 在同一个 HTML 页面上的 applet,这样就限制了您通过 applet 间的通信构建有趣界面的方式。这篇技巧说明的替代方法能使处于不同框架甚至不同浏览器窗口中的 applet 彼此调用对方的方法。

java.applet 包中的 AppletContext 类包含两个成员方法,即 getApplet 和 getApplets。通过使用这两个方法,一个 applet 就可以找到其他 applet 并调用它们的方法。要这样做必须满足下面的安全要求:

  • 这些 applet 来自同一个服务器上的同一个目录中。
  • 这些 applet 运行于同一个浏览器窗口中的同一个页面上。

    这样设计安全限制可能有很好的原因;但是,后一个要求限制了利用 applet 间的通信制作有趣的多 applet 界面的方式。

    试考虑这样一种情况:

    您刚编好一个很好的股票市场交易 applet,并决定为它编写一个良好的帮助系统。您希望帮助系统也是一个 applet,并希望将它与股票市场交易 applet 在不同的浏览器框架中运行。您作出这个决定可能是出于网站结构方面的考虑,也可能是出于始终显示帮助系统的需要。另外,您希望使帮助系统根据用户当前在股票交易 applet 中进行的操作转至正确的信息/指导(就像 Microsoft Office 套件中的“回形针”一样)。您甚至计划在帮助系统中编制向导,这些向导可远程指出问题,并可远程执行股票市场交易 applet 中的任务。

    这一方案中体现的思想很不错。但是,因为这两个 applet 处于不同的页面上,所以 AppletContext 中的 Java API 无法帮助您实现这个想法 -- 但这篇技巧可以帮助您。


    使用 AppletContext API

    在说明 applet 间通信的替代机制前,我将首先简要说明一下 getApplet 和 getApplets 这两个方法是如何工作的。一个 applet 通过使用 getApplet 方法可以按名称找到同一个 HMTL 页面中的另一个 applet,而通过使用 getApplets 方法可以找到同一个页面上的所有 applet。这两个方法如果成功执行,则会向调用者返回一个或多个 Applet 对象。调用者一旦找到一个 Applet 对象,它就可能调用这个 Applet 的公用方法。

    假定有下面这样一段 HTML 代码:
    PHP代码:
    <applet code="Applet1" width="400" height="100" name="app1">
    </
    applet>

    <
    applet code="Applet2" width="400" height="100" name="app2">
    </
    applet>

    通过使用 applet 标记中的 name 属性,您就可以用下面的方式引用一个特定的 applet:
    PHP代码:
    Applet theOtherApplet = getApplet("app1");
    theOtherApplet.anyMethod(); //调用任一个公用方法

    或者,您也可以用以下的代码来检索这个页面上的所有 applet:
    PHP代码:
    Enumeration allAppletsOnSamePage = getApplets();
    while(
    allAppletsOnSamePage.hasMoreElements()) {
    Applet appl = (Applet) allAppletsOnSamePage.nextElement();
    appl.anyMethod(); //调用任一个公用方法
    }

    当发出调用的 applet 在它所在的同一个 HTML 页面上检索到一个或几个 applet 之后,它就可以调用这些 applet 的公用方法。

    使用静态数据结构

    不幸的是,如果使用标准方法,则只能与同一个 HTML 页面中的 applet 通信。幸运的是,您很容易就可以避开这个限制。使 applet 间跨页面通信的方法基于这样一个事实,即如果两个 applet 的 codebase 相同,则即使它们是在不同的浏览器窗口中被加载的,它们也共享同一个运行时环境。粗略地说,codebase 就是从中加载 applet 的那个目录。请参阅文后的参考资源,其中有一个链接指向有关 codebase 的一篇教程。

    由于运行时环境是共享的,因此所有 applet 实例都可以访问静态域和静态结构,这样这些静态域和结构就可用来在不同 applet 之间传递信息。

    applet 不仅可以存储诸如整数、字符和字符串这样的简单数据类型,而且每个 applet 都可以将其自身(实例)的一个引用存储在一个静态域(可能在它自己的类中)中。任何 applet 都可以访问这个域,从而获得指向这个实例的引用。

    这听起来复杂吗?不,一点也不复杂。我首先举一个简单的例子。假定您的一个 applet (AppletA.class) 在一个框架中,而另一个 applet (AppletB.class) 在另一个框架中,而且这两个 applet 都是从同一个 codebase 加载的。

    您现在希望授予 AppletA 访问 AppletB 的公用方法的权限。您必须让 AppletB 将其自身的一个引用存储在一个静态公用域中,就像下面这样:
    PHP代码:
    public class AppletB {
    public static
    AppletB selfRef = null; // 初始归零

    public void init() {
    // 生成对该实例的引用
    selfRef = this;
    }
    ...
    }

    现在您就可以从 AppletA 访问 AppletB 的实例了:
    PHP代码:
    public class AppletA {
    AppletB theOtherApplet = null;

    public
    void callAppletB() {
    // 获取静态域,其中存储着指向 AppletB 的
    // 实例的指针。
    theOtherApplet = AppletB.selfRef;

    // 此后就可以调用实例方法了,
    // 如下所示...
    theOtherApplet.repaint();
    }
    ...
    }

    这就是我们所要做的全部工作。因为运行时环境是由不同的 applet 共享的,所以即便 applet 不在同一个页面上,这个方法同样奏效。

    值得注意的一点是,上面的代码并没有处理在启动 AppletB 之前就调用 AppletA 中的 callAppletB 方法的情况。如果发生这种情况,则 selfRef 将是 null,这样不能进行任何通信。

    一种更通用的方法

    当然,还有一种更通用的方法。您可以创建这样一个类,创建它的唯一目的就是在静态数据结构中存储 applet 的引用。稍后您将看到的 AppletList 类就属于这种情况。希望其他 applet 访问自己的公用方法的 applet 实例通过 AppletList 将自己注册。按照 AppletContext.getApplet(string name) 中的模式,每个注册项都与一个字符串相关联。当一个 applet 调用某个 applet 的引用时,这个字符串就起关键字的作用。

    通常,applet 是按下面的方式注册的:
    PHP代码:
    public class AppletA {
    public
    void start() {
    AppletList.register("Stock-trade-applet", this);
    ...
    }
    }

    另一个 applet 获取对它的访问权:
    PHP代码:
    public class AppletB {
    public
    void run() {
    AppletA tradeApplet =
    (
    AppletA) AppletList.getApplet("Stock-trade-applet");
    ...
    }
    }

    当该 applet 停止运行时,您必须紧记在 AppletList 中撤销注册:
    PHP代码:
    public void stop() {
    AppletList.remove("Stock-trade-applet");
    ...
    }

    AppletList 类的完整源代码如下所示:
    PHP代码:
    0: import java.util.*;
    1: import java.applet.Applet;
    2:
    3: public class AppletList {
    4: private static Hashtable applets = new Hashtable();
    5:
    6: public static void register(String name, Applet applet) {
    7: applets.put(name,applet);
    8: }
    9:
    10: public static void remove(String name) {
    11: applets.remove(name);
    12: }
    13:
    14: public static Applet getApplet(String name) {
    15: return (Applet) applets.get(name);
    16: }
    17:
    18: public static Enumeration getApplets() {
    19: return applets.elements();
    20: }
    21:
    22: public static int size() {
    23: return applets.size();
    24: }
    25: }

    要获得说明如何使用这个类的示例,请在参考资源中下载 exampleCode.zip。

    局限性

    正如我在前面提到的那样,必须从同一个 codebase 中加载这些 applet。此外,如果浏览器的两个不同副本正在运行,并且 applet 被加载到每个副本中,则 applet 可能无法彼此通信(取决于浏览器的版本和设置),因为它们可能不再共享同一个运行时环境。但是,如果是浏览器本身衍生出新的浏览器窗口,则没有任何问题。

    该技巧已在几个平台和几个浏览器版本中通过测试,但在某些配置中每个 applet 的运行时环境可能是独立的。该技巧已在下面的操作系统和浏览器组合中通过测试:
  • Windows2000: Internet Explorer 5.0,Internet Explorer 5.5,Netscape Navigator 4.72,Opera 4.01
  • Windows 98: Internet Explorer 4.72,Internet Explorer 5.0,Netscape Navigator 4.02
  • Mac OS 9: Internet Explorer 4.5,
  • Netscape Navigator 4.5
    Red Hat 6.2: Netscape Navigator 4.73

    小结

    这篇技巧说明了能使 applet 彼此通信的一种替代方法。这种方法以 Java API 的 getApplet() 方法不支持的方式工作。这篇技巧中介绍的知识增大了将 applet 作为网站或内部网的一部分的可能性 -- 可以用它替代或补充 getApplets 方法。

    作者简介

    Tobias Hill 是 Citerus 的创办者之一,该公司以瑞典为基地,致力于在 Java 平台上构建因特网、内部网和外部网系统。Hill 从 1996 年开始用 Java 编程,参与了许多项目,从为自主控制的机器人编程到开发在线焰火明信片制作程序等等。

    参考资源

    * 说明如何使用 AppletList 类的示例:
    exampleCode.zip
    * Sun 提供的关于 applet 间通信的 Java 教程:
    http://web2.java.sun.com/docs/books...tsonly/iac.html
    * Sun 提供的有关 codebase(在其他问题中)的 Java 教程:
    http://web2.java.sun.com/docs/books...sonly/html.html
    * 查看以前的所有 Java 技巧以及提交您自己的技巧:
    http://www.javaworld.com/javatips/j...tips.index.html
  • posted @ 2005-12-23 17:06 Ben 阅读(359) | 评论 (0)编辑 收藏

    [转贴]2005年11月程序语言世界排行榜-Java居首位

    摘要:
    近日来,在TIOBE程序员社区中公布了其2005年11月的程序语言排行榜。这得注意的是PHP即将超过C++成为了排行榜的老三!而Java作为开源先锋首当其冲的成为了龙头老大,并且仍然保持着很好的增长势头。



    转载:转载请保留本信息,本文来自http://www.matrix.org.cn/resource/news/315.html


    版权申明:转载必须保留以下信息
    作者:cleverpig

    可以自由转载, 转载请保留下面的作者信息:

    作者 cleverpig(http://www.matrix.org.cn/blog/cleverpig)


    近日来,在TIOBE程序员社区中公布了其2005年11月的程序语言排行榜。这得注意的是PHP即将超过C++成为了排行榜的老三!而Java作为开源先锋首当其冲的成为了龙头老大,并且仍然保持着很好的增长势头。

    这个排行榜每月更新一次,其排名顺序按照世界范围内的技术工程师、讲师、第三方厂商的调查依据,并查询了目前流行的搜索引擎:Google,MSN,Yahoo,结合前两者的数据计算后得出的。根据TIOBE的观点,此排行榜是被程序员们用来检查自己的程序技能是否过时,或者作为建立新的软件系统时进行参考之依据,并非意味着哪种语言是最好的。

    1。世界前20位语言排行榜:




    2。世界前10位语言在前五年内长期发展趋势图:




    3。世界前30-50位语言排行榜:







    图示说明:
    * (Position):此列表明当前语言与去年位置的变化。
    * Ratings:在查询搜索引擎计算排名顺序时使用了 '+" programming" -tv -channel'公式,对上12个月内Google,MSN,Yahoo!和Google新闻组的数据进行查询。注意此公式应用于标准的Google web点击率、标准的MSN web点击率、标准的Yahoo!web点击率和标准的Google新闻组点击率。这里的“标准”意味着一次对前50位语言web点击率总和的查询是均匀分布的,即保证了排名的相对公正性和科学性。
    * (Ratings): 此列表明当前语言在上12个月内的排名变化。
    * Status:带有“A”的程序语言被认为是主流语言。
    带有“A-”和“A--”表示程序语言位于“A”和“B”之间。
    从支持能力的观点看,尽量在工业的、任务危机的软件系统中使用带有“A”的主流程 序语言。
    如果某种语言在上3个月内具有超过0.7%的增长率,则此语言将获得“A”状态。上两个月内具有超过0.7%的增长率的程序语言相应的将获得“A--”和“A-”状态。

    posted @ 2005-12-23 16:53 Ben 阅读(321) | 评论 (0)编辑 收藏

    你是否需要XML?

    XML是现在很热门的一个话题,但是实际上它能为你的公司做些什么?你需不需要配置XML呢?大家只有对XML有所了解之后才能做出正确的评估,然后才能真正决定是否采用XML。通过权衡利弊,能够帮助你做最后的决定。


    XML如何被使用?

    XML对于描述那些要被应用程序所使用的数据来说是一种非常出色的工具。这是由于绝大多数基于网络的应用软件是使用这些数据制作出来的,而对于XML来说,它已经发展成为了网络服务的一种标准。



    你可以在企业里的许多层次上都使用XML。XML经常被用来存储那些会出现在网络站点的内容。你还可以把XML用作内部的信息存储库,这个库是可以被第三方应用软件所访问的,而且不需要具备数据库相关的功能。



    从内部移动到外部应用软件,XML可以让你和合作者之间以一种有协议的方式进行数据交换。你可以维持你系统原来的状态,而不用去考虑合作者系统的结构。

    采用XML的有利条件

    许多企业采用XML的主要原因是由于它允许与外部的合作者进行方便的集成。可能有三个提供商在为你服务,他们都有自己的系统,但是都需要访问相同的数据。XML允许你把数据制作成一种格式,让这三者都能够通过他们自己的系统来获取和使用这些信息。



    很明显,XML是由于它本身的简便易用以及节省时间的信息集中化管理而流行起来的。



    在适当的环境里,使用XML还有其它的一些好处。当处理网络应用软件的时候,把数据装入XML文件然后再由应用软件进行分析的方法能够有效的简化保持维护的复杂性。这就不用再更换菜单、页面标题以及内容了。在许多情况下,只需简单的编辑XML文件就能够完成这些改变。



    XML还可以方便的用于扩展存储于文件中的内容和内容的类型。虽然这可能会比访问数据库要花去更多的时间,但是如果只有相关的信息被存储在文件中的话,那么,处理的时间则会被缩短。你可以使用编程语言中的查找与分类功能来实现,而不是使用数据库中的相关功能。但是,总的来说,XML的内容是有意被显示出来的,而且该过程也不是必需的。

    网络服务对P2P的贡献

    另一个很大的好处是你可以简单的就加入相关数据的子集,能够禁止系统访问那些没有被使用的信息。

    采用XML的缺点

    当然,所有的事情都有两面性,使用XML也有一些缺点,这些缺点会让你在真正使用它之前会再审慎的考虑一番。举例来说,XML有可能会产生非常不便于维护的相当巨大的数据量。由于这个原因,人们通常会把数据存储在数据库中,然后才把输出的相关信息送入XML。在这种情况下,你实际上并不把信息保存在XML文件中。这种情况是否被看作是一个不利条件还不确定,但是还是有必要在作决定之前考虑一下这种情况。



    XML有一个明显的缺点,就是缺少完整的安全保护。一个共享的XML文件对于请求的回应是自动的。如果你把该文件加密以寻求安全保护,那么,接收端就不能够自动的识别出它的内容。XML有几种可以使用的安全标准,但是还没有最后确定选择哪一个标准。



    因此,公司就需要限制他们的文件在VPN或者外部网络上的发布。否则这些公司就会冒一定的风险,因为任何人都知道在国际互联网上如何浏览包含有重要信息的XML文件。



    控制访问也会带来一系列的问题。到安全标准被真正实现之前,唯一可信赖的方法就是为不同的人提供你信息的不同子集,这样做能够为不同的人创建分开的XML文件。如果你试图把XML作为企业B2B解决方案主要组成部分,并且还需要为每一方都进行用户化,那么,选择使用数据库可能比选择使用包含大量XML文件的方式要好得多。

    如何做决定?

    在做决定之前,要考虑一下你要完成什么样的目标,是否使用XML能让完成这个目标变得更加容易。你是否正试图传送相同的或者相关的信息给不同的人,这些人在他们的终端上都使用不同的软件。如果是这样的话,XML是你的好选择。你是否希望能够方便的维护你的网络站点而不用依靠数据库呢?那么,也可以选择XML。



    然而,如果你处理的是比较敏感而且重要的数据,又或者你正在把你数据的不同部分传送给不同的目标,那么,你就会希望能够得到更多的安全保护。如果你的解决方案中包含为相似的服务创建多个XML文件,你的选择可能有些超前了,而且有可能会导致维护上的灾难。



    对于local应用软件,你可能会需要考虑一下具体配置的每一个细节。如果安全和访问都不是问题的话,考虑一下,把你的信息都集中到一个XML源是否能够让你从中获得好处。如果你需要显示这些数据,并且还会出现在不同的地方,那么,XML对于网络服务来说就是一个很好的选择。

    总结

    如果你对于使用XML已经有所准备,那么你就要考虑一下数据的类型和工作的环境了,这些都能够帮助你决定这是否是一个很好的解决方案。如果这么做有很明显的好处,而且你并不介意安全上的问题,那么,你只要多投入些注意力和智慧就可以了。否则,你可能就会希望别的人先于你这么做,而你等到时机成熟了才会选择这样的解决方案。

    posted @ 2005-12-23 16:49 Ben 阅读(331) | 评论 (0)编辑 收藏

    快速精确的对数学表达式求值

    快速精确的对数学表达式求值 英文原文
    内容:
    表达式求值的经典算法
    W3Eval:一种新的方法
    结论
    参考资料
    关于作者
    对本文的评价
    相关内容:
    教程:Building a Java applet
    更多 dW Java 参考资料
    使用这个方便的 applet ,您就能一步一步的计算数学表达式了 Nikola Stepan (nikola.stepan@vz.tel.hr)
    软件工程师,ABIT Ltd.
    2001 年 9 月
    对于未经训练的用户来说,计算机科学领域中数学表达式求值的传统方法即不顺手又难以使用;软件工程师 Nikola.Stepan 旨在改变这些传统方法。他的 applet W3Eval 对表达式求值与您用纸笔计算的一系列步骤完全一致,但更快并且没有错误。请往下读,了解这一挑战 — 人类易读的数学到 Java 代码的转换。
    还记得在您的第一台科学计算器上用逆波兰表示法奋斗的经历吗?W3Eval applet 无法让您可信赖的 HP-41 更易用,正如它的名称所暗示 — 一个只能运行于 Web 的表达式求值程序。但它的确提供了一种方法 — 人类更易于遵循的对表达式一步一步的求值。

    W3Eval 的方法与传统计算器不同,却和人类的计算方式一致。当您用传统的计算器计算时,每输入一个新数,前一个数就看不到了。如果在输入一个长表达式中出了错,就得全部重来。有了 W3Eval,您就能看到参与计算的所有东西,还能轻松的编辑表达式。它独特的能力(一步一步的对表达式求值)非常容易实现,因为用户能看到求值的每一步,包括临时结果。

    本文将让您从头至尾认识 W3Eval 功能性的要点;您将看到一些用于表达式求值的代码。不过,我们还是先看看表达式求值的经典算法,这样您就会明白 W3Eval 方法的差异究竟有多少。

    表达式求值的经典算法
    编写代码对算术表达式求值的经典方法由 Donald Knuth 描述于 1962 年(请参阅参考资料)。Knuth 将此概括为三个步骤:
    • 对中缀表达式进行语法分析
    • 中缀表达式到后缀表达式的转换
    • 对后缀表达式求值
    注意到我们谈到的这个经典算法有些简化:算术表达式只包含操作数、二元操作符和一种括号。此外,对于每个操作数和操作符,只用单个字符表示,使语法分析直观。

    表达式表示法
    算术表达式中最常见的表示法形式有中缀、前缀后缀表示法。中缀表示法是书写表达式的常见方式,而前缀和后缀表示法主要用于计算机科学领域。

    中缀表示法
    中缀表示法是算术表达式的常规表示法。称它为中缀表示法是因为每个操作符都位于其操作数的中间,这种表示法只适用于操作符恰好对应两个操作数的时候(在操作符是二元操作符如加、减、乘、除以及取模的情况下)。对以中缀表示法书写的表达式进行语法分析时,需要用括号和优先规则排除多义性。



    Syntax: operand1 operator operand2Example: (A+B)*C-D/(E+F)
    前缀表示法
    前缀表示法中,操作符写在操作数的前面。这种表示法经常用于计算机科学,特别是编译器设计方面。为纪念其发明家 — Jan Lukasiewicz(请参阅参考资料),这种表示法也称波兰表示法



    Syntax : operator operand1 operand2Example : -*+ABC/D+EF
    后缀表示法
    在后缀表示法中,操作符位于操作数后面。后缀表示法也称逆波兰表示法(reverse Polish notation,RPN),因其使表达式求值变得轻松,所以被普遍使用。



    Syntax : operand1 operand2 operatorExample : AB+C*DEF+/-
    前缀和后缀表示法有三项公共特征:
    • 操作数的顺序与等价的中缀表达式中操作数的顺序一致
    • 不需要括号
    • 操作符的优先级不相关
    中缀表达式到后缀表达式的转换
    要把表达式从中缀表达式的形式转换成用后缀表示法表示的等价表达式,必须了解操作符的优先级和结合性。优先级或者说操作符的强度决定求值顺序;优先级高的操作符比优先级低的操作符先求值。 如果所有操作符优先级一样,那么求值顺序就取决于它们的结合性。操作符的结合性定义了相同优先级操作符组合的顺序(从右至左或从左至右)。



    Left associativity : A+B+C = (A+B)+CRight associativity : A^B^C = A^(B^C)
    转换过程包括用下面的算法读入中缀表达式的操作数、操作符和括号:
    1. 初始化一个空堆栈,将结果字符串变量置空。
    2. 从左到右读入中缀表达式,每次一个字符。
    3. 如果字符是操作数,将它添加到结果字符串。
    4. 如果字符是个操作符,弹出(pop)操作符,直至遇见开括号(opening parenthesis)、优先级较低的操作符或者同一优先级的右结合符号。把这个操作符压入(push)堆栈。
    5. 如果字符是个开括号,把它压入堆栈。
    6. 如果字符是个闭括号(closing parenthesis),在遇见开括号前,弹出所有操作符,然后把它们添加到结果字符串。
    7. 如果到达输入字符串的末尾,弹出所有操作符并添加到结果字符串。
    后缀表达式求值
    对后缀表达式求值比直接对中缀表达式求值简单。在后缀表达式中,不需要括号,而且操作符的优先级也不再起作用了。您可以用如下算法对后缀表达式求值:
    1. 初始化一个空堆栈
    2. 从左到右读入后缀表达式
    3. 如果字符是一个操作数,把它压入堆栈。
    4. 如果字符是个操作符,弹出两个操作数,执行恰当操作,然后把结果压入堆栈。如果您不能够弹出两个操作数,后缀表达式的语法就不正确。
    5. 到后缀表达式末尾,从堆栈中弹出结果。若后缀表达式格式正确,那么堆栈应该为空。
    W3Eval:一种新的方法
    W3Eval 的方法与上面概括的经典算法不同。不是把中缀表达式转换为后缀表示法;恰恰相反,它对中缀表达式直接求值。这种方法比传统方法稍微复杂了些,但它支持一步一步的求值,在执行时您能看到每一步。求值过程类似于手工计算:如果表达式中包含括号,先求嵌套最深的括号对中的子表达式的值。所有括号内的子表达式都求值完毕后,表达式的其它部分再求值。

    求值过程分为三个步骤:
    1. 表达式语法分析
    2. 表达式检查
    3. 一步一步的求值
    表达式语法分析
    W3Eval 的数学表达式由数字、变量、操作符、函数和括号组成。除了缺省的十进制计数制外 W3Eval 还支持二进制、八进制和十六进制。这些以其它计数制计数的数必须以 # 开头,并紧跟 bo 或者 h 来分别表示二进制、八进制或十六进制。

    W3Eval 的变量是不限长度的大写字母和数字序列,其首字符必须是字母。W3Eval 有一些预定义的变量,不过它也支持用户定义的变量。

    W3Eval 支持带有固定或不定数量自变量的函数。 函数可分为以下几组:
    • 三角函数(sin、cos、tan、cot、sec、csc)
    • 反三角函数(asin、acos、atan、atan2、acot、asec、acsc)
    • 双曲线函数(sinh、cosh、tanh、coth、sech、csch)
    • 反双曲线函数(asinh、acosh、atanh、acoth、asech、acsch)
    • 指数函数(log、log2、log10、exp、exp2、exp10、sqrt、cur)
    • 组合学函数(Combinatoric)(comb、combr、perm、permr、var、varr)
    • 统计函数(sum、avg、min、max、stddev、count)
    • 其它(abs、ceil、fact、floor、pow、random、rint、round、sign、frac、hypot、deg、rad、trunc、int)
    W3Eval 对表达式进行语法分析,也就是指它识别出表达式的算术成分,并将它们转化成语言符号(token),然后把它们放入向量。表达式一旦处于这种状态,就为下面两步做好了准备:表达式检查和求值。

    W3Eval 的符号(token)是算术表达式的组成部分;记号(mark) 是独立的字符, 由 applet 使用,作为识别各种符号的内部标志。每种符号有唯一的 mark 与之对应。W3Eval 的表达式由表 1 所示的符号组成。

    表 1. W3Eval 的符号
    Token Mark
    十进制数 Double
    二进制数 String
    十六进制数 String
    八进制数 String
    变量 Variable
    函数 Function
    操作符 Operator
    开括号 String
    闭括号 String
    逗号 String


    用以表示函数、操作符和变量类的定义如清单 1 所示:

    清单 1. Function、Operator 和 Variable 类的定义


    public class Function { public String function; public int number_of_arguments; public Function( String function, int number_of_arguments ) { this.function=function; this.number_of_arguments=number_of_arguments; } public String toString() { return function; } }public class Operator { public String operator; public byte priority; public Operator( String operator, byte priority ) { this.operator=operator; this.priority=priority; } public String toString() { return operator; } }public class Variable { public String variable; public double value; public Variable( String variable, double value ) { this.variable=variable; this.value=value; } public String toString() { return variable; } }
    Token 类如清单 2 所示。

    清单 2. Token 类


    public class Token { public Object token; public char mark; public int position; public int length; public Token ( Object token, char mark, int position, int length ) { this.token=token; this.mark=mark; this.position=position; this.length=length; } public String toString() { return token.toString()+" ; "+mark+" ; "+position+" ; "+length+""; } }
    表达式检查
    检查正规表达式正确性的所有代码都在一个独立的类中。详细的表达式检查能够确定错误确切的类型和位置。 错误检查有七类:

    括号检查。W3Eval 的表达式可以包含三种括号:标准圆括号、方括号和花括号。如果表达式包含相同数量的开括号和闭括号,并且每个开括号与一个相应的同种闭括号相匹配,则表达式的括号语法正确。三种括号在语义上等价,如下面的代码段所示。

    清单 3. 三种括号


    import java.util.Stack;public class Parentheses_check { public static boolean is_open_parenthesis( char c ) { if ( c=='(' || c=='[' || c=='{' ) return true; else return false; } public static boolean is_closed_parenthesis( char c ) { if ( c==')' || c==']' || c=='}' ) return true; else return false; } private static boolean parentheses_match( char open, char closed ) { if ( open=='(' && closed==')' ) return true; else if ( open=='[' && closed==']' ) return true; else if ( open=='{' && closed=='}' ) return true; else return false; } public static boolean parentheses_valid( String exp ) { Stack s = new Stack(); int i; char current_char; Character c; char c1; boolean ret=true; for ( i=0; i < exp.length(); i++ ) { current_char=exp.charAt( i ); if ( is_open_parenthesis( current_char ) ) { c=new Character( current_char ); s.push( c ); } else if ( is_closed_parenthesis( current_char ) ) { if ( s.isEmpty() ) { ret=false; break; } else { c=(Character)s.pop(); c1=c.charValue(); if ( !parentheses_match( c1, current_char ) ) { ret=false; break; } } } } if ( !s.isEmpty() ) ret=false; return ret; } }
    token 检查。检查表达式语法。确保表达式所有部分都被认为是合法的。

    表达式开头的检查(请参阅清单 4确保表达式从合法的符号开始。不可以用操作符、逗号或闭括号作为表达式的开始符。





    清单 4. 正确的表达式开头的检查


    private static boolean begin_check( Vector tokens, Range r, StringBuffer err ) { char mark; Token t; t=(Token)tokens.elementAt( 0 ); mark=t.mark; if ( mark=='P' ) err.append( Messages.begin_operator ); else if ( mark==')' ) err.append( Messages.begin_parenthesis ); else if ( mark=='Z' ) err.append ( Messages.begin_comma ); else return true; r.start=0; r.end=t.length; return false; }


    表达式末尾的检查。确保表达式以合法符号结束。不可以用操作符、函数、逗号或开括号作为表达式结束符。

    符号序列的检查。检查表达式中的符号序列。在下面的表格中,若 X 轴上的符号和 Y 轴上的符号对应的交界处用 X 作了记号,则相应 X 轴上的符号可以接在 Y 轴上符号的后面。

    表 2. 合法的符号序列
    _ D B H O V F P ( ) Z
    D _ _ _ _ _ _ _
    B _ _ _ _ _ _ _
    H _ _ _ _ _ _ _
    O _ _ _ _ _ _ _
    V _ _ _ _ _ _ _
    F _ _ _ _ _ _ _ _ _
    P _ _ _
    ( _ _ _
    ) _ _ _ _ _ _ _
    Z _ _ _


    函数检查。确保表达式中所有函数的自变量数量正确。

    逗号检查。逗号只能用于分隔函数的自变量。若用于表达式其它地方,就不合法。

    一步一步的求值
    只有能顺利通过以上概括的所有检查的表达式,W3Eval 才求值。从而确保内建于 W3Eval 中的前提条件不会出现问题。后面的算法用于单步执行表达式求值:
    1. 找出嵌入最深的那对括号。
    2. 在这对括号中,找出优先级最高的操作符。
    3. 若这对括号中没有操作符:
      • 如果表达式再不包含任何其它的括号,求值(过程)完成。
      • 如果表达式包含括号,但不包含操作符,则存在一个函数。对函数求值,然后转到步骤 5。
    4. 获取操作数并执行运算。
    5. 从向量中除去用过的符号并在同一位置放入结果。
    6. 除去冗余括号。
    7. 将向量中剩余的符号结合到字符串并在屏幕上显示结果。
    现在,我们将更为详细的查看算法的每一步,同时查看大部分有意思的代码片段。

    步骤 1:为避免括号的处理,W3Eval 确定哪个子表达式处于嵌套最深的那对括号中。这项任务需要两步。第一步,W3Eval 必须找出第一个闭括号:

    清单 5. 找出第一个闭括号


    public static int pos_first_closed_parenthesis( Vector tokens ) { Token t; for ( int i=0; i
    第二步,找出与第一步找到的闭括号相匹配的开括号,如清单 6 所示





    清单 6. 找出匹配的开括号


    public static int pos_open_parenthesis( Vector tokens, int closed_parenthesis ) { int i; Token t; i=closed_parenthesis-2; while ( i>=0 ) { t=(Token)tokens.elementAt( i ); if ( t.mark=='(' ) { return i; } i--; } return 0; }


    步骤 2:要实现求值的单步执行,W3Eval 在嵌套最深的那对括号中找出优先级最高的操作符。(操作符的优先级已硬编码到 applet 中;请参阅参考资料以获取完整的代码清单。)

    清单 7. 找出优先级最高的操作符


    public static int pos_operator( Vector tokens, Range r ) { byte max_priority=Byte.MAX_VALUE; int max_pos=0; byte priority; String operator; Token t; for ( int i=r.start+2; i<=r.end-2; i++ ) { t=(Token)tokens.elementAt( i ); if ( t.mark!='P' ) continue; priority=((Operator)t.token).priority; operator=((Operator)t.token).operator; if ( priority < max_priority || ( operator.equals("^") || operator.equals("**") ) && priority == max_priority ) { max_priority=priority; max_pos=i; } } return max_pos; }
    步骤 3:如果表达式中不包含其它括号,求值的过程就完成。如果表达式包含括号,但不包含操作符,则存在需要求值的函数。

    清单 8. 检查是否还有其它操作符


    ...int poz_max_op=pos_operator( tokens, range );// if there are no operatorsif ( poz_max_op==0 ) { if ( no_more_parentheses ) { return false; } else { double result; result=function_result( tokens, range.start-1 ); function_tokens_removal( tokens, range.start-1 ); t = new Token ( new Double(result), 'D', 0, 0 ); tokens.setElementAt( t, range.start-1 ); parentheses_removal( tokens, range.start-1 ); return true; } }...
    步骤 4:所有的操作符都是二元的,也就是说第一个操作数位于操作符之前,第二个操作符位于操作符之后。

    清单 9. 获取操作数并执行运算


    ...double operand1, operand2;// first operand is before...t=(Token)tokens.elementAt( poz_max_op-1 );operand1=operand_value( t );// ...and second operand is after operatort=(Token)tokens.elementAt( poz_max_op+1 );operand2=operand_value( t );// operatort=(Token)tokens.elementAt( poz_max_op );String op=((Operator)t.token).operator;double result=operation_result( operand1, operand2, op );tokens.removeElementAt( poz_max_op+1 );tokens.removeElementAt( poz_max_op );t = new Token ( new Double(result), 'D', 0, 0 );tokens.setElementAt( t, poz_max_op-1 );parentheses_removal( tokens, poz_max_op-1 );...
    操作数可以是变量,还可以是十进制、十六进制、八进制或二进制数。

    清单 10. 获取操作数


    public static double operand_value( Token t ) { if ( t.mark=='V' ) return ((Variable)t.token).value; else if ( t.mark=='D' ) return ((Double)t.token).doubleValue(); else if ( t.mark=='H' ) return base_convert( ((String)t.token).substring(2), 16 ); else if ( t.mark=='O' ) return base_convert( ((String)t.token).substring(2), 8 ); else if ( t.mark=='B' ) return base_convert( ((String)t.token).substring(2), 2 ); }
    接下来的方法将不同计数制的数转化为十进制的形式。

    清单 11. 将数转化为十进制数


    public static long base_convert( String s, int base ) { long r=0; int i, j; for ( i=s.length()-1, j=0; i>=0; i--, j++ ) r=r+digit_weight( s.charAt( i ) )*(long)Math.pow( base, j ); return r; }public static int digit_weight( char c ) { if ( Character.isDigit( c ) ) return c-48; else if ( 'A'<=c && c<='f' ) return c-55; else if ( 'a'<=c && c<='f' ) return c-87; return -1; }
    一旦确定操作数和操作符后,就可以执行运算了,如清单 12 所示。

    步骤 5:在这步中,W3Eval 从向量中除去用过的符号并在同一位置放入结果。对于函数求值这类情况,除去的是函数、括号、自变量和逗号;而对于操作符求值这类情况而言,除去的则是操作数和操作符。

    步骤 6:在求值的这一步,W3Eval 从表达式中除去冗余括号。

    清单 13. 除去冗余括号


    private static void parentheses_removal( Vector tokens, int pos ) { if ( pos>1 &&&& ((Token)tokens.elementAt( poz-2 )).mark!='F' &&&& ((Token)tokens.elementAt( poz-1 )).mark=='(' &&&& ((Token)tokens.elementAt( poz+1 )).mark==')' || pos==1 &&&& ((Token)tokens.elementAt( 0 )).mark=='(' &&&& ((Token)tokens.elementAt( 2 )).mark==')' ) { tokens.removeElementAt( poz+1 ); tokens.removeElementAt( poz-1 ); } return; }
    步骤 7:在求值的最后一步,向量中剩余的符号被结合到字符串,并在屏幕上显示。

    清单 14. 结合符号并显示结果


    public static String token_join( Vector tokens ) { String result=new String(); Token t; for ( int i=0; i < tokens.size(); i++ ) { t=(Token)tokens.elementAt( i ); if ( t.mark=='D' ) { double n=((Double)t.token).doubleValue(); result=result + formated_number( n ); } else result=result + t.token; if ( result.endsWith( ".0" ) ) result=result.substring( 0, result.length()-2 ); result=result + " "; } return result; }
    结论
    本文分析了一个 applet ,它能一步一步的对算术表达式求值。同时还按顺序回顾了最有意思的代码片段,并论述了两种不同的表达式求值方法。

    下一版 W3Eval 有望在各方面得到增强,包括有能力添加用户定义的功能;支持分数、复数和矩阵;改良的图形用户界面(GUI);大小和速度优化以及安全性方面的增强。我鼓励您提供您自己对于增强方面的设想。

    我希望您会发现 W3Eval 是个对表达式求值有益的在线工具,它在某种程度上比经典的方法更简单自然。我还期待这里谈到的代码和算法使您明白 Java 语言有助于处理数学问题。

    参考资料
    • W3Eval applet 是免费的,它的帮助有助于您解决问题。
    • 这张表格展示了 W3Eval 操作符的优先级
    • 请阅读波兰数学家 Jan Lukasiewicz 的传记。
    • Donald Knuth,计算机科学领域卓越的学者,曾详尽的就算法的设计和分析撰写和演讲。他的主页提供最近出版的有关其作品的论文和信息的链接。
    • 有兴趣随意编写 applet 吗?可以查看我们的教程 Building a Java applet(developerWorks,1999 年)以获得一步一步的指导。
    • 您会觉得 Java FAQ 很有用。
    • 还有很多有关 applet 的信息在 Peter Van Der Linden(Prentice Hall PTR/Sun Microsystems 出版社出版,1998 年 12 月)的Just Java 2 中。
    • 由 Ken Arnold、James Gosling 和 David Holmes 撰写的 The Java Programming Language(Addison Wesley 出版社出版,2000 年 12 月)包含有益的关于集合的信息。
    • 学习 Martin Bastiaan 的“A Walk in the Park”(developerWorks,1998 年 1 月),了解更多有关 applet 的知识。
    • VisualAge for Java 使 applet 的开发变得轻而易举。
    • developerWorks Java 技术专区查找更多 Java 参考资料。

    关于作者
    Nikola Stepan 是 ABIT Ltd. 的软件工程师,他在那里从事银行业软件的设计和开发。他有广博的信息系统方面的学术背景和丰富的编程经验(从低级编程到信息系统)。他特别喜欢面向对象编程语言、关系数据库、因特网编程和系统编程。他于 1999 年在克罗地亚 Varazdin 的 Faculty of Organisation and Informatic 获得信息系统学士学位。他会说克罗地亚语、英语和一点德语。请通过 nikola.stepan@vz.tel.hr 与 Nikola 联系。
    __________________
    “日本固有新奇的武器,我当以热血应付;日本固有猛烈的枪炮,我当以头颅拼挡。”
    “作为军人,志在以身报国,苟有一线之机不减,自应鼓舞勇气,而为国家尽其最后之牺牲。凡为官为吏,不过一时职业之选择,民族之保存,始为骨头之归宿!”

    posted @ 2005-12-23 16:28 Ben 阅读(1319) | 评论 (0)编辑 收藏

    如何通过Goool查找专业文献资料

    如何通过Goool查找专业文献资料
    转自:http://www.readfree.net/html/200512/122142.html


    第一讲
    推荐先读读google从入门到精通等文章.
    我们了解常规搜索方式,但每个人都会搜索出不同结果,为什么?核心问题在于关键词选择不同。
    关键的分析必须保证两点:
    一是专业性,即这个词是很精的,可能蚧愕乃阉鹘峁蚨噬踔量梢怨忠坏悖×勘苊獯笾诨拇剩鏽et,site等。即使需要大众化词,如password,username,但若加入一两个特征词,则结果将大大简化。
    二是具有代表性,也即这个词具有代表意义,也即它在包含你所需网页内,它在出现的可能,以免一些有用信息被遗漏。
    如何达到上述两个要求?我们必须分析网页中字词出现的特点,以及本学科专业词汇特征。

    大家看看yahoo,google等medicine和science--biology条目下的分类,发现许多相关的词均在内,如
    http://libinfo.uark.edu/eresources/eresources.asp
    医学有关的都在Science & Technology 大条目下,又细分为:
    Agriculture & Food | Biology | Botany | Chemistry | Computer Science | Engineering | Environmental Dynamics | Geology | Kinesiology | Mathematics | Medicine | Nursing | Physics | Psychology | Statistics | Zoology。
    因此如果仅以medicine检索,就会漏掉不少很有价值的信息,特别是漏掉的专业的。
    其次,在medicine下又有很多数据库,如:EBSCO OVID,PROQUEST还有各大出版社自己的万能密码。

    第二讲
    主要讲定点搜索和遍搜索的区别及应用。
    所谓定点搜索,即指定找某个数据库相关信息,或某篇文章。
    遍搜索是指在网上任意逛逛,找些pswd,或者无心插柳柳成荫。
    (1)定点数据库和期刊搜索。还是同第一讲一样,主要分析关键词的选择。当然关键词之一是这个数据库的名称。大家注意了:数据库名称一定要用全称和简称都试试。
    关键词之二是free,ID,password,user name。
    为什么这个关键词?其实这些只能称作是一个关键词,因为它们具有同性或不相容性。如elservier数据库,你最好不要用username和password,因为它主要是采用IP限制的。因而你的重点放在pxory!而不是上述的任何一个。而找某一杂志,则多用user name 和ID/password合用(注:ID/password只可用一个!),因为杂志往往个人购买,便拥有帐号了。
    关键词三:这些数据库可能出现的地方?大学图书馆最多!即使是杂志,图书馆也较个人帐号多。那么图书馆主页上有哪些关键词?library,database,trial,free....,可看看国内一些图书馆的主页,仔细分析比较,便能找到一些共性的东西。
    (2)定点文章搜索。
    文章,在国外通用PDF格式,因而文章搜索必须用PDF这个核心内容。即找后缀为PDF的东东,语法:filetype:PDF 这是关键之一
    关键词之二:找你所需文章的题或文摘中最怪的词!而不是常用词。(不要用很专业的词往往能找到相近的文章,所谓无心插柳了)
    命中率高,但最好是题目中出现的词,为什么?因为往往许多个人站点收录了不少文章,而这些文章往往是以题目名称作为索引的。
    第三讲
    专业文献搜索技巧

    1 查找某本专业刊物的登录密码,如Brain Res
    首先选关键词:杂志名(Brain Res),登录(sign in),密码(password)
    这样成功率并不高,其实细细看来,不应有登录,因为许多提供密码的地方,并不出现登录这个词,而多出现用户名(user name),而且杂志名多用全称(brain research),再试试!哦,成功了!
    2 查找某篇文章的全文,尤其是外文文献,许多全文服务均需收费。
    当然可先按第一种方法搜索一下,看看有无密码可寻,若无,则找到该篇文章的特殊字段(key words),然后搜索PDF文件。不过这有几个条件,一是该杂志确已上网,有明确地址,其二,一般需在1997年以后文献才可。
    举例:Gattullo D, Pagliaro P, Marsh NA, Losano G。New insights into nitric oxide and coronary circulation.Life Sci 1999;65(21):2167-74。
    这篇文章是收费的。采用:inurldf:Gattullo Pagliaro coronary,结果24项,找到其中的第2页,有下面一项Life Sciences [Volume 65, Issue 21, Pages 2167-2268 (1999)]
    ... 1. New Insights into Nitric Oxide and Coronary Circulation, Pages
    2167-2174 D. Gattullo, P. Pagliaro, NA Marsh and G. Losano 2. ...
    147.46.94.112/journal/sej/j_l/l339.htm - 14k - 网页快照 - 类似网页
    打开网页快照,第一篇即是其目录,下载即可!OK!成功

    2 查找专业软件的破解软件或注册码
    常规软件的注册码很好找,但专业软件太少,而且注册码也少,破解更少,如何找?
    如找origin 6.1版的破解版,或注册码。不管采用网易、搜狐等软件搜索,均找不到该软件。那么只好借用特殊搜索了。
    分析:一般有些破解软件的页面一般至少有以下一些信息:软件名称,版本,序列号(serial number, OR sn),破解(crack, OR CRK),提供下载的地方有.ZIP字样(压缩文件为多)。为了方便起见,也防止版本太精确反而不易搜索的特点,在googlek 输入
    origin 破解, 哦!OK!成功!如果其它的软件一次搜索的结果太多的话,则考虑加6.1以减小其搜索范围。或搜索结果太少且不是需要的话,将破解换为"注册码"试试,一般效果不错。
    3 查找中文文献的免费全文
    如我知道重庆维普提供免费全文服务,但目前许多站点都不能用了。另外,还有万方数据库、CNKI也提供,那么我如何查到这些数据库的免费入口呢?
    这需要一定的技巧,采用google或百度试试:输入:重庆维普 密码
    哦!66项!仔细找一找,必有结果!OK!

    第四讲
    这一讲讲百度与google比较
    搜索英文不必说用google,搜索中文呢?
    很多人并不了解它们更新的情况,google发展早,因而它贮存了大量旧的信息,百度发展迟,信息较新。
    更新速度:对中文google一般半月至一月一更新,而且仅搜索到三级链接,三级以下便不在搜索,那么我如何看到最新的google搜索的结果呢?这个站点:
    http://www3.google.com/,可见google采用不同服务器逐步更新的。百度的更新较快,半月一次,最快一周。那么如何衡梁这半月与一月的差剧与价值?
    对于一些试用数据库,有效期短,或象万方等一月一换密码,最好选用百度,现在维普老是打一枪换一个地方,因而也只好用百度了,google往往搜索出来的结果已过期了。而能长期使用的密码或数据库,一般象国外的(国内有没有,我真不知道),最好用google,毕竟技术更老道一些,搜索出的结果更多,更广!

    第五讲
    关于关键词
    关键词组合:
    nurse journal password
    new medicine password
    What's New medicine password
    périodiques électroniques password( 注意了,不是英文字母样!)
    biomedical library password
    LWW Journal Collection password
    Bibliotekets databaser password
    Kluwer Online password
    journalwebsite password
    基本路子仍是数据库+password+补充性关键词(或称定向性关键词)
    所谓定向性关键词是将你的检索范围定于某一可能的区域,如图书馆、个人站点,以缩小检索范围。如单个杂志,可定位于个人,若是数据库检索,则宜加library,因为个人是不会买数据库的。
    同时另一个定向是生物和医学,所用的关键词medicine,biology,biomed.
    当然仍可加第三定向关键词,如杂志(journal)、免费(free)、在线(online),但一定要注意第三关键词的特征性不强,要选择使用,不可过用,否则会将一大批可能有用的站点排除掉,切记!
    但这主要针对国外的,而国内的一般多在各大学图书馆内,常用密码、免费、杂志、数据库名等搜索,效果较好。
    但对于有些杂志,如sciencedirect,Ideallibrary多采用IP验证方式,一般密码并不能用,这时多采用代理服务器方式,因而如何找到有效的代理太重要的。如清华的elsevier便是代理。

    第六讲
    本讲讲关键词联合使用。
    国内图书馆提到数据库往往只提***数据库,而国外图书馆多列出该数据库内各种杂志名,而且多按字母分类。因而为了提高检索的准确率,一般将同一数据库内的杂志的首字母相同的杂志名用两到三个联合搜索,再结合前面讲的加用其它关键词,能有效缩小检索范围,翕中率极高。从这里可以看到,如果透彻分析一些图书馆内主页设计的特征,是搜索的关键。
    如检索brain research,可列出brain research bulltin,同时检索,效果要好些。

    第七讲
    搜索代理服务器技巧:
    中文:
    代理 维普(或其它数据库名) 数据库,能找到一些,但国内一般真正使用代理的较少。
    英文:
    proxy 数据库名 IE netscape
    效果非常好,但一定要注意,许多地方不仅用代理服务器,而且需密码认证,不可过于乐观!应认真鉴别。

    第八讲
    找特定文件名的文件,尤其是PDF、ZIP、DOC、TXT、RAR、EXE、RM、Mp3,MOV这些文件名都是大家想找的重点,至于各是什么类型文件,请上网查一下便知道了,这里不多说了。
    方法是利用语法filetype:后缀名。
    如找PDF文件,在正常关键词后面加filetype:PDF即可,搜索结果全是PDF文件。这是我写的另一篇,可参考:
    http://bbs.bioon.com/bbs0/dispbb ... D=839&ID=839&page=1
    找特定题目的网页语法intitle:网站
    查找友情链接:
    "link:"(英文单字link后加冒号)用于搜索链接到某个URL地址的网页。可以了解有哪些网页把链接指向您的网页
    查找特定站点:
    site:www.*.com
    如 金庸 古龙 site:sina.com.cn
    但不可加入http://或/这类,否则是错的
    cache”用来搜索GOOGLE服务器上某页面的缓存,通常用于查找某些已经被删除的死链接网页,相当于使用普通搜索结果页面中的“网页快照”功能。

    示例:查找GOOGLE缓存的中文yahoo首页
    搜索:“cache:www.yahoo.com.cn

    info用来显示与某链接相关的一系列搜索,提供cache、link、related和完全包含该链接的网页的功能。

    示例:查找和新浪首页相关的一些资讯。
    搜索:“info:www.sina.com.cn
    结果:www.sina.com.cn的网页信息。

    示例:查找美国教育网上的宇宙大爆炸jpg图片
    搜索:“BIG BANG filetype:jpg site:edu”
    结果:搜索有关 BIG BANG filetype:jpg site:edu 的图片

    第九讲
    专讲一个特殊语法,很有用。inurl
    “inurl”语法返回的网页链接中包含第一个关键字,后面的关键字则出现在链接中或者网页文档中。有很多网站把某一类具有相同属性的资源名称显示在目录名称或者网页名称中,比如“MP3”、“GALLARY”等,于是,就可以用INURL语法找到这些相关资源链接,然后,用第二个关键词确定是否有某项具体资料。INURL语法和基本搜索语法的最大区别在于,前者通常能提供非常精确的专题资料。

    示例:查找MIDI曲“沧海一声笑”。
    搜索:“inurl:midi 沧海一声笑”
    结果:已搜索有关inurl:midi 沧海一声笑的中文(简体)网页。
    示例:查找微软网站上关于windows2000的安全课题资料。
    搜索:“inurl:security windows2000 site:microsoft.com”
    结果:已在microsoft.com内搜索有关inurlecurity windows2000 的网页。
    注意:“inurl:”后面不能有空格,GOOGLE也不对URL符号如“/”进行搜索。例如,GOOGLE会把“cgi-bin/phf”中的“/”当成空格处理。
    而一般众多密码或数据库往往出现在链接之中,如查Ideallibrary
    inurl;ideallibrary proxy passowrd(ID)

    “allinurl”语法返回的网页的链接中包含所有作用关键字。这个查询的关键字只集中于网页的链接字符串。

    示例:查找可能具有PHF安全漏洞的公司网站。通常这些网站的CGI-BIN目录中含有PHF脚本程序(这个脚本是不安全的),表现在链接中就是“域名/cgi-bin/phf”。
    语法:“allinurl:"cgi-bin" phf +com”
    搜索:已向英特网搜索allinurl:"cgi-bin" phf +com. 共约有37项查询结果,这是第1-10项 。 搜索用时0.36秒。

    第十讲
    代理:
    国外的数据库,许多需代理,如何搜索到?普通的代理遍地都是,只要用google输入proxy free或代理服务器 免费就能搜索到非常多的代理,但这些代理并不适用于查阅一些著名数据库,好么如何找到?一般有以下几点技巧,我并作简要分析:
    由于这些代理必须要出现于大学内。
    (1)因而如果采用普通的免费代理,则必须保证这种代理在某个大学,这可通过代理测得,其中无特别的技巧。可见下面一个代理服务器帖子的说明
    (2)如果要搜索,则应该将代理服务器限制于大学内,因而其搜索格式应该如下:
    proxy 数据库名 site:edu
    这是标准格式,搜索的数据库较多,但一定注意并不等于搜索出的代理都有用,有些代理还需密码支持,仔细判定。
    其它类似可选关键词也列一些,与上述核心关键词适当组合便可,提高搜索准确率:
    Off-Campus:能提高无密码搜索成功率
    netscape:能提高准确率
    第十一讲
    用google查密码。大多数人用google,仍未能对google有深入地了解。往往用google搜索出大量密码,一用才知道都过期了,尤其是中文的密码,现在更新极度频繁,如何能查到最新的密码很重要。在前面几讲我讲过百度的更新较google快,然而百度对链接分析能力较google差,google能分析到下四层链接,而百度可能只能至第三层,而往往密码出现的位置:大学主页--图书馆---电子数据库---某些数据库密码,从这个分析可以看到,许多密码都出现在主页的第四层下面,百度往往搜索不到(当然第三层也有很多,这是百度长处之一)。因而搜索中文密码google仍很重要,那么如何用最新的google?google的中文数据库一月一更新(太慢了,英文的一天一更新),但 google在全球有数千台服务器,它们对各种语种更新的速度是不同的。并且更新方式采用梯度更新,即先更新某些服务器,后来全面更新。因而我们能利用google最新的服务器搜索,而 goole最新服务器的链接在这里:
    http://www3.google.com.

    posted @ 2005-12-20 18:04 Ben 阅读(601) | 评论 (0)编辑 收藏

    Jsp如何实现网页的重定向

    转自  豆豆技术网
    1.可以使用:

      response.sendRedirect("http://www.foo.com/path/error.html");

      2.可以手工修改HTTP header的Location属性,如下:

    <%
    response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
    String newLocn = "/newpath/index.html";
    response.setHeader("Location",newLocn);
    %>

      3.也可以使用forward:

      <jsp:forward page="/newpage.jsp" />

      请注意:只能在任何输出还没有发送到客户端之前使用这种方式。

      5.6 类似global.asa的做法

      在JSP中没有global.asa的对应物。但可以有一个workaround来运行。例如,如果你需要存储或存取application scope变量,你总是可以创建一个Javabean,并在页面中需要这些变量的地方将它包含进来。

    <jsp:useBean id="globals" scope="application" class="com.xxx.GlobalBean"/>

      但是,也有一些产品具有这样的对应:

      Allaire公司的产品JRun 3.0将提供global.jsa。JRun 2.3.3仍然给予支持,但只对JSP 0.92。当JRun 3.0最终推出时它将支持用于JSP 1.0和1.1的global.jsa。

      你可以从http://beta.allaire.com/jrun30得到JRun 3.0 beta 5

      另外,Oracle的JSP支持globals.jsa。

      5.7 jsp显示当前时间

    <%@ page import="Java.util.*, Java.text.*" %>
    <HTML>
    <HEAD>
    <TITLE>JSP to display the current time</TITLE>
    </HEAD>
    <BODY>
    The current time is:
    <%
    Date now = new Date();
    out.println(DateFormat.getTimeInstance().format(now));
    %>
    </BODY>
    </HTML>

      5.8在JSP中创建目录 Mkdir(String path)

    <%@ page import="Java.io.*" %>
    <%!
    String Mkdir(String path)
    {
    String msg=null;
    Java.io.File dir;

    // 新建文件对象
    dir =new Java.io.File(path);
    if (dir == null) {
    msg = "错误原因:<BR>对不起,不能创建空目录!";
    return msg;
    }
        if (dir.isFile()) {
        msg = "错误原因:<BR>已有同名文件<B>" + dir.getAbsolutePath() + "</B>存在。";
        return msg;
        }
        if (!dir.exists())
    {
        boolean result = dir.mkdirs();
            if (result == false) {
        msg = "错误原因:<BR>目录<b>" + dir.getAbsolutePath() + "</B>创建失败,原因不明!";
            return msg;
        }
       // 如果成功创建目录,则无输出。
        // msg ="成功创建目录: <B>" + dir.getAbsolutePath() + "</B>";
        return msg;
        }
      else {
          msg = "错误原因:<BR>目录<b>" + dir.getAbsolutePath() + "</b>已存在。";
        }
      return msg;
    }
    %>
    <%
    String filepath = "/usr/home/hoyi/html/dir";
    String opmsg = Mkdir(filepath);
    %>

      5.9将return 转为<br>函数

    public static String returnToBr(String sStr)
    {
    if (sStr == null // sStr.equals(""))
    {
    return sStr;
    }

    String sTmp = new String();
    int i = 0;

    while (i <= sStr.length()-1)
    {
    if (sStr.charAt(i) == '\n')
    {
    sTmp = sTmp.concat("<br>");
    }
    else
    {
    sTmp = sTmp.concat(sStr.substring(i,i+1));
    }
    i++;
    }
    return sTmp;
    }

    posted @ 2005-12-20 14:26 Ben 阅读(392) | 评论 (1)编辑 收藏

    Jsp 传数组给Applet

    <body>
      <%
      String[] choosedlist = (String[])session.getAttribute("choosedlist");
      String curshowType = (String)session.getAttribute("LowORHigh");
            String curpicType = (String)session.getAttribute("type");
            //System.out.println("Movie" + curshowType + curpicType );
      //for(int i = 0; i<choosedlist.length; i++){
       //System.out.println(choosedlist[i]);
      //}
     %>
     
     <APPLET
     CODE = "cn.com.ztesoft.Animation.Animation.class"
     codebase = "."
     WIDTH = 740 
     HEIGHT = 400 
     NAME = "TestApplet" 
     ALIGN = middle 
     VSPACE = 0 
     HSPACE = 0>
     <%
     for (int a=0; a<choosedlist.length; a++)
     {%>
      <PARAM NAME = "paramA<%=a%>" VALUE = "<%=choosedlist[a]%>">
     <%}%>
     <PARAM NAME = "ParamNumber" VALUE = "<%=choosedlist.length%>">  
     <PARAM NAME = "curshowType" VALUE = "<%=curshowType%>">
     <PARAM NAME = "curpicType" VALUE = "<%=curpicType%>">
     </APPLET>   
     <a href="gms.jsp">返回</a>
      </body>

    posted @ 2005-12-20 14:12 Ben 阅读(777) | 评论 (0)编辑 收藏

    SWT……内幕?

    注: 转载至 JR  
    SWT……内幕?
    FooSleeper
    原文:
    http://groups.yahoo.com/group/straight_talking_java/
    http://groups.yahoo.com/group/straight_talking_java/messages/24236

    翻译整理:FooSleeper
    最后修改:2004-03-03


    译注:本文来自straight_talking_java@yahoogroups.com讨论组,已经是一年多前的文章。Alan Williamson是Java Developers Journal的编辑,下文来自他在IBM的一个消息来源。SWT和Swing的论争我见过不少,Netbeans和Eclipse的也同样多。译者翻译此文并不是要激起什么争执,也不是支持哪一方(虽然我的确是站在SWT一边的),更不是要攻击Amy。我最重要的理由是,这是一篇有趣的文章。里面有内幕、线人、公司政治、垄断巨头、美女、商界风云……足够拍一出电影。有趣,这就够了。不过此文反映了IBM对Swing的看法和SWT的由来,还是有一点营养的。

    From:  Alan Williamson <alan@n-ary.com>
    Date:  Wed Nov 6, 2002  10:31 am 
    Reply-To: <straight_talking_java@yahoogroups.com>
    To: <straight_talking_java@yahoogroups.com>
    Subject:  SWT ... the scoop?(SWT……内幕?)

    好了这就来……阅读……消化……再阅读……再消化……
    ;-) 

    --------------------------------
    谢谢你的回复。我很乐意给你提供Swing和SWT背后的一些信息,既然你还把我当作你秘密的“IBM内幕线人”。

    要想弄清楚为什么一切都被弄得如此混乱,要从几年前只存在AWT的时候说起。SUN当时已经建立了一套基本的可移植控件类,这些类映射到不同操作系统上的原生窗口组件(native widget),显然下一步应该继续增强这套模型,除了初始的CUA 92组件(文字、按钮等等),再继续加上表格、树、记事本、滑块等等……当时的AWT还满是漏洞,远不能称为可靠,还需要SUN的coder们去修补。SUN的developer们如Graham和Otto总是习惯于公开把他们的bug归咎为操作系统的差异,比如“Windows和OS/2的焦点次序不同”或者“在……之间Ctrl-X的行为不一样”,以及其他苍白的托辞,好让批评的火力从SUN太早释出代码这个问题的真相上移开。然后Amy Fowler来到了SUN。不是我大男子主义,Amy是个聪明的美女,大多数呆头呆脑只懂技术的开发人员都要被她捏在手里。

    Amy来自一家Smalltalk公司,叫做Objectshare,在那里她负责搞UI类库。跟Java相比Smalltalk的历史有些悲惨,曾几何时有3家庞大的Smalltalk公司——IBM、Parc-Place和Digitalk。在90年代初期3家公司的市场份额大致相等,生活是美好的。Parc-Place采用仿窗口部件(emulated widgets)的设计(即Swing的设计),IBM和Digitalk则采用原生窗口部件(native widgets)。后来IBM压倒了另外两家,因此他们打算合并成一家,假设叫做Parc-Place Digitalk。随后当他们试图将他们的产品融合到一个叫做Jigsaw的计划中时爆发了一场大战,计划由于政治原因失败了(开发人员实际上已经能让它运转起来),就因为原生和仿造两派的死战。Amy赢得了精神上的胜利,不过在IBM我们赢得了他们所有的生意,因为这两家公司在一整年里除了吵架什么都没做。当尘埃落定之后PPD(Parc-Place Digitalk当时已改名为Objectshare,跟Windscale改名为Sellafield的原因相同——让人们淡忘之前发生的灾难)的股票价格从60美元掉到了低于1美元1股。他们因为伪报收入被NASDAQ摘牌,从此消失。此时SUN正走上与PPD类似的技术方向,于是PDD的技术人员都把他们的简历投到了SUN。Amy被雇佣了,她承诺通过轻量级方案解决所有窗口组件的问题,因此说服SUN管理层让她当了GUI开发部门的头头。她是拿着“这里原来的人都搞砸了,我是来解决的”的钥匙进来的。随后Amy雇佣了所有她过去在Parc-Place的旧朋友,让他们来开发Swing。

    显然Swing应该做的是仅仅成为一个绘制框架,给那些希望创建地图软件或者绘图软件的人们使用,无论如何,应该围绕AWT类库来建造它,按钮之类的东西仍然交给AWT来管。SUN的人比如Philip和Mark已经让AWT能够处理表格、树和记事本(notebook,?),所以Swing的方向应该说很明显了。但那些毁了PDD的人不干,他们非要把一切都弄成轻量级的。由于SUN管理层的无知,再加上Amy无情的政治手段,造成了我们今天所见的混乱局面。Amy还使SUN相信Swing是作为Mozilla项目的一部分与Netscape联合开发的,事实上这只是她的宣传伎俩。

    在IBM,我们从第一天起就憎恶Swing。庞大、满是错误,而且难看至极。原先我们的工具如VisualAge for Java都是用Smalltalk(用的是原生窗口组件)写的,所以当我们将这些工具向Java代码库迁移时,我们需要一套窗口组件。IBM这边的开发人员都是原来搞Smalltalk的那一批人,我们对管理层要求用Swing来构建WebSphere Studio工具都非常不情愿。Swing是个可怕的充满缺陷的怪兽。在WebSphere Studio最初的预览中,当与Microsoft Visual Studio作对比演示的时候,我们所有的客户都讨厌它,就因为它的外观,而不管它的功能有多强。大多数消费者都不会买一辆让人觉得难看的车,哪怕这车有一台出色的引擎。因此我们开始了一个项目,是把我们的Smalltalk原生窗口组件移植到Java上去。这个项目是加拿大的Object Technology International小组做的。这个项目获得了成功,被运用在在我们发布的VisualAge Micro Edition产品中,VisualAge Micro Edition后来成为J2ME开发方面一个非常成功的IDE。但是OTI的人发现,Swing在读取Windows事件方面有极严重的缺陷,我们甚至无法进行SWT(S开始是Simple的缩写,不过后来变成了Standard的缩写)和Swing间的互操作。他们在读事件队列的时候用了一种可能留下内存漏洞的方式,所以我们不得不采用我们自己的查询Windows事件队列的循环,以纠正这个错误。我们试了一次又一次让SUN修复这个错误,但Amy就是听不进去,所以我们才决定SWT和AWT/Swing不能共存。我们甚至在SWT中定义了自己的Point和Rectangle类——整个工具包对AWT或Swing都没有任何依赖。我们把这个工具包放到了Eclipse中,这是一个工具平台,它的总体设计目标就是要战胜Micrsoft和Visual Studio。Eclipse是开源的,所以任何人都可以在上面构建自己的东西,我们已经有像TogetherSoft和Rational这样的公司移植到了上面。我们的竞争者是Microsoft,所以我们所有努力和注意力都是从正面针对Microsoft。

    不管怎么说SUN对此非常不满。他们的Netbeans跟Eclipse做的是相同的事,因此他们向IBM高层抱怨。他们认为SWT是要将你绑到Windows上,这纯粹是胡说,因为SWT能通过GTK在Mac/Linux上运行,以及一大堆嵌入式平台。他们拒绝让Eclipse获得Java认证,因为里面有原生代码,所以Eclipse产品必须很小心地使用单词“Java”这个SUN的商标。Eclipse甚至不能把自己称为一个Java IDE,SUN已经威胁过要采取法律行动来制止IBM在任何时候把Eclipse称作一个Java IDE。结果之一就是IBM在Eclipse上创建的GUI设计工具,允许你构建Swing/AWT GUI,却不让你往里面拖放SWT窗口控件。

    将SWT从Eclipse中分离出来是完全可能的,只需要把DLL抠出来放到路径中,并使用窗口组件工具包来给你的银行或者保险或者其他什么应用程序开发GUI。再次说明,我们无法更进一步,因为SUN把我们的双手绑上了。虽然作为Eclipse开放源码协议的一部分,CPL允许我们提供这样的解决方案,但SUN已经很清楚地表明他们不希望我们这样做。

    对于用户社区来说,无论IBM和SUN的最终动机是什么,我发现有一点总是很有趣:喜爱Swing的人总会说“一旦你花上几年时间去掌握它,你就能正确地使用它”,这基本上是他们在试图证明和维护他们辛苦得来的用途有限的专门技术;而SWT的拥护者们说的是“哇,这真快,这跟原生的一样,还可以用XP皮肤……它还又轻又小”。有一句话是我喜欢的,我们的一个用户说,Swing就像Java决定不通过操作系统来实现原生的IO,而是通过磁头马达API自己来读磁盘的扇区。Swing基本上就是这样的,它拿着个底层的“paint(Graphics)”方法,自己来绘制所有的窗口组件。
    --------------------------------

    后记:现在的情况已经有所不同,SWT到底还是单独发布了,VE也承诺在1.0版的时候支持SWT的GUI设计。 

    posted @ 2005-12-12 18:23 Ben 阅读(289) | 评论 (0)编辑 收藏

    .Net在SqlServer中的图片存取技术 选择自 kwklover 的 Blog

     

    本文总结如何在.Net Winform和.Net webform(asp.net)中将图片存入sqlserver中并读取显示的方法
    1,使用asp.net将图片上传并存入SqlServer中,然后从SqlServer中读取并显示出来
    一,上传并存入SqlServer
     数据库结构
      create table test
      {
         id identity(1,1),
         FImage image
      }
      相关的存储过程
      Create proc UpdateImage
      (
         @UpdateImage Image
      )
      As
      Insert Into test(FImage) values(@UpdateImage)
      GO

    在UpPhoto.aspx文件中添加如下:
    <input id="UpPhoto" name="UpPhoto" runat="server" type="file">
    <asp:Button id="btnAdd" name="btnAdd" runat="server" Text="上传"></asp:Button>

    然后在后置代码文件UpPhoto.aspx.cs添加btnAdd按钮的单击事件处理代码:
    private void btnAdd_Click(object sender, System.EventArgs e)
    {
            //获得图象并把图象转换为byte[]
            HttpPostedFile upPhoto=UpPhoto.PostedFile;
            int upPhotoLength=upPhoto.ContentLength;
            byte[] PhotoArray=new Byte[upPhotoLength];
            Stream PhotoStream=upPhoto.InputStream;
            PhotoStream.Read(PhotoArray,0,upPhotoLength);

            //连接数据库
            SqlConnection conn=new SqlConnection();
            conn.ConnectionString="Data Source=localhost;Database=test;User Id=sa;Pwd=sa";

            SqlCommand cmd=new SqlCommand("UpdateImage",conn);
            cmd.CommandType=CommandType.StoredProcedure;

            cmd.Parameters.Add("@UpdateImage",SqlDbType.Image);
            cmd.Parameters["@UpdateImage"].Value=PhotoArray;

            //如果你希望不使用存储过程来添加图片把上面四句代码改为:
            //string strSql="Insert into test(FImage) values(@FImage)";
            //SqlCommand cmd=new SqlCommand(strSql,conn);
            //cmd.Parameters.Add("@FImage",SqlDbType.Image);
            //cmd.Parameters["@FImage"].Value=PhotoArray;

     conn.Open();
     cmd.ExecuteNonQuery();
     conn.Close();
    }

    二,从SqlServer中读取并显示出来
    在需要显示图片的地方添加如下代码:
    <asp:image id="imgPhoto" runat="server" ImageUrl="ShowPhoto.aspx"></asp:image>

    ShowPhoto.aspx主体代码:
    private void Page_Load(object sender, System.EventArgs e)
    {
         if(!Page.IsPostBack)
         {
                    SqlConnection conn=new SqlConnection()
                    conn.ConnectionString="Data Source=localhost;Database=test;User Id=sa;Pwd=sa";
                   
                    string strSql="select * from test where id=2";//这里假设获取id为2的图片
                    SqlCommand cmd=new SqlCommand()
                    reader.Read();
                    Response.ContentType="application/octet-stream";
                    Response.BinaryWrite((Byte[])reader["FImage"]);
                    Response.End();
                    reader.Close();
         }
    }


    3,在winform中将图片存入sqlserver,并从sqlserver中读取并显示在picturebox中

    1,存入sqlserver
    数据库结构和使用的存储过过程,同上面的一样
     1.1,在窗体中加一个OpenFileDialog控件,命名为ofdSelectPic
     1.2,在窗体上添加一个打开文件按钮,添加如下单击事件代码:
        Stream ms;
      byte[] picbyte;
      //ofdSelectPic.ShowDialog();
      if (ofdSelectPic.ShowDialog()==DialogResult.OK)
      {
       if ((ms=ofdSelectPic.OpenFile())!=null)
       {
        //MessageBox.Show("ok");
        picbyte=new byte[ms.Length];
        ms.Position=0;
        ms.Read(picbyte,0,Convert.ToInt32(ms.Length));
        //MessageBox.Show("读取完毕!");

        //连接数据库
        SqlConnection conn=new SqlConnection();
        conn.ConnectionString="Data Source=localhost;Database=test;User Id=sa;Pwd=sa";

        SqlCommand cmd=new SqlCommand("UpdateImage",conn);
        cmd.CommandType=CommandType.StoredProcedure;

        cmd.Parameters.Add("@UpdateImage",SqlDbType.Image);
        cmd.Parameters["@UpdateImage"].Value=picbyte;

        conn.Open();
        cmd.ExecuteNonQuery();
        conn.Close();

        ms.Close();
        }
       }

    2,读取并显示在picturebox中
     2.1 添加一个picturebox,名为ptbShow
     2.2 添加一个按钮,添加如下响应事件:
          SqlConnection conn=new SqlConnection();
     conn.ConnectionString="Data Source=localhost;Database=test;User Id=sa;Pwd=sa";

     string strSql="select FImage from test where id=1";

     SqlCommand cmd=new SqlCommand(strSql,conn);

     conn.Open();
     SqlDataReader reader=cmd.ExecuteReader();
            reader.Read();

     MemoryStream ms=new MemoryStream((byte[])reader["FImage"]);


     Image image=Image.FromStream(ms,true);

            reader.Close();
            conn.Close();

     ptbShow.Image=image;

    posted @ 2005-12-12 18:20 Ben 阅读(267) | 评论 (0)编辑 收藏

    java中利用POI处理Excel

    package txtToExcel;

    import org.apache.poi.hssf.usermodel.HSSFCellStyle;
    import org.apache.poi.hssf.usermodel.HSSFDataFormat;
    import org.apache.poi.hssf.usermodel.HSSFFont;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFCell;

    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.util.ArrayList;

    /**
     * @author lx
     *
     */
    public class TxtToExecl {
     /** Excel 文件要存放的位置,假定在C盘下 */
     public static String outputFile = "c:\\11.xls";
     
     private static String[] DataOfLine = null;

     private static ArrayList array = new ArrayList();

     public static void main(String argv[]) {
      try {
       String fromPath = "c:/11.txt";// 取得当前目录的路径
       FileReader txtReader = new FileReader(fromPath);// 建立FileReader对象,并实例化为txtReader
       BufferedReader br = new BufferedReader(txtReader);// 建立BufferedReader对象,并实例化为br
       String Line = br.readLine();// 从文件读取一行字符串

       // 判断读取到的字符串是否不为空
       for (int i = 0; Line != null; i++) {
        // System.out.println(Line);//输出从文件中读取的数据
        array.add(Line);
        Line = br.readLine();// 从文件中继续读取一行数据
       }
       DataOfLine = new String[array.size()];
       // System.out.println(array.size());
       array.toArray(DataOfLine);
       br.close();// 关闭BufferedReader对象
       txtReader.close();// 关闭文件
      } catch (FileNotFoundException e1) {
       e1.printStackTrace();
      } catch (IOException e1) {
       e1.printStackTrace();
      }

      try {
       // 创建新的Excel 工作簿
       HSSFWorkbook workbook = new HSSFWorkbook();
       // 在Excel工作簿中建一工作表,其名为缺省值
       // 如要新建一名为"效益指标"的工作表,其语句为:
       // HSSFSheet sheet = workbook.createSheet("效益指标");
       HSSFSheet sheet = workbook.createSheet("FeeOfTel");

       // 创建字体,设置其为红色、粗体
       HSSFFont font = workbook.createFont();
       font.setColor(HSSFFont.COLOR_NORMAL);
       font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
       HSSFCellStyle cellStyle = workbook.createCellStyle();
       //将字体设置到中间
       cellStyle.setFont(font);
       cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
       //将文字设置到右边
       HSSFCellStyle cellStyle1 = workbook.createCellStyle();
       cellStyle1.setAlignment(HSSFCellStyle.ALIGN_RIGHT);
    //    HSSFDataFormat format = workbook.createDataFormat();
    //    cellStyle1.setDataFormat(format.getFormat("0.00"));

       int NumLine = (array.size() / 13);
       System.out.println(NumLine);
       // 在索引0的位置创建行(最顶端的行)
       HSSFRow row = null;
       HSSFCell cell = null;
       for (int j = 0; j <= NumLine; j++) {
        row = sheet.createRow((short) j);
        for (int i = 0; i <= 12 && i + j * 13 < array.size(); i++) {
         // 在索引0的位置创建单元格(左上端
         cell = row.createCell((short) i);

         // 定义单元格为字符串类型
         cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
         cell.setEncoding(HSSFCell.ENCODING_UTF_16);
    //     cell.setCellType(HSSFCell.CELL_TYPE_STRING);
         if (j == 0 || j == NumLine - 1) {
          cell.setCellStyle(cellStyle);
          cell.setCellValue(DataOfLine[i + j * 13]);
         }
         else{
          cell.setCellStyle(cellStyle1);
          cell.setCellValue(DataOfLine[i + j * 13]);
         }
         // 在单元格中输入一些内容
         // System.out.println(DataOfLine[i + j * 13]);
    //     cell.setCellValue(DataOfLine[i + j * 13]);
        }
       }

       // 新建一输出文件流
       FileOutputStream fOut = new FileOutputStream(outputFile);
       // 把相应的Excel 工作簿存盘
       workbook.write(fOut);
       fOut.flush();
       // 操作结束,关闭文件
       fOut.close();
       System.out.println("文件生成...");
      } catch (Exception e) {
       System.out.println("已运行 TxtToExecl() : " + e);
      }
     }
    }

    posted @ 2005-12-12 12:58 Ben 阅读(699) | 评论 (4)编辑 收藏