日历

« 2008-12-02  
 123456
78910111213
14151617181920
21222324252627
28293031   

音乐欣赏

我的好友

统计信息

  • 访问量: 1366
  • 日志数: 13
  • 建立时间: 2007-07-05
  • 更新时间: 2008-11-04

RSS订阅

我的最新日志

  • 针对Excel表格文件操作的编程实现【转】

    2008-11-04


    简介
    通过本文及配套示例源码你可以更加灵活的控制Excel表格文件,其中包括创建新Excel文件、写入表格数据、读取表格数据(包括对原建Excel文件自已手工添加的行、列数据的准确读取),删除已有Excel表格,对表格中指定行、列、单元格进行查询、插入、替换等操作,同时还可以将生成的Excel文件转换为按指定分隔符分隔的其它文本格式的文件。下面是把此方法用VC6编写的示例程序运行效果:



    基本思路
    基础实现方法同上篇文章《直接通过ODBC读、写Excel表格文件》相同,都是通过ODBC来把Excel表格文件当成数据库文件来进行读、写等操作,所以在Excel表格文件中写入的行头名必须是唯一的(不要重名,相当于数据库中的ID值)。本文中对Excel文件的操作都被封装进一个类CSpreadSheet中,通过它我们可以非常简便的实现各种Excel表格数据操作,并且可以对该类进行扩充来满足自己的需求。

    具体实现

    一、 包含Excel文件操作类头文件

    #include "CSpreadSheet.h"
    二、 新建Excel文件,并写入默认数据
    // 新建Excel文件名及路径,TestSheet为内部表名
    CSpreadSheet SS("c:\\Test.xls", "TestSheet");
    
    CStringArray sampleArray, testRow;
    	
    SS.BeginTransaction();
    	
    // 加入标题
    sampleArray.RemoveAll();
    sampleArray.Add("姓名");
    sampleArray.Add("年龄");
    SS.AddHeaders(sampleArray);
    
    // 加入数据
    CString strName[] = {"徐景周","徐志慧","郭徽","牛英俊","朱小鹏"};
    CString strAge[]  = {"27","23","28","27","26"};
    for(int i = 0; i < sizeof(strName)/sizeof(CString); i++)
    {
    	sampleArray.RemoveAll();
    	sampleArray.Add(strName[i]);
    	sampleArray.Add(strAge[i]);
    	SS.AddRow(sampleArray);
    }
    	
    SS.Commit();

    三、 读取Excel文件数据
    CSpreadSheet SS("c:\\Test.xls", "TestSheet");
    
    CStringArray Rows, Column;
    
    //清空列表框
    m_AccessList.ResetContent();
    for (int i = 1; i <= SS.GetTotalRows(); i++)
    {
    	// 读取一行
    	SS.ReadRow(Rows, i);
    	CString strContents = "";
    	for (int j = 1; j <= Rows.GetSize(); j++)
    	{
    		if(j == 1)
    			strContents = Rows.GetAt(j-1);
    		else
    			strContents = strContents +  " --> " + Rows.GetAt(j-1);
    	}
    
    	m_AccessList.AddString(strContents);
    }

    四、 对已存在Excel表格数据进行添加、插入、替换操作
    // 初始化测试行数据,进行添加、插入及替换数据操作演示
    for (int k = 1; k <= 2; k++)
    {
    	testRow.Add("Test");
    }
    	
    SS.AddRow(testRow);		// 添加到尾部
    SS.AddRow(testRow, 2);		// 插入新行到第二行
    SS.AddRow(testRow, 6, true);	// 替换原第四行来新的内容
    SS.AddCell("徐景周", 1,2);    // 添加(不存在)或替换(存在)第二行,第一列单元格内容
    
    SS.Commit();	
    五、 对已存在Excel表格数据进行行、列、单元格查询
    void CExcelAccessDlg::OnQuery() 
    {
    	CSpreadSheet SS("c:\\Test.xls", "TestSheet");
    
    	CStringArray Rows, Column;
    	CString tempString = "";
    
    	UpdateData();
    
    	if(m_strRow == "" && m_strColumn == "")         // 查询为空
    	{
    		AfxMessageBox("行号、列号不能同时为空!");
    		return;
    	}    
    	else if(m_strRow == "" && m_strColumn != "")    // 查询指定列数据
    	{
    		int iColumn = atoi(m_strColumn);
    		int iCols = SS.GetTotalColumns();
    		if(iColumn > iCols)	// 超出表范围查询时
    		{
    			CString str;
    			str.Format("表中总列数为: %d, ", iCols);
    			AfxMessageBox(str + " 查询列数大于Excel表中总列数,请重新输入!");
    			return;
    		}
    
    		// 读取一列数据,并按行读出
    		if(!SS.ReadColumn(Column, iColumn))
    		{
    			AfxMessageBox(SS.GetLastError());
    			return;
    		}
    
    		CString tmpStr;
    		for (int i = 0; i < Column.GetSize(); i++)
    		{
    			tmpStr.Format("行号: %d, 列号: %d ,内容: %s\n", i+1,iColumn,Column.GetAt(i));
    			tempString += tmpStr;
    		}
    		
    		AfxMessageBox(tempString);
    	}
    	else if(m_strRow != "" && m_strColumn == "")     // 查询指定行数数据
    	{
    		int iRow = atoi(m_strRow);
    		int iRows = SS.GetTotalRows();
    		
    		if(iRow > iRows)	// 超出表范围查询时
    		{
    			CString str;
    			str.Format("表中总行数为: %d, ", iRows);
    			AfxMessageBox(str + " 查询行数大于Excel表中总行数,请重新输入!");
    			return;
    		}
    
    		// 读取指定行数据
    		if(!SS.ReadRow(Rows, iRow))
    		{
    			AfxMessageBox(SS.GetLastError());
    			return;
    		}
    
    		CString tmpStr;
    		for (int i = 0; i < Rows.GetSize(); i++)
    		{
    			tmpStr.Format("行号: %d, 列号: %d ,内容: %s\n", iRow, i+1, Rows.GetAt(i));
    			tempString += tmpStr;
    		}
    
    		AfxMessageBox(tempString);
    	}
    	else if(m_strRow != "" && m_strColumn != "")     // 查询指定单元格数据
    	{
    		int iRow = atoi(m_strRow), iColumn = atoi(m_strColumn);
    		int iRows = SS.GetTotalRows(), iCols = SS.GetTotalColumns(); 
    		
    		if(iColumn > iCols)             // 超出表范围查询时
    		{
    			CString str;
    			str.Format("表中总列数为: %d, ", iCols);
    			AfxMessageBox(str + " 查询列数大于Excel表中总列数,请重新输入!");
    			return;
    		}
    		else if(iRow > iRows)
    		{
    			CString str;
    			str.Format("表中总行数为: %d, ", iRows);
    			AfxMessageBox(str + " 查询行数大于Excel表中总行数,请重新输入!");
    			return;
    		}
    
    		// 读取指定行、列单元格数据
    		if(!SS.ReadCell(tempString, iColumn, iRow))
    		{
    			AfxMessageBox(SS.GetLastError());
    			return;
    		}
    
    		CString str;
    		str.Format("行号: %d, 列号: %d ,内容: %s", iRow,iColumn,tempString);
    		AfxMessageBox(str);
    	}
    	
    }

    六、 将存在的Excel转换另存为指定分隔的文本文件
    // 将原Excel文件转换为用分号分隔的文本,并另存为同名文本文件
    SS.Convert(";"); 
    七、 删除Excel中表格
    SS. DeleteSheet();            // 删除Excel文件中所有表格
    SS. DeleteSheet(" TestSheet ");  // 删除Excel中TextSheet表格
    
    八、 获取Excel中总行数、总列数、当前行
    int iCols = SS.GetTotalColumns();   // 总列数
    int iRows = SS.GetTotalRows();    // 总行数
    int iCurRow = SS.GetCurrentRow(); // 当前所在行号
    
    九、 获取行头数据
    CStringArray rowHeader;
    SS.GetFieldNames(rowHeader);
    CString tmpStr;
    for (int i = 0; i < rowHeader.GetSize(); i++)
    {
    		tmpStr.Format("行号: %d, 列号: %d ,内容: %s\n", 1, i+1, rowHeader.GetAt(i));
    		tempString += tmpStr;
    }
    AfxMessageBox(tempString);

    最后,如果想知道详细实现细节的话,可以在下载示例源码后,仔细查看源码既可(内有详细注释)。

    参考文献:
    直接通过ODBC读、写Excel表格文件 – 徐景周(译)
    A Class to Read and Write to Excel and Text Delimited Spreadsheet – Yap Chun Wei

  • silktest q&a[转]

    2008-11-04

    Q1: silktest是什么
    A1:silktest
    是一个segue公司的一个自动化测试工具。
     
    Q2:Segue
    的测试方法论是什么?
    A2:Segue
    的测试方法论是一个包括六个阶段的测试流程:
    1.
    计划。决定测试策略并且定义测试需求。
    2.
    捕捉。将你的应用程序中的GUI对象对象化,并且建立一个运行测试的框架。
    3.
    创建测试。创建自动的,可重用的测试。利用录制和编程手段建立用Segue4Test语言编写的测试脚本。
    4.
    运行测试。选择某些测试并且针对需要测试的软件执行它们。
    5.
    报告。分析测试结果并且生成缺陷报告。
    6.
    追踪。在待测软件中追踪缺陷并且执行回归测试。
     
    Q3:silktest host
    是什么?
    A3:Silktest host
    是一个用来管理和执行测试脚本的组件。Silktest host通常运行在和待测软件不同的机器上。
     
    Q4:silktest agent
    是什么?
    A4:Silktest agent
    是从silktest host接收测试指令,并且和待测软件交互的组件。它通常和待测软件运行在同一机器上。
     
     
    Q5: 4Test
    是什么
    A5:4Test
    silktest用来组成测试脚本执行自动测试的一种测试脚本语言。4Test是面向对象的第四代语言,它由三部分组成:
    一个可以使testcase可以和GUI对象交互的强壮的面向对象的类库。
    一组用来创建记录testcase的结构和逻辑的申明,操作符和数据类型。
    一个用来支持普通支持任务的内建函数库。
     
    Q6:DOM
    浏览器扩展是什么?
    A6:
    文档对象模型(DOM)浏览器扩展是为了测试Web程序的一个silktest附加组件。DOM浏览器扩展直接和Wed浏览器联系来识别,分类处理Web页面上的对象。该组件并非是使用可视化模式识别技术来进行这些对象的识别,而是通过处理实际的HTML代码来实现的。
     
    Q7:VO
    浏览器扩展是什么?
    A7:
    虚拟对象(VO)浏览器扩展是一个为了测试Web程序的silktest附加组件。VO浏览器扩展使用模式识别技术来识别浏览器中呈现出来的对象。VO扩展以页面呈现出来的样子来看待页面而不是通过识别html标记。而且VO扩展以页面中的对象例如:链接,表格,图片和附加在它们上的操作来看待它们,而不考虑它们背后所用的技术。
     
    Q8:6.0
    版本的脚本运用到6.5甚至更高版本的系统上会出现问题么?
    A8:
    从低版本到高版本的迁移不会导致问题,不过这只是一个一般性的声明,而并非适合于所有的情况。我曾经遇到6.5版本的脚本无法在7.0版本上运行的情况,原因是一些识别模式已经被改变了。而且在一些情况下,最后处于不同路径下的脚本竟然执行了基于版本的相同的操作。
    Ps
    :从6.06.5倒没有遇到任何问题。
     
    Q8.:
    近我在使用silktest V3v的是否遇到一个问题,当我记录选择菜单项时,比如:Product.File.Exit.Pick()但是当我回放时,它能够选择File菜单,但是无法选择Exit项。File菜单没有被下拉显示出来,仅仅是高亮了。这个应用是用vc开发并且运行在NT4的系统上的。
    虽然我可以使用菜单的快捷键绕过这个问题,但是在某些testcase里面我更希望能模拟鼠标进行上面的操作,有什么好的办法么?
    A8:
    我也曾经遇到这样的问题,这是由于焦点问题而产生的。首先,我们需要理解QAP/Silktest选择菜单项的原理。它并不是真正的使用鼠标,而是用键盘来高亮菜单栏,然后使用箭头选择想要操作的菜单项。试试下面这个方法:首先将你的应用置于菜单被选中之前的状态,然后手工点击F10键或者Alt键看是否菜单被高亮了并且允许你使用箭头选择菜单项。我猜可能是由于某个childwin或者dialogbox真正拥有了焦点,从而没有把键盘事件传递给mainwin。如果是这种情况,你需要向开发人员说明他们必须解决这个问题,这样你才能够进行自动测试。一个小的技巧是设置一个YourProduct.Click()函数,强制将焦点交给mainwin,然后再进行菜单的选择。
     
    Q9:silktest project
    是什么?
    A9:
    一个silktest project是一个包含测试项目信息的文件集合。
     
    Q10
    如何建立一个新的silktest项目?
    A10:
    运行
    silktest
    选择基本工作流栏

    点击打开项目。
    选择新建项目。
    在新建项目对话框中双击建立项目的图标。
    在新建项目对话框中输入你的项目名字和你的项目描述。
    点击OK
    Silktest
    将会在silktest项目目录下面新建一个子目录,然后在该子目录下存储新项目相关的所有文件。

    Q11:silktest中有没有计算web页面上单词数量的函数?
    A11
    :你可以使用Clipboard函数。使用Ctrl+aCtrl+c,然后解析stringlist.

    Q12:silktesttestplan是什么?
    A12:silktest
    testplan是一个提供软件测试过程框架的大纲,它为组织和管理你的测试需求提供了控制的重点。一个testplan由两个不同的部分组成:一个是大纲,它是测试需求的格式化描述,另一个是声明,被用来连接silktesttestplan脚本和实现测试需求的testcase

    Q13:创建新的test脚本的最佳途径是什么?
    A13:
    在自动测试中,建立测试脚本包括最基本的两个步骤:
    1
    .为所有的testcase创建测试数据。
    2
    .为自动测试编写脚本。
    第一步是分析了你的testcase需要哪些数据后的结果,这些数据被收集,脚本编写出来以后,测试数据才算准备完全了。
    第二步是测试用例自动执行的基本步骤。


    Q14
    :如何得到buttoncaption?
    A14:
    答案1:使用GetCaption ()方法。
    答案2:还可以使用sCaption属性。


    Q14:
    如何关闭不需要的窗口?
    A14:
    你是否意味着那些原窗口(定购状态)以外的一个或者多个浏览器窗口(定购请求)?
    Answer1:
    如果定购请求窗口是弹出式窗口,下面的代码将会关闭一个弹出式的激活状态的窗口。
    [-] !(if Browser.ComboBox("#1").exists())
    [ ] Browser.SetActive()
    [ ] Browser.typekeys("")
    Answer2:
    如果订购请求窗口是一个非弹出式浏览器窗口,你可以使用下面的代码关闭不需要的的浏览器。
    Order_Status.SetActive()
    Browser.CloseOthers()

    Q15:testplan文件里面的文本行有哪些类型?
    A15:
    一个testplan文件包括一些文本行,在其中有5种不同的文本行。
    1.
    注释-绿色标识,提供注释信息。
    2.
    组描述-黑色标识,提供一组测试的描述。Testplan里面的测试可以被组成多个级别的组。
    3.
    测试描述- 蓝色标识,提供单个测试的描述
    4.
    测试计划语句-暗红色标识,提供到testcase,test data,下级testplan或者引用文件的相关链接。
    5.
    打开下级testplan文件的标记-洋红色表示,提供一个到下级testplan的相关链接。


    Q16:testplan
    的属性是什么?
    A16
    Testplan的属性是用户定义属性,它和测试组的描述相关联,或者和某个测试的描述相关联。你可以通过不同的属性值来搜索,标识和报告testcase


    Q17:
    默认的testplan的属性是什么?
    A17:silktest
    提供3种预定义的默认属性:
    1.
    种类: testcase或者testcase组的类型。例如,你可以使用这个属性将你的testcase组分为boudary value testsnavagation tests等种类。
    2.
    组件:被测试的应用的模块名。
    3.
    开发者:开发testcase或者testcase组的QA工程师的名字。

    Q:如何维护恢复系统?
    A
    :在你的TestCaseExit()函数里面,你可以使用如下的代码:
    If condition == 1
    do this
    If condition == 2
    do that


    Q18:
    如何定义一个新的testplan属性?
    A18:
    1.
    确定你的测试项目是打开的。
    2.
    点击Testplan/Define Attributes菜单,定义属性的对话框会被打开,你将看到3个预先定义好的默认属性Category, Component, Developer.
    3.
    点击新建按钮,新属性对话框将被打开。
    4.
    输入你的新属性,例如:Level,用来表示testcase的复杂程度。
    5.
    选择属性的类型:Normal, Edit, 或者Set.
    6.
    点击确定。

     Q19:disabletextfield中得到文本。Silktest不能够识别disable的对象,我如何能解决这个问题。我有一个基于web的应用,在一个页面中有一个radio button。选择这个radio button可以打开一个applet窗口。现在如果我希望得到该窗口的定义,它一样会失败。Silktest被正确地配置成可识别基于javac\s结构应用。如何解决这个问题呢?
    A19:
    如果你希望从一个disabled textfield上得到数据,你首先需要disable Agent选项"OPT_VERIFY_ENABLED" 然后你可以使用GetText。其步骤是:
    Agent.SetOptions("OPT_VERIFY_ENABLED", false)
    Print(TextField.GetText())
    然后来回答你的下一个问题,答案是同样的,disable你的Agent选项,步骤如下:

    1.
    在选项菜单中,点击Agent菜单项。
    2.
    Agent窗口,点击Verification标签。
    3.
    取消所有的选项,保留最后一项,(verification of application ready)
    4.
    点击确定。

    Q20.当调用java应用后(silktest可以启动我的java应用),然后将出现登录屏木,但是silktest报一个JavaMainWin无法找到的错误。为什么?现在我无法正确启动该程序调用然后执行另外一段代码,例如输入用户名和密码登录进应用。
    A20:
    答案1:
    在调用一个应用之后,silktest将一直等待找到这个应用。在这样情况下,应用是你的java窗口。有时会出现在调用之后,silktest无法识别出,但是如果你手动调用,它却能够正常工作。
    解决方法:
    声明一个窗口变量使用start方法。这时你可以使用下面的代码:
    JavaAppWindow.Invoke ()替换为
    Window MyJavaApp
    MyJavaApp.Start ("path of exe or batch file to invoke the application")
    sleep (x) (x -->
    合适的值)

    答案2
    window MainWin MyWin //
    声明一个全局变量
    main ()
    try ()
    testcase try () appstate none
    MyWin.Start(sPath)

    答案3
    当你用start命令作为JavaMainWin的一部分时,保证你的类路径是独立运行的-silktest以外,这样它将会正常工作。

    Q21:如何给testcase的属性赋值?
    A21

    1.
    确定你的testplan处于打开状态。
    2.
    点击你准备赋属性值的testcase
    3.
    点击TestPlan/detail菜单,testplan详细对话框会出现。
    4.
    点击test attribute标签。
    5.
    点击组件域,下拉列表会出现所有组件的可选值。
    6.
    选择下拉列表中的值。
    7.
    点击确定。

    Q22:关于关闭孩子窗口
    A22:
    答案1
    1.
    识别进程句柄
    2.
    关闭它的第一个孩子然后关闭MainWindow

    答案2
    Integer HWnd=Browser.GetHandle() ///
    在孩子窗口弹出之前
    ....
    下面是你的窗口
    While Browser2.Exists()
    {
    If Browser.GetHandle()!=HWnd
    Browser.Close()
    Else
    Browser2.SetActive()
    }
    你也可以在上面的代码中使用窗口的catpion

    答案3
    我想用来识别双亲和孩子的tag不唯一,这正是为什么双亲会被关闭的原因。可以试着使window ID唯一然后关闭页面。第一个激活孩子,然后关闭应该可以管用。

    Q23:如何建立一个test frame
    A23:
    1.
    确定你的浏览器被激活并且打开了你的web应用的首页。不要最小话web页窗口。
    2.
    确定你的测试项目处于打开状态。
    3.
    点击File/New菜单,一个新的对话框将会出现。
    4.
    查看(19) 评论(0)

  • 【转】在silktest用excel实现测试数据驱动

    2008-11-04

     

    2007-12-26 10:35:10 / 个人分类:SilkTest

    [-] type DB_person is record

                    [ ] string name

                    [ ] integer age

                     

    [-] testcase testselect()

                    [ ] STRING sResultFile = "C:\data\SilkeTest.xls"

                    [ ] DB_person personS

                    [ ] STRING sConnectStringSelect = "DSN=Segue DDA Excel;DBQ={sResultFile}"

                    [ ] HANDLE hDBSelect = DB_Connect (sConnectStringSelect)

                    [ ] STRING sSQLSelect = "select name,age from [person$]"

                    [ ] HANDLE hBufferSelect = DB_ExecuteSQL(hDBSelect, sSQLSelect)

                    [-] while(DB_FetchNext(hBufferSelect,person))

                                    [ ] print("Name:{person.name};Age:{person.age}")

                    [ ] DB_FinishSql (hBufferSelect)

                    [ ] DB_Disconnect (hDBSelect)

     

     [-] testcase testinsert()

                    [ ] STRING sResultFile = "C:\data\SilkeTest.xls"

                    [ ] STRING sConnectStringInsert = "DSN=Segue DDA Excel;ReadOnly=False;DBQ={sResultFile}"

                    [ ] HANDLE hDBInsert = DB_Connect (sConnectStringInsert)

                    [ ] STRING sSQLInsert = "insert into [person$] (Name,Age) values ('Zhao Liu',11);"

                    [ ] HANDLE hBufferInsert = DB_ExecuteSQL(hDBInsert, sSQLInsert)

                    [ ] DB_FinishSql (hBufferInsert)

                    [ ] DB_Disconnect (hDBInsert)

                     

    [-] testcase testupdate()

                    [ ] STRING sResultFile = "C:\data\SilkeTest.xls"

                    [ ] STRING sConnectStringUpdate = "DSN=Segue DDA Excel;ReadOnly=False;DBQ={sResultFile}"

                    [ ] HANDLE hDBUpdate = DB_Connect (sConnectStringUpdate)

                    [ ] STRING sSQLUpdate = "update  [person$]  set name ='51testing' where name='Zhao Liu'"

                    [ ] HANDLE hBufferUpdate = DB_ExecuteSQL(hDBUpdate, sSQLUpdate)

                    [ ] DB_FinishSql (hBufferUpdate)

                    [ ] DB_Disconnect (hDBUpdate)

  • 5565

    2007-11-29

  • 自我解析--考试篇

    2007-9-11

     实在是不知道什么原因,为什么每次考试结果是那么的出乎我的意料,是我不行吗?说实话,我真的不信,每堂课我都听的懂并不觉得困难和跟不上,但事实却总是让人无法理解。或者,其实也不是那么的难以理解吧,矛盾
     
    一直纠结每次的考试都是在及格边缘的我,或许真的对知识的掌握不是那么熟练,付出的努力和收获都是成正比的,即使我真的觉得自己付出不少了(至少比以前要认真很多),但相对于别人来说,可能真的微不足道。
     
    仔细分析:原因有几点
    一、没有按时完成每次的作业
    二、只学到了老师讲的一些表面知识,没有深入分析其缘由及如果变化后的结果
    三、没有整理老师给的课余资料,也没有看过
    四、没有好好复习,也是只是复习了表面的东西,对不懂的问题没有深入搞懂
     
    总之,把这次培训当成了任务,没有将兴趣培养出来,只是完成任务式的学习,导致总觉得学习任务很重很累,没时间完成作业。时间上没有调配好,主次不分,以致娱乐学习两误。
     
    针对以上几点,应采取措施:
    一、对老师交代的作业一定要按时按质按量的完成
    二、对每次学完后要对当天的课程回顾并解决上课没懂的地方,加深理解
    三、老师给的课余资料都是学习的辅助资料,一定要抽时间看
    四、复习,要深入,对不懂的地方一定要搞懂,不可以轻易放过,这也是对自己的负责
     
    最后,要从学习中找到乐趣,最后的一个月了,要好好把握,再不把握,实在太丢人了
     
    这段学校期间,真的学到了很多,对自己的缺点有了新的认识
    加油加油
    AZAZA!!!!!!
    FIGHT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  • sprintf的用法

    2007-8-30

    最近不知道sprintf的用法,特意查上,收藏,一起共享

    在将各种类型的数据构造成字符串时,sprintf 的强大功能很少会让你失望。由于sprintf 跟printf 在用法上几乎一样,只是打印的目的地不同而已,前者打印到字符串中,后者则直接在命令行上输出。这也导致sprintf 比printf 有用得多。

    sprintf 是个变参函数,定义如下:
    int sprintf( char *buffer, const char *format [, argument] ... );
    除了前两个参数类型固定外,后面可以接任意多个参数。而它的精华,显然就在第二个参数:
    格式化字符串上。


    printf 和sprintf 都使用格式化字符串来指定串的格式,在格式串内部使用一些以“%”开头的格式说明符(format specifications)来占据一个位置,在后边的变参列表中提供相应的变量,最终函数就会用相应位置的变量来替代那个说明符,产生一个调用者想要的字符串。

    格式化数字字符串
    sprintf 最常见的应用之一莫过于把整数打印到字符串中,所以,spritnf 在大多数场合可以替代
    itoa。

    如:
    //把整数123 打印成一个字符串保存在s 中。
    sprintf(s, "%d", 123); //产生"123"
    可以指定宽度,不足的左边补空格:
    sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"
    当然也可以左对齐:
    sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567"
    也可以按照16 进制打印:
    sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐
    sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐

    这样,一个整数的16 进制字符串就很容易得到,但我们在打印16 进制内容时,通常想要一种左边补0 的等宽格式,那该怎么做呢?很简单,在表示宽度的数字前面加个0 就可以了。
    sprintf(s, "%08X", 4567); //产生:"000011D7"
    上面以”%d”进行的10 进制打印同样也可以使用这种左边补0 的方式。


    这里要注意一个符号扩展的问题:比如,假如我们想打印短整数(short)-1 的内存16 进制表示形式,在Win32 平台上,一个short 型占2 个字节,所以我们自然希望用4 个16 进制数字来打印它:
    short si = -1;
    sprintf(s, "%04X", si);
    产生“FFFFFFFF”,怎么回事?因为spritnf 是个变参函数,除了前面两个参数之外,后面的参数都不是类型安全的,函数更没有办法仅仅通过一个“%X”就能得知当初函数调用前参数压栈时被压进来的到底是个4 字节的整数还是个2 字节的短整数,所以采取了统一4 字节的处理方式,导致参数压栈时做了符号扩展,扩展成了32 位的整数-1,打印时4 个位置不够了,就把32 位整数-1 的8 位16 进制都打印出来了。

    如果你想看si 的本来面目,那么就应该让编译器做0 扩展而不是符号扩展(扩展时二进制左边补0 而不是补符号位):
    sprintf(s, "%04X", (unsigned short)si);
    就可以了。或者:
    unsigned short si = -1;
    sprintf(s, "%04X", si);


    sprintf 和printf 还可以按8 进制打印整数字符串,使用”%o”。注意8 进制和16 进制都不会打
    印出负数,都是无符号的,实际上也就是变量的内部编码的直接的16 进制或8 进制表示。

    控制浮点数打印格式
    浮点数的打印和格式控制是sprintf 的又一大常用功能,浮点数使用格式符”%f”控制,默认保
    留小数点后6 位数字,比如:
    sprintf(s, "%f", 3.1415926); //产生"3.141593"
    但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:”%m.nf”格式,其中m 表
    示打印的宽度,n 表示小数点后的位数。比如:
    sprintf(s, "%10.3f", 3.1415626); //产生:" 3.142"
    sprintf(s, "%-10.3f", 3.1415626); //产生:"3.142 "
    sprintf(s, "%.3f", 3.1415626); //不指定总宽度,产生:"3.142"

    注意一个问题,你猜
    int i = 100;
    sprintf(s, "%.2f", i);
    会打出什么东东来?“100.00”?对吗?自己试试就知道了,同时也试试下面这个:
    sprintf(s, "%.2f", (double)i);
    第一个打出来的肯定不是正确结果,原因跟前面提到的一样,参数压栈时调用者并不知道跟i相对应的格式控制符是个”%f”。而函数执行时函数本身则并不知道当年被压入栈里的是个整数,于是可怜的保存整数i 的那4 个字节就被不由分说地强行作为浮点数格式来解释了,整个乱套了。不过,如果有人有兴趣使用手工编码一个浮点数,那么倒可以使用这种方法来检验一下你手工编排的结果是否正确。

    字符/Ascii 码对照
    我们知道,在C/C++语言中,char 也是一种普通的scalable 类型,除了字长之外,它与short,
    int,long 这些类型没有本质区别,只不过被大家习惯用来表示字符和字符串而已。(或许当年该把
    这个类型叫做“byte”,然后现在就可以根据实际情况,使用byte 或short 来把char 通过typedef 定义出来,这样更合适些)于是,使用”%d”或者”%x”打印一个字符,便能得出它的10 进制或16 进制的ASCII 码;反过来,使用”%c”打印一个整数,便可以看到它所对应的ASCII 字符。以下程序段把所有可见字符的ASCII 码对照表打印到屏幕上(这里采用printf,注意”#”与”%X”合用时自动为16 进制数增加”0X”前缀):
    for(int i = 32; i < 127; i++) {
    printf("[ %c ]: %3d 0x%#04X\n", i, i, i);
    }


    连接字符串
    sprintf 的格式控制串中既然可以插入各种东西,并最终把它们“连成一串”,自然也就能够连
    接字符串,从而在许多场合可以替代strcat,但sprintf 能够一次连接多个字符串(自然也可以同时
    在它们中间插入别的内容,总之非常灵活)。比如:
    char* who = "I";
    char* whom = "CSDN";
    sprintf(s, "%s love %s.", who, whom); //产生:"I love CSDN. "
    strcat 只能连接字符串(一段以’\0’结尾的字符数组或叫做字符缓冲,null-terminated-string),但有时我们有两段字符缓冲区,他们并不是以’\0’结尾。比如许多从第三方库函数中返回的字符数组,从硬件或者网络传输中读进来的字符流,它们未必每一段字符序列后面都有个相应的’\0’来结尾。如果直接连接,不管是sprintf 还是strcat 肯定会导致非法内存操作,而strncat 也至少要求第一个参数是个null-terminated-string,那该怎么办呢?我们自然会想起前面介绍打印整数和浮点数时可以指定宽度,字符串也一样的。比如:
    char a1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
    char a2[] = {'H', 'I', 'J', 'K', 'L', 'M', 'N'};
    如果:
    sprintf(s, "%s%s", a1, a2); //Don't do that!
    十有八九要出问题了。是否可以改成:
    sprintf(s, "%7s%7s", a1, a2);
    也没好到哪儿去,正确的应该是:
    sprintf(s, "%.7s%.7s", a1, a2);//产生:"ABCDEFGHIJKLMN"
    这可以类比打印浮点数的”%m.nf”,在”%m.ns”中,m 表示占用宽度(字符串长度不足时补空格,超出了则按照实际宽度打印),n 才表示从相应的字符串中最多取用的字符数。通常在打印字符串时m 没什么大用,还是点号后面的n 用的多。自然,也可以前后都只取部分字符:
    sprintf(s, "%.6s%.5s", a1, a2);//产生:"ABCDEFHIJKL"
    在许多时候,我们或许还希望这些格式控制符中用以指定长度信息的数字是动态的,而不是静态指定的,因为许多时候,程序要到运行时才会清楚到底需要取字符数组中的几个字符,这种动态的宽度/精度设置功能在sprintf 的实现中也被考虑到了,sprintf 采用”*”来占用一个本来需要一个指定宽度或精度的常数数字的位置,同样,而实际的宽度或精度就可以和其它被打印的变量一样被提供出来,于是,上面的例子可以变成:
    sprintf(s, "%.*s%.*s", 7, a1, 7, a2);
    或者:
    sprintf(s, "%.*s%.*s", sizeof(a1), a1, sizeof(a2), a2);
    实际上,前面介绍的打印字符、整数、浮点数等都可以动态指定那些常量值,比如:
    sprintf(s, "%-*d", 4, 'A'); //产生"65 "
    sprintf(s, "%#0*X", 8, 128); //产生"0X000080","#"产生0X
    sprintf(s, "%*.*f", 10, 2, 3.1415926); //产生" 3.14"


    打印地址信息
    有时调试程序时,我们可能想查看某些变量或者成员的地址,由于地址或者指针也不过是个32 位的数,你完全可以使用打印无符号整数的”%u”把他们打印出来:
    sprintf(s, "%u", &i);
    不过通常人们还是喜欢使用16 进制而不是10 进制来显示一个地址:
    sprintf(s, "%08X", &i);
    然而,这些都是间接的方法,对于地址打印,sprintf 提供了专门的”%p”:
    sprintf(s, "%p", &i);
    我觉得它实际上就相当于:
    sprintf(s, "%0*x", 2 * sizeof(void *), &i);
    利用sprintf 的返回值
    较少有人注意printf/sprintf 函数的返回值,但有时它却是有用的,spritnf 返回了本次函数调用
    最终打印到字符缓冲区中的字符数目。也就是说每当一次sprinf 调用结束以后,你无须再调用一次
    strlen 便已经知道了结果字符串的长度。如:
    int len = sprintf(s, "%d", i);
    对于正整数来说,len 便等于整数i 的10 进制位数。
    下面的是个完整的例子,产生10 个[0, 100)之间的随机数,并将他们打印到一个字符数组s 中,
    以逗号分隔开。
    #include
    #include
    #include
    int main() {
    srand(time(0));
    char s[64];
    int ōffset = 0;
    for(int i = 0; i < 10; i++) {
    offset += sprintf(s + offset, "%d,", rand() % 100);
    }
    s[offset - 1] = '\n';//将最后一个逗号换成换行符。
    printf(s);
    return 0;
    }
    设想当你从数据库中取出一条记录,然后希望把他们的各个字段按照某种规则连接成一个字
    符串时,就可以使用这种方法,从理论上讲,他应该比不断的strcat 效率高,因为strcat 每次调用
    都需要先找到最后的那个’\0’的位置,而在上面给出的例子中,我们每次都利用sprintf 返回值把这
    个位置直接记下来了。


    使用sprintf 的常见问题
    sprintf 是个变参函数,使用时经常出问题,而且只要出问题通常就是能导致程序崩溃的内存访
    问错误,但好在由sprintf 误用导致的问题虽然严重,却很容易找出,无非就是那么几种情况,通
    常用眼睛再把出错的代码多看几眼就看出来了。


    ?? 缓冲区溢出
    第一个参数的长度太短了,没的说,给个大点的地方吧。当然也可能是后面的参数的问
    题,建议变参对应一定要细心,而打印字符串时,尽量使用”%.ns”的形式指定最大字符数。


    ?? 忘记了第一个参数
    低级得不能再低级问题,用printf 用得太惯了。//偶就常犯。:。(


    ?? 变参对应出问题
    通常是忘记了提供对应某个格式符的变参,导致以后的参数统统错位,检查检查吧。尤
    其是对应”*”的那些参数,都提供了吗?不要把一个整数对应一个”%s”,编译器会觉得你
    欺她太甚了(编译器是obj 和exe 的妈妈,应该是个女的,:P)。

    strftime
    sprnitf 还有个不错的表妹:strftime,专门用于格式化时间字符串的,用法跟她表哥很像,也
    是一大堆格式控制符,只是毕竟小姑娘家心细,她还要调用者指定缓冲区的最大长度,可能是为
    了在出现问题时可以推卸责任吧。这里举个例子:
    time_t t = time(0);
    //产生"YYYY-MM-DD hh:mm:ss"格式的字符串。
    char s[32];
    strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime(&t));
    sprintf 在MFC 中也能找到他的知音:CString::Format,strftime 在MFC 中自然也有她的同道:
    CTime::Format,这一对由于从面向对象哪里得到了赞助,用以写出的代码更觉优雅。

  • 如何使你的雅虎中文电邮支持POP服务!(收藏)

    2007-8-30

    雅虎中文对新用户现在缺省是不提供POP Access服务的, 但还留有"后门":-), 方法如下:

    (1). 用你的账号登陆进 Yahoo 电邮.

    (2). 然后把下面整个的链接贴到你的浏览器(IE)的地址栏里(注意整个都是一行!):

    http://edit.my.yahoo.com/config/set_popfwd?.src=ym&.done=http://cn.f150.mail.yahoo.com/ym/Options?YY=22797

    (3). 然后就是出现要你同意POP Access服务的网页了, 点了提交按钮以后就可以看到你的POP

    Access服务已经开通的页面了! ! 还不赶快去申请一个? :)

    (4). 如果出错, 登出Yahoo电邮后再次登陆, 然后重复上述步骤 2, 3 即可.

    雅虎中文邮件服务器设置如下:

    接收邮件(POP3)服务器:pop.mail.yahoo.com.cn

    发送邮件(SMTP)服务器:smtp.mail.yahoo.com

    如果看英文不眼晕, 也可直接到Yahoo Canada申请一个帐户, 现在仍直接支持POP Access.

    另外无论是雅虎, 雅虎中文, 还是雅虎加拿大, POP服务器其实均指向同一服务器:

      pop.vip.sc5.yahoo.com [216.136.173.10]

    SMTP服务器均指向:

      smtp.mail.vip.sc5.yahoo.com [216.136.173.12]

  • Tomcat+Jsp经典配置(转)

    2007-8-30

    Tomcat+Jsp经典Tomcat下JSP、Servlet和JavaBean环境的配置

    经常看到jsp的初学者问tomcat下如何配置jsp、servlet和bean的问题,于是总结了一下如何tomcat下配置jsp、servlet和ben,希望对那些初学者有所帮助。
    一、开发环境配置
    第一步:下载j2sdk和tomcat:到sun官方站(http://java.sun.com/j2se/1.5.0/download.jsp)下载j2sdk,注意下载版本为Windows Offline Installation的SDK,同时最好下载J2SE 1.5.0 Documentation,然后到tomcat官方站点(http://jakarta.apache.org/site/downloads/downloads_tomcat-5.cgi)下载tomcat(下载最新5.5.9版本的tomcat);
    第二步:安装和配置你的j2sdk和tomcat:执行j2sdk和tomcat的安装程序,然后按默认设置进行安装即可。
    1.安装j2sdk以后,需要配置一下环境变量,在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量(假定你的j2sdk安装在c:\j2sdk1.5.0):
    JAVA_HOME=c:\j2sdk1.5.0
    classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;(.;一定不能少,因为它代表当前路径)
    path=%JAVA_HOME%\bin
    接着可以写一个简单的java程序来测试J2SDK是否已安装成功:
    public class Test{
    public static void main(String args[]){
    System.out.println("This is a test program.");
    }
    }
    将上面的这段程序保存为文件名为Test.java的文件。
    然后打开命令提示符窗口,cd到你的Test.java所在目录,然后键入下面的命令
    javac Test.java
    java Test
    此时如果看到打印出来This is a test program.的话说明安装成功了,如果没有打印出这句话,你需要仔细检查一下你的配置情况。
    2.安装Tomcat后,在我的电脑->属性->高级->环境变量->系统变量中添加以下环境变量(假定你的tomcat安装在c:\tomcat):
    CATALINA_HOME=c:\tomcat
    CATALINA_BASE=c:\tomcat
    然后修改环境变量中的classpath,把tomat安装目录下的common\lib下的(可以根据实际追加)servlet.jar追加到classpath中去,修改后的classpath如下:
    classpath=.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\common\lib\servlet.jar;
    接着可以启动tomcat,在IE中访问http://localhost:8080,如果看到tomcat的欢迎页面的话说明安装成功了。
    第三步:建立自己的jsp app目录
    1.到Tomcat的安装目录的webapps目录,可以看到ROOT,examples, tomcat-docs之类Tomcat自带的的目录;
    2.在webapps目录下新建一个目录,起名叫myapp;
    3.myapp下新建一个目录WEB-INF,注意,目录名称是区分大小写的;
    4.WEB-INF下新建一个文件web.xml,内容如下:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
    <display-name>My Web Application</display-name>
    <descrīption>
    A application for test.
    </descrīption>
    </web-app>
    5.在myapp下新建一个测试的jsp页面,文件名为index.jsp,文件内容如下:
    <html><body><center>
    Now time is: <%=new java.util.Date()%>
    </center></body></html>
    6.重启Tomcat
    7.打开浏览器,输入http://localhost:8080/myapp/index.jsp 看到当前时间的话说明就成功了。
    第四步:建立自己的Servlet:
    1.用你最熟悉的编辑器(建议使用有语法检查的java ide)新建一个servlet程序,文件名为Test.java,文件内容如下:
    package test;
    import java.io.IOException;
    import java.io.PrintWriter;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    public class Test extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    PrintWriter ōut=response.getWriter();
    out.println("<html><body><h1>This is a servlet test.</h1></body></html>");
    out.flush();
    }
    }
    2 .编译
    将Test.java放在c:\test下,使用如下命令编译:
    C:\Test>javac Test.java
    然后在c:\Test下会产生一个编译后的servlet文件:Test.class
    3 .将结构test\Test.class剪切到%CATALINA_HOME%\webapps\myapp\WEB-INF\classes下,也就是剪切那个test目录到classes目录下,如果classes目录不存在,就新建一个。 现在webapps\myapp\WEB-INF\classes下有test\Test.class的文件目录结构
    4 .修改webapps\myapp\WEB-INF\web.xml,添加servlet和servlet-mapping
    编辑后的web.xml如下所示,红色为添加的内容:
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
    <web-app>
    <display-name>My Web Application</display-name>
    <descrīption>
    A application for test.
    </descrīption>
    <servlet>
    <servlet-name>Test</servlet-name>
    <display-name>Test</display-name>
    <descrīption>A test Servlet</descrīption>
    <servlet-class>test.Test</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>Test</servlet-name>
    <url-pattern>/Test</url-pattern>
    </servlet-mapping>
    </web-app>
    这段话中的servlet这一段声明了你要调用的Servlet,而servlet-mapping则是将声明的servlet"映射"到地址/Test上
    5 .好了,重启动Tomcat,启动浏览器,输入http://localhost:8080/myapp/Test 如果看到输出This is a servlet test.就说明编写的servlet成功了。
    注意:修改了web.xml以及新加了class,都要重启Tomcat
    第四步:建立自己的Bean:
    1.用你最熟悉的编辑器(建议使用有语法检查的java ide)新建一个java程序,文件名为TestBean.java,文件内容如下:
    package test;
    public class TestBean{
    private String name = null;
    public TestBean(String strName_p){
    this.name=strName_p;
    }
    public void setName(String strName_p){
    this.name=strName_p;
    }
    public String getName(){
    return this.name;
    }
    }
    2 .编译
    将TestBean.java放在c:\test下,使用如下命令编译:
    C:\Test>javac TestBean.java
    然后在c:\Test下会产生一个编译后的bean文件:TestBean.class
    3 .将TestBean.class文件剪切到 %CATALINA_HOME%\webapps\myapp\WEB-INF\classes\test下,
    4 .新建一个TestBean.jsp文件,文件内容为:
    <%@ page import="test.TestBean" %>
    <html><body><center>
    <%
    TestBean testBean=new TestBean("This is a test java bean.");
    %>
    Java bean name is: <%=testBean.getName()%>
    </center></body></html>
    5 .好了,重启Tomcat,启动浏览器,输入http://localhost:8080/myapp/TestBean.jsp 如果看到输出Java bean name is: This is a test java bean.就说明编写的Bean成功了。
    这样就完成了整个Tomcat下的jsp、servlet和javabean的配置。接下来需要做的事情就是多看书、多读别人的好代码,自己多动手写代码以增强自己在这方面开发的能力了。

    jvm应填写到
    c:\j2sdk\bin

    给你一个简单的配置::::

    JSP环境配置心得
    首先要说的是,使用jdk+tomcat完全可以配置我们的jsp服务器,不再需要其实任何东东,有很多文章介绍了Apache,其实根本用不着,一般的学习调试tomcat完全可以胜任了。
    安装jdk后,tomcat在安装之前会自动找到jdk的安装路径,一路点击"下一步",经过一段时间的文件复制,最后"close",完成comcat的安装。
    您最好去下载一个版本较高的tomcat,比如4.1以上的,因为它不需要设置太多的系统变量,右击"我的电脑",选择"属性"->"高级"->"环境变量"->"系统变量",新建一个TOMCAT_HOME,值设置成你的tomcat所在的路径,比如:D:\Program Files\Apache Group\Tomcat 5.5,配置完成。
    从开始菜单中找到tomcat选项,一般打开顺序是:开始->程序->Apache Tomcat 5.5,选择"Start Tomcat",让jsp服务器开始运行,此时会打开一个类似Dos的窗口,会显示一些相关的信息。
    如果您使用代理上网,一定要先撤掉代理,不然您的jsp程序永远也得不到执行。如果不是代理的,这一步就跳过了。
    打开浏览器,在地址栏中输入:http://localhost:8080,如果看到有老虎(我也不知道是老虎还是猫)的画面,恭喜您,您成功了一半。
    先来享受一下成功的喜悦吧,请输入下面的代码:
    <html>
    <head>
    <title>First Page</title>
    </head>
    <body>
    <H3>Today is: h
    <%= new java.util.Date() %>
    </H3>
    </body>
    </html>
    将该程序保存为:First.jsp,放到Tomcat的ROOT目录下,然后在浏览器的地址栏中输入:http://localhost:8080/First.jsp,(First.jsp跟我们保存的文件名的大小写要一致)回车,如果不出意外,应该可以看到形如Today is: h Fri Apr 11 08:32:38 CST 2003 的结果。
    注意:ROOT是tomcat的默认虚拟目录,如果要改成自己的虚拟目录怎么办呢?请继续往下看吧。
    要改成自己的虚拟目录,就要请出server.xml来了,该文件是一个配置文件,在Tomcat\conf目录下,使用任何文本编辑软件都能打开它,我们先找到下面一句:
    <Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
    port="8080" minProcessors="5" maxProcessors="75"
    enableLookups="true" redirectPort="8443"
    acceptCount="100" debug="0" connectionTimeout="20000"
    useURIValidationHack="false" disableUploadTimeout="true" />
    这里的port="8080"就是端口,我们完全可以用别的端口来代替,但不能是被系统占用的端口(0--1023),这里简单提一下。
    下面我们再往下找,会发现以下的语句:
    </Context>
    </Host>
    我们就应该找到这两个语句,如果不懂E文,您就认定这两个语句好了。然后我们将该语句更改如下:
    </Context>
    <Context path="/myjsp" debug="0" docBase="e:/myjsp" reloadable="true">
    </Context>
    </Host>
    这里的path="/myjsp"就是我们就配置的虚拟目录了,以后在地址栏中输入http://localhost:8080/myjsp即可。而docBase="e:/myjsp" 则是机器本地路径,他们通过这个语句形成一个映射关系,其它照抄。
    将上面的First.jsp文件放到e:/myjsp目录下,输入http://localhost:8080/myjsp/First.jsp,是不是有一种喜上眉梢的感觉?
    在论坛里我见得最多的就是很多人不知道javaBean文件放到哪里,老实说开始我也不知道,更令人不解的是,十个人有九种不同的说法,这更让我们茫然。其实这问题也不是我们想像的那么复杂,我们以一个例子说明:
    先建立一个java程序,代码如下:
    package hall;
    public class SimpleBean {
    private String message = "No message specified";
    public String getMessage() {
    return(message);
    }
    public void setMessage(String message) {
    this.message = message;
    }
    }
    保存为SimpleBean.java,编译后会生成一个包,其实就相当于一个目录,也就是SimpleBean.class会存放在hall目录中,暂且保存起来,将来备用。
    再输入以下代码:
    <HTML>
    <HEAD>
    <TITLE>Reusing JavaBeans in JSP</TITLE>
    </HEAD>
    <BODY>
    <CENTER>
    <TABLE BORDER=5>
    <TR><TH CLASS="TITLE">
    Reusing JavaBeans in JSP</TABLE>
    </CENTER>
    <P>
    <jsp:useBean id="test" class="hall.SimpleBean" />
    <jsp:setProperty name="test" property="message" value="Hello WWW" />
    <H1>Message: <I>
    <jsp:getProperty name="test" property="message" />
    </I></H1>
    </BODY>
    保存在我们刚才建立的虚拟目录e:/myjsp下面,并命名为:BeanTest.jsp。
    现在我们应该将hall(包)目录放在哪儿呢?别急,我们先在e:/myjsp下建立一个文件夹WEB-INF,然后再在WEB-INF下建立一个classes文件夹,最后将hall目录放到classes下,当然,hall下的字节码文件SimpleBean.class也一并要移过来,而SimpleBean.java就和BeanTest.jsp放到同一目录吧(可以不需要放的,自己试试)。
    好了,大功告成了,重新启动机器(如果您试了好多次都不行,这一步一定要做),在浏览器中输入:http://localhost:8080/myjsp/BeanTest.jsp,您看到了什么?呵,别告诉我您什么都没看到,那肯定是您设置的问题了。
    好了,文章写完了,我也只是一只菜鸟,所以有写的不准备的地方请多多指教。祝您jsp之旅一路顺风!!!
    Java学习 - 技术文章中心
    初学者问的诸如:《怎样配置环境变量》《怎样运行Servlet》啊?这样的问题太多了,现在我写一个初学者入门必读,以便对初学者有指导作用!
    首先是下载工具:
    我建议初学者用Editplus+JDK,我觉得如果用例如JB,Eclipse,JCreator,虽然刚开始的时候比较方便,但是确使初学者门不知道怎样配置环境变量,
    从而难以达到知其然,知其所以然的地步
    可以通过如下地址下载:
    Editplus(最新版本是v2.11):http://count.skycn.com/softdown.php?id=3641&url=http://sc-http.skycn.net/down/epp211a_cn.exe(要照注册码就自己找吧,网上很多的)
    JDK(最新版本是Java2sdk1_5_0):http://192.18.97.54/ECom/EComTicketServlet/BEGIN30AA3B63E5C2F61C8C26F84B78970A98/-2147483648/926882595/1/627578/627410/926882595/2ts+/westCoastFSEND/jdk-1.5.0_04-oth-JPR/jdk-1.5.0_04-oth-JPR:3/jdk-1_5_0_04-windows-i586-p.exe(这是For Windows)
    然后就是安装JDK,我是把它装到从c:\JDK目录下面:
    然后就是CLASSPATH的问题了:
    正如操作系统利用PATH来搜索可执行程序一样,Java运行环境也会遍历CLASSPATH来查找类,即便是HelloWorld这样简单的程序,JVM也会遍历
    CLASSPATH定义的每一个路径,直到找到相应的文件为止。
    相信大家用的系统不是2k就是XP,然后就应当如下设置Path:
    我的电脑->属性->高级->环境变量
    然后在环境变量的Path后面追加: C:\JDK\bin;.;C:\JDK\lib
    也可以这样配置:C:\JDK\bin;.;C:\JDK\lib\dt.jar;C:\JDK\lib\tools.jar
    ★记住:环境变量中的 . 切记不能少,它表示当前路径,如果少掉出现的错误等会就说!
    dt.jar是关于运行环境的类库,tools.jar是关于一些工具的类库
    如果没有配置:C:\JDK\bin,则会出现 " javac´ 不是内部或外部命令,也不是可运行的程序或批处理文件。"这样的错误。
    然后下面就该写程序了:
    首先是(HelloWorld.java),打开Editplus,新建一个Java文件,请照着如下输入,要一字不漏,并且分清大小写:
    public class HelloWorld{
    public static void main(String[] args){
    System.out.println("Hello,World!");
    }
    }
    然后把这个文件保存(ctrl + s)到HelloWorld.java,记住大小写一定要分清,是HelloWorld.java不是helloworld.java或者其它的
    下面就该运行了,开始->运行->cmd
    在控制台中把目录切换到当前目录:
    javac HelloWorld.java
    java HelloWorld
    你就会在控制台上看见输出的Hello,World!(没出来?我把电脑吃了:))
    javac是编译命令,它把HelloWorld.java编译成HelloWorld.class
    java就是解释命令,JVM把HelloWorld.class解释执行.
    在这个时候:
    1。如果出现Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorld
    那就是你在环境变量中没有加上那个.(dot)
    2。如果出现Exception in thread "main" java.lang.NoSuchMethodError: main
    或者HelloWorld.java:1: Public class helloworld must be defined in a file called
    "HelloWorld.java".
    那就是你没有分清大小写的写入这个HelloWorld,或者保存得时候没有保存为HelloWorld.java
    这个名字一定要跟public class的名字一样
    对于环境变量的问题就说到这里,下面我先所说怎么在Editplus里面编译和运行,在Tools->参数设置->配置用户工具
    1.添加工具(添加应用程序)
    菜单文字:Compile Java Program
    程序:C:\JDK\bin\javac.exe
    参数:文件名称
    初始目录:文件目录
    2.添加工具(添加应用程序)
    菜单文字:Run Java Program
    程序:C:\JDK\bin\java.exe
    参数:文件名称(不含扩展名)
    初始目录:文件目录
    工具组名称可以随便添,比如Debug Java Program
    然后在Tools的下拉菜单中,你就会看见Compile Java Program以及Run Java Program这两个选项,以后你就可以利用ctrl + 1编译和ctrl +2运行程序了

    下面就讨论Servlet的运行:
    首先要运行Servlet,则需要JSP/Servlet container,我建议初学者用Tomcat
    Tomcat(最新版本5.5):http://apache.justdn.org/jakarta/tomcat-5/v5.5.9/bin/jakarta-tomcat-5.5.9.exe然后把这个压缩包解压到:
    C:\Tomcat
    然后再配置环境变量:
    添加三个系统变量:
    JAVA_HOME: C:\JDK
    TOMCAT_HOME: C:\Tomcat
    CLASSPATH: %JAVA_HOME%\lib;%TOMCAT_HOME%\lib
    Tomcat的环境变量就配置完毕了,下面检验Tomcat是否能够运行:
    在控制台中转到C:\Tomcat\bin这个目录,运行startup,然后回出现一个窗口,连跳一大串东西,最后表示Server已经运行
    在浏览器中输入http://localhost:8080,出现欢迎界面,则表示Tomcat没