?? 新建 文本文檔.txt
字號:
%>
格式化成"yyyy-MM-dd HH:mm:ss"格式的日期時間:<%=str_date1%>
未經格式化的String格式的日期時間:<%=str_date2%>
未經格式化的Date格式的日期時間:<%=currentTime%>
-------------------------------------------------
頁面的輸出內容:
格式化成"yyyy-MM-dd HH:mm:ss"格式的日期時間:2005-03-17 09:55:40
未經格式化的String格式的日期時間:Thu Mar 17 09:55:40 CST 2005
未經格式化的Date格式的日期時間:Thu Mar 17 09:55:40 CST 2005
通常我們需要的是這種格式化后的時間:2005-03-17 09:55:40。現在有這樣一個問題:“2005-03-17 09:55:40”是一個字符串,有些時候我們需要在這個字符串里提取出年、月、日等的相關信息,怎么辦呢?看下面的代碼:
----------------------規則的字符串----------------------------------------------
規則的字符串(年4位,月2位,日2位,中間用字符“-”分隔):
<br>原字符串為:
<%
String date="1989-12-30";
out.println(date+"<br>");
String year=date.substring(0,4);//取第0+1位至第4位
String month=date.substring(5,7);//取第5+1位至第7位
String day=date.substring(8,10);//取第8+1位至第10位
out.println("year="+year+",month="+month+",day="+day);
%>
----------------------------------------------------------------------------------
從上面的代碼我們可以看出來:這只能針對規則的字符串(年4位,月2位,日2位),要是不規則的呢?年可能2位也可能4位,月和日可能1位也可能2位,怎么辦?通過對上面的代碼修改,可以得到下面的通用的代碼(這個“通用”有一個前提——年月日之間必須以“-”分隔):
----------------------不規則的字符串----------------------------------------------
不規則的字符串(年、月、日長度不一定,中間用字符“-”分隔):
<br>原字符串為:
<%
String date="04-05-6";
out.println(date+"<br>");
int a=date.indexOf("-");//求第一個“-”的位數
int b=date.lastIndexOf("-");//求最后一個“-”的位數
int len=date.length();//求字符串的長度
year=date.substring(0,a);//取第一個“-”前的字符串
month=date.substring(a+1,b);//取兩個“-”之間的字符串
day=date.substring(b+1,len);//取最后一個“-”以后的字符串
out.println("year="+year+",month="+month+",day="+day);
%>
----------------------------------------------------------------------------------
現在這個問題解決了。可是我們會想到:每次需要對一個表示年月日的字符串進行分割的時候都需要在.jsp頁面里寫上這么一段代碼,不但麻煩而且使頁面顯得混亂,能不能以一種看起來更清晰的方法解決這個問題呢?當然可以了,用javabean就行了。
二、第一個javabean
什么是javabean?我在接觸到這個問題時苦惱不已,因為我始終無法理解這個概念,直到我相繼寫了幾個之后,我驀然發現:它不就是一個類嗎?!現在,我們先不去管什么是類,先看下面的這個javabean:
--------------------------------DateBean.java-------------------------------------
//該bean能夠從jsp文件中得到一個表示年月日(用“-”分隔)的字符串,然后返回給jsp文件分別表示年、月、日的字符串
package ringz.javabeans; //ringz.javabeans是我的包名,我自己寫的javabean都在這個包里
public class DateBean //這個class的名字是DateBean,那么這個javabean文件的名就必須叫:DateBean.java
{
private String dateStr;
private String year;
private String month;
private String day;
//
public void setDateStr(String str) //私有變量dateStr的set方法
{
this.dateStr=str;
}
public String getDateStr() //私有變量dateStr的get方法
{
return dateStr;
}
public String getYear()//得到年的字符串
{
int a=dateStr.indexOf("-");//求第一個“-”的位數
year=dateStr.substring(0,a);//取第一個“-”前的字符串
return year;
}
public String getMonth()//得到月的字符串
{
int a=dateStr.indexOf("-");//求第一個“-”的位數
int b=dateStr.lastIndexOf("-");//求最后一個“-”的位數
month=dateStr.substring(a+1,b);//取兩個“-”之間的字符串
return month;
}
public String getDay()//得到日的字符串
{
int b=dateStr.lastIndexOf("-");//求最后一個“-”的位數
int len=dateStr.length();//求字符串的長度
day=dateStr.substring(b+1,len);//取最后一個“-”以后的字符串
return day;
}
}
---------------------------------------------------------------------------------
一個javabean里最主要的是set和get方法:set方法用于從.jsp頁面向javabean傳值;get方法用于從javabean向.jsp頁面傳值。下面看.jsp頁面如何使用這個javabean:
------------------------------ymd_use_bean.jsp----------------------------------
<%@ page contentType="text/html; charset=gb2312" language="java" import="java.sql.*" errorPage="" %>
<jsp:useBean id="ymd" scope="page" class="ringz.javabeans.DateBean">
<jsp:setProperty name="ymd" property="*"/>
</jsp:useBean>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>使用javabean從字符串中取得年月日信息</title>
</head>
<body>
<%
try
{
out.println("您輸入的字符串是:"+ymd.getDateStr()+"<br>");
out.println("year="+ymd.getYear()+",month="+ymd.getMonth()+",day="+ymd.getDay());
}
catch(Exception e){}
%>
<br><br><hr><br>請在下邊的文本框中輸入代表年月日的字符串,格式:XXXX-XX-XX,其中代表年、月、日的位數可以不限定。
<form method="post" action="ymd_use_bean.jsp">
<input type="text" name="dateStr"><!--必須和所使用的javabean:DateBean中的這個“private String dateStr;”所定義的名稱完全一致!!!-->
<input type="submit" value="確定">
(必須使用兩個“-”分開,如:1999-9-29)
</form>
</body>
</html>
--------------------------------------------------------------------------------
你在這段代碼里能看到get方法,可是set方法呢?怎么沒看見?這里面的玄機在<jsp:useBean></jsp:useBean>之間和form里的這句:<input type="text" name="dateStr">,這里我不想重點說明.jsp文件如何引用javabean,你不清楚的話請查閱其他資料。
另外在這里提一個小技巧你自己試一試:把try和catch的內容去掉,看看結果是什么樣的;把catch的內容改成這樣:
catch(Exception e)
{out.print(e);}
再看看結果是什么樣的。然后自己分析一下為什么會這樣。這是一個我經常使用的小技巧,不知道別人是不是也用這種方法來解決這種問題。
上面已經說了javabean就是一個類,下面我要用自己的話說一下什么是類,我是怎么理解類這個概念(理解的不一定準確,還請高手們給予指正,免的誤人子弟^_^!):
先是想起一個笑話:說有一種機器,從機器的一側放進一頭豬,機器的另一側就會出香腸。引申一下。這臺機器在一個倉庫里,這個倉庫里還有一臺能自動出豬毛和一臺出豬皮的機器。現在這個倉庫就可比做一個類,而每臺機器就是一個方法,因為這個倉庫是只針對豬的倉庫,所以這個倉庫一定在java.pig這個包(java的API——說白了就是類庫或者按照C的說法就是函數庫——里有很多類,這些類是分類存放的,每一個分類稱做一個包,比如,和輸入輸出有關的類就放在java.io包里,和繪制圖形相關的類就放在java.awt包里)里面,我們給這個倉庫起名叫PigFactory,這就是類名。現在拿來一頭豬:Japanese屬于類Pig,先通過和PigFactory同名的構造函數PigFactory()為處理這頭豬新建一個實例:
java.pig.PigFactory pf = new java.pig.PigFactory();
現在我們可以通過這個實例對這頭豬進行操作了——由于我們只想要它的皮,那就使用出皮的機器就行了,這臺機器作為一個方法叫做getSkin(),那么:
Skin pigskin = pf.getSkin(Japanese);
豬皮(pigskin)出來了,并且運送出倉庫,它屬于類“皮”(Skin)了。
類似的,還有一些專門處置牛、羊的倉庫,它們也有自動出皮的機器,所以也是方法:getSkin(),這也就是為什么我們會發現很多不同的類里邊有相同名稱的方法,如:getString方法。
我們可以發現:這臺自動出皮的機器是如何工作的,我們并不關心,我們所關心的只是怎樣使用它。我們也可以自己開發一個類(或者javabean),它的工作原理和SUN給我們開發好的API里的類是基本一致的。在使用時我們所關心的僅僅是如何把值傳給它和如何從它那里得到值。
以上是我的理解,可能有很多不確切的地方,希望大家指正。
說了這很多廢話以后,你可能想問:我們上面寫的javabean現在可以用了嗎?還不行。剛剛我們寫好的是一個.java文件,必須把它編譯成.class文件以后Jsp才能調用它。下面說怎么編譯,由于我現在沒有使用專門的java開發工具(如JBuilder),所以只能使用我們安裝的JDK(java 2 sdk)所提供的編譯工具:
把DateBean.java這個文件放到C:\下,“開始”-“運行”-“cmd命令”,在開啟的窗口中將當前路徑改為C:\,然后輸入:javac DateBean.java,回車,如果窗口中沒有提示出錯的話,OK,編譯成功了。這時你會發現和DateBean.java處于同目錄的地方多了一個DateBean.class文件,就是它了。現在的問題是它應該放在哪了。由于是我自己寫的javabean,所以我不打算把他們和Tomcat自帶的放在一起:之前我們定義了自己的根目錄:e:\MyJsp,在它的下面新建一個WEB-INF文件夾(注意大小寫),其下再建一個classes文件夾,放在這里就行了。當然你可以專門為你自己開發的javabean做一個包——就像SUN那樣——我自己的包名叫ringz.javabeans,所以我在classes文件夾下建了一個ringz的文件夾,里面再建一個javabeans文件夾,然后把我開發的.class文件放到這里。這時使用的時候要注意包名:<jsp:useBean id="ymd" scope="page" class="ringz.javabeans.DateBean" />。
本章需要注意的當然是每次改完后的.java文件都要重新編譯成.class文件,而且使用.class文件時要重啟Tomcat服務器。
CNBIE BLOG
--------------------------------------------------------------------------------
一個microsoft的.exe程序文件的啟動過程
原文:一個microsoft的.exe程序文件的啟動過程
一個microsoft的.exe程序的啟動過程
學習windows 編程從mfc角度來說可分為兩部分那就是WinMain函數以前的,和WinMain函
數以后的。前者涉及很多windows操作系統內部的知識,后者么看mfc源碼就可以了。雖然大
多數程序不需要你了解太多關于os加載應用程序這方面的知識,但我認為能較深入了解wind
ows os的運行情況對程序員是很有幫助的。
最近我正在研究一個microsoft的.exe程序的啟動過程,這也是以上所說的關于os如何加
載程序的知識,它包括進程創建,主線程 創建,PE文件加載,程序c運行時啟動函數以及四種
main函數的調用等許多令我不得不靜下心來好好思索的東東。從mfc編程角度來說,這些都是
不得見的,不過了解這些對程序員編制好的windows程序是有好處的。在平時的學習中中我有
很多疑點,到底在桌面雙擊一個exe程序,os調用的第一個函數是什么?甚至到現在我研究很
長時間后,還是得不到令我滿意的答案。不過在學習的過程中我還是又說收獲的,下面和大
家一起分享一下,我也把這段時間所學作一下總結。
要了解一個.exe程序的啟動過程就不得不了解一下有關操作系統方面的知識,such as“
進程,線程,虛擬內存"的基本的知識。當然這里我就不詳細介紹了,有興趣的同學可以自己
去查一查這方面的資料。在未真正開始之前,先統一一下本文出現的一些名詞的含義:
App.exe----------假定為應用mfc的AppWizard做出的一個SDI程序,App是它的名字。你
可以把它看為一個標準的"hello mfc!"程序。
PE------------不要以為它是“體育課”的縮寫呦。它可是微軟的標準win32可執行文件
.exe和動態鏈接庫.dll的文件格式,它的english name是Portable Executable File Forma
t。
下面可要正式開始了。
一個microsoft的.exe程序的啟動方法有很多,這里我們以雙擊App.exe圖標啟動為例(
其他方法,我想也是一樣的)。在補充一下,我所用的os是Windows2000Server,所以這里也
主要討論win2000下的應用程序,過要涉及較多關于NT內核,畢竟微軟主推win2000/winxp和
Unicode么。
一個microsoft的.exe程序的啟動過程如下:
(1)當我們雙擊App.exe圖標啟動程序時,系統首先做什么呢,讓我們先聽一聽侯捷是如何
說的吧“執行起來的App進程其實是shell調用CreateProcess激活的”----"深入淺出MFC se
cond edition" page39載。很多書上都是如是說的,shell又名“命令解釋器”,是win32操
作系統基于瀏覽器的一個32位用戶接口,它是一個多線程的好例子,屏幕上每一個文件夾瀏
覽窗口都是它的一個線程。它是操作系統引導時加載的系統進程,它具體表現為windows ex
plorer.exe。explorer.exe是所有用戶應用程序的創造者。你完全可以將shell看成是所有應
用程序進程的父進程,就像桌面(desktop)可看成所有窗口的父窗口一樣。shell的用途很多
,如啟動應用程序,管理文件系統,將應用程序與相應文件相關聯等等。我們常見的桌面上
的帶有小箭頭的快捷方式(shortcut)就是一個shell鏈接,shell負責管理一個叫"名字空間"
的類似文件系統似的“超文件系統”,它允許應用程序在任何地方在不知訪問對象名字和位置
的前提下訪問到這個對象,此類對象有:文件,目錄,驅動器,打印機以及網絡資源。而名
字空間就是shell把這些對象有層次組織起來的一個結構。名字空間為用戶和應用程序提供了
一種可靠和高效的方法來訪問和管理對象。好了不論它是什么,凡正它調用了CreateProcess,一切就從這里開始了。
(2)CreateProcess這個函數可作了不少工作。App進程由此誕生。當CreateProcess這個函
數被調用,系統就會創建一個“進程內核對象”。進程內核對象可以看作一個操作系統用來
管理進程的內核對象,它也是系統用來存放關于進程統計信息的地方(一個小的數據結構)
,其實它的真正創建者是一個叫NtCreateProcess的windows2000系統服務函數(也叫執行體服
務函數),他創建了進程內核對象供用戶擴展。進程內核對象的初始使用計數為1。然后系統
為該進程創建4GB(=2^32)的虛擬地址空間(所謂虛擬就不是真的創建4GB的物理內存空間,這
些空間不是真在物理內存上).用于加載App.exe可執行文件和任何必要的dll文件的數據和代
碼。
(3)下面概述一下系統的加載器(可稱為loader)是如何加載這些東東的。首先了解一下系
統為該進程創建4GB的虛擬地址空間是如何分配的,對于win2000/winxp來說,默認情況下每
個用戶進程可以占有2GB的私有地址空間;操作系統占有剩余的2GB空間。
在32位x86系統上,
從0x00000000到0x7fffffff的空間中存放著 應用程序代碼,全局變量,每個線程堆棧,dll
代碼。
從0x80000000到0xc0000000的空間中存放著 內核和執行體,HAL(硬件抽象層),引導驅動程序
。
從0xc0000000到0xc0800000的空間中存放著 進程頁表和超空間。
從0xc0800000到0xffffffff的空間中存放著 系統高速緩存,分頁緩沖池,非分頁緩沖池。
首先,CreateProcess打開應用程序文件(.exe),它先掃描該文件的文件頭,該文件頭里含有文
件能運行在那個環境之下,如果是win32環境,系統就直接加載文件的代碼和數據并輸入(im
port)該文件執行所需的dll函數。如果不是win32環境比如時os/2的.exe則先加載相應的環境
子系統,載由該環境加載該文件的代碼和數據以及該文件執行所需的dll函數。至于系統是如
何知道文件的代碼和數據以及該文件執行所需的dll函數所在的位置就需要你了解一下PE文件
格式了,其實也很簡單,PE文件擁有很多sections,數據和代碼都放在不同的section里面,
文件執行所需的dll也放在單獨的section(.idata)里,這里就不詳述了。而且在加載過程中涉
及到有關虛擬內存,內存映射文件等很多較深的知識,我會在以后的系列文章中詳細專題論
述的。
(4)進程加載代碼和數據完畢后,就開始創建線程來執行進程空間內的代碼。進程是靜態的
,它只是線程的容器。一個進程至少因該有一個線程(main thread),其它線程都是主線程通
過調用CreateThread函數創建的。線程也是核心對象,他的實際創建者是一個叫NtCreateTh
read的windows2000系統服務函數。一個線程其實只是一個線程核心對象和兩個堆棧(一個核
心堆棧,用于線程運行在核心態;一個用戶堆棧,用于線程運行在用戶態),線程與進程類似
,也擁有線程核心對象計數和線程句柄,這里不詳述。線程用于描述進程中的運行路徑。每
當進程被初始化時,系統就要創建一個主線程。該線程與c/c++運行時庫的啟動代碼一道開始
運行,啟動代碼則調用進入點函數(就是我們的main函數,它也是主線程的進入點函數),并
且繼續運行直到進入點函數返回并且c/c++運行時庫的啟動代碼調用ExitProcess為止。每個
線程都有自己的入口點函數,主線程入口點函數名字必須是main,wmain,WinMain或wWinMain
.而其他的線程入口點函數名字可使用任何名字。每個線程函數必須有一個返回值,它將作為
線程的退出代碼。對于主線程來說,這個返回值將傳給c/c++運行時庫的啟動函數。
(5)c/c++運行時庫的啟動函數它其實是一個程序的真正調用的第一個函數,它是在程序鏈
接時由鏈接程序選擇相應的啟動函數并加到程序的開始處。c/c++運行時庫有四個版本的啟動
函數,他們分別對應不同類型的應用程序。比如,需要ANSI字符和字符串的GUI應用程序的啟
動函數是WinMainCRTStartup,其對應的進入點函數是
WinMain,需要Unicode字符和字符串的GUI應用程序的啟動函數是wWinMainCRTStartup,其對應
的進入點函數是
wWinMain,而需要ANSI字符和字符串的CUI應用程序(如控制臺console程序)的應用程序的啟動
函數是mainCRTStartup,對應的入口點函數為main;需要Unicode字符和字符串的CUI應用程序
(如控制臺console程序)的應用程序的啟動函數為wmainCRTStartup,對應的入口點函數為wma
in;c/c++運行時庫的啟動函數的功能如下:
以wWinMainCRTStartup(大多數運行在windows2000下的應用程序的啟動函數都是它)為例。它
負責:
*檢索指向新進程的完整命令行指針;
*檢索指向新進程的環境變量的指針;
*對c/c++運行時的全局變量進行初始化;
*對c運行期的內存單元分配函數(比如malloc,calloc)和其他低層I/O例程使用的內存棧進
行初始化。
*為C++的全局和靜態類調用構造函數。
當這些初始化工作完成后,該啟動函數就調用wWinMain函數進入應用程序的執行。
當wWinMain函數執行完畢返回時,wWinMainCRTStartup啟動函數就調用c運行期的exit()函
數,將返回值
(nMainRetVal)傳遞給它。之后exit()便開始收尾工作:
*調用由_onexit()函數調用和注冊的任何函數。
*為C++的全局和靜態類調用析構函數;
*調用操作系統的ExitProcess函數,將nMainRetVal傳遞給它,這使得操作系統能夠撤銷進
程并設置它的exit 代碼。
(6)至此啟動函數的任務完成,至于中間wWinMain函數的運行過程看看mfc源碼即可。不過我還要提一下,wWinMain函數其實只是調用了mfc的AfxWinMain()函數,而一切的真正代碼的運
行也是從AfxWinMain()開始的。
以上只是粗略將一下一個microsoft的.exe程序的啟動過程,其中有很多深奧的知識我只是提了一下,有些知識在以后的文章中還會陸續提到的。
bigwhite
2002.5.18
CNBIE BLOG
--------------------------------------------------------------------------------
一個oracle+PHP的查詢的例子
原文:一個oracle+PHP的查詢的例子
http://qdlover.yeah.net
一個oracle+PHP的查詢的例子
本來我不用php了,可是還是有很多朋友問我,我就做了一個例子,具體函數請查手冊
其實oracle的函數和別的也差不多,只不過它這里多了一個定義輸出變量的過程,
如果學過pl/sql的人都知道的(不過聽說只有清華和西安交大用它做網站)。
就是OCIDefineByName($id,"ROWNUM",&$rownum);對應了查詢中的rownum,一個對應一個,
而且最應該注意的就是,在定義的時候,字段名必須是大寫的,因為oracle里不認小寫
其它的就差不多了,賦值,顯示,關閉游標
$conn = ocilogon("gcxx","gcxx","server1");
$id = OCIParse($conn,"select rownum,gcdjbh,gcmc from zbgg");
OCIDefineByName($id,"ROWNUM",&$rownum);
OCIDefineByName($id,"GCDJBH",&$gcdjbh);
OCIDefineByName($id,"GCMC",&$gcmc);
OCIExecute($id);
$i=0;
while (OCIFetch($id)) {
echo "序號:".$rownum."
";
echo "工程登記編號:".$gcdjbh."
";
echo "工程名稱:".$gcmc."
";
$i++;
if ($i>10) break;
}
OCIFreeStatement($id);
OCILogoff($conn);
?>
(出處:Viphot)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -