2007/06/23

Call Stored Procedure

不同資料庫的Stored Procedure的呼叫方式應該是大同小異,至少透過JDBC來呼叫更應該如此吧?! 但是,我只在Oracle 9.2上試過,所以,以下的方法只保證在Oracle 9.2下執行是正確的。
假設目前有stored procedure - gpv(empId, password)
它的功能是傳入員工編號 (empId),傳回加密的密碼,並且,當執行成功時,會傳回0,失敗時會傳回錯誤代碼,傳回值的型別是整數,那麼程式該怎麼寫?

con = pool.getConnection(); // 由Connection Pool取得Connection
sql = "{ ? = call gpv(?, ?) }"; // sql statement,詳見說明A
cstmt = con.prepareCall(sql); // cstmt的型別是CallableStatement
cstmt.registerOutParameter(1, Types.INTEGER); // 說明B
cstmt.setString(2, emp_id); // 說明C
cstmt.registerOutParameter(3, Types.LONGVARCHAR);
cstmt.execute(); // 執行
ret = cstmt.getInteger(1);
pwd = cstmt.getString(3).trim(); //說明D

  • 說明A:這是呼叫stored procedure的途述,如上是當有傳回值時,如果沒有傳回值要寫成{ call gpv(?, ?) }
  • 說明B:如果參數將會傳回值的話,必須註冊。
  • 說明C:當參數只傳入不傳出時,如此設定。
  • 說明D:傳回值是第一個參數,傳回的參數是第三個參數。
[轉貼自 - 史帝芬心得筆記]

2007/06/07

Java Excel Api - II

Workbook類提供的方法

  1. int getNumberOfSheets()

  獲得工作薄(Workbook)中工作表(Sheet)的個數,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
int sheets = rwb.getNumberOfSheets();

  2. Sheet[] getSheets()

  返回工作薄(Workbook)中工作表(Sheet)物件陣列,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
Sheet[] sheets = rwb.getSheets();

  3. String getVersion()

  返回正在使用的API的版本號,好像是沒什麼太大的作用。
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
String apiVersion = rwb.getVersion();

  Sheet介面提供的方法

  1) String getName()

  獲取Sheet的名稱,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
String sheetName = rs.getName();

  2) int getColumns()

  獲取Sheet表中所包含的總列數,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
int rsColumns = rs.getColumns();

  3) Cell[] getColumn(int column)

  獲取某一列的所有單格,返回的是單格物件陣列,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell[] cell = rs.getColumn(0);

  4) int getRows()

  獲取Sheet表中所包含的總行數,示例:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
int rsRows = rs.getRows();

  5) Cell[] getRow(int row)

  獲取某一行的所有單格,返回的是單格物件陣列,示例子:
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell[] cell = rs.getRow(0);

  6) Cell getCell(int column, int row)

  獲取指定單格的物件引用,需要注意的是它的兩個參數,第一個是列數,第二個是行數,這與通常的行、列組合有些不同。
jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile));
jxl.Sheet rs = rwb.getSheet(0);
Cell cell = rs.getCell(0, 0);

  2、生成新的Excel工作薄

  下面的代碼主要是向大家介紹如何生成簡單的Excel工作表,在這裏單格的內容是不帶任何修飾的(如:字體,顏色等等),所有的內容都作為字串寫入。(完整代碼見ExcelWriting.java)

  與讀取Excel工作表相似,首先要使用Workbook類的工廠方法創建一個可寫入的工作薄(Workbook)物件,這裏要注意的是,只能通過API提供的工廠方法來創建Workbook,而不能使用WritableWorkbook的構造函數,因為類WritableWorkbook的構造函數為protected類型。示例代碼片段如下:
import java.io.*;
import jxl.*;
import jxl.write.*;
… … … …
try
{
//構建Workbook物件, 唯讀Workbook物件
//Method 1:創建可寫入的Excel工作薄
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile));

//Method 2:將WritableWorkbook直接寫入到輸出流
/*
OutputStream os = new FileOutputStream(targetfile);
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os);
*/
}
catch (Exception e)
{
e.printStackTrace();
}

  API提供了兩種方式來處理可寫入的輸出流,一種是直接生成本地檔,如果檔案名不帶全路徑的話,缺省的檔會定位在當前目錄,如果檔案名帶有全路徑的話,則生成的Excel檔則會定位在相應的目錄;另外一種是將Excel物件直接寫入到輸出流,例如:用戶通過流覽器來訪問Web伺服器,如果HTTP頭設置正確的話,流覽器自動調用用戶端的Excel應用程式,來顯示動態生成的Excel試算表。

  接下來就是要創建工作表,創建工作表的方法與創建工作薄的方法幾乎一樣,同樣是通過工廠模式方法獲得相應的物件,該方法需要兩個參數,一個是工作表的名稱,另一個是工作表在工作薄中的位置,參考下面的代碼片段:
//創建Excel工作表
jxl.write.WritableSheet ws = wwb.createSheet("Test Sheet 1", 0);

"這鍋也支好了,材料也準備齊全了,可以開始下鍋了!",現在要做的只是實例化API所提供的Excel基本資料類型,並將它們添加到工作表中就可以了,參考下面的代碼片段:
//1.添加Label對象
jxl.write.Label labelC = new jxl.write.Label(0, 0, "This is a Label cell");
ws.addCell(labelC);

//添加帶有字型Formatting的物件
jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TIMES, 18, WritableFont.BOLD, true);
jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf);
jxl.write.Label labelCF = new jxl.write.Label(1, 0, "This is a Label Cell", wcfF);
ws.addCell(labelCF);

//添加帶有字體顏色Formatting的物件
jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false,
Underlinestyle.NO_UNDERLINE, jxl.format.Colour.RED);
jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc);
jxl.write.Label labelCFC = new jxl.write.Label(1, 0, "This is a Label Cell", wcfFC);
ws.addCell(labelCF);

//2.添加Number對象
jxl.write.Number labelN = new jxl.write.Number(0, 1, 3.1415926);
ws.addCell(labelN);

//添加帶有formatting的Number對象
jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##");
jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf);
jxl.write.Number labelNF = new jxl.write.Number(1, 1, 3.1415926, wcfN);
ws.addCell(labelNF);

//3.添加Boolean對象
jxl.write.Boolean labelB = new jxl.write.Boolean(0, 2, false);
ws.addCell(labelB);

//4.添加DateTime對象
jxl.write.DateTime labelDT = new jxl.write.DateTime(0, 3, new java.util.Date());
ws.addCell(labelDT);

//添加帶有formatting的DateFormat對象
jxl.write.DateFormat df = new jxl.write.DateFormat("dd MM yyyy hh:mm:ss");
jxl.write.WritableCellFormat wcfDF = new jxl.write.WritableCellFormat(df);
jxl.write.DateTime labelDTF = new jxl.write.DateTime(1, 3, new java.util.Date(), wcfDF);
ws.addCell(labelDTF);

  這裏有兩點大家要引起大家的注意。第一點,在構造單格時,單格在工作表中的位置就已經確定了。一旦創建後,單格的位置是不能夠變更的,儘管單格的內容是可以改變的。第二點,單格的定位是按照下面這樣的規律(column, row),而且下標都是從0開始,例如,A1被存儲在(0, 0),B1被存儲在(1, 0)。

  最後,不要忘記關閉打開的Excel工作薄物件,以釋放佔用的記憶體,參見下面的代碼片段:
//寫入Exel工作表
wwb.write();

//關閉Excel工作薄物件
wwb.close();

  這可能與讀取Excel檔的操作有少少不同,在關閉Excel物件之前,你必須要先調用write()方法,因為先前的操作都是存儲在緩存中的,所以要通過該方法將操作的內容保存在檔中。如果你先關閉了Excel物件,那麼只能得到一張空的工作薄了。

  3、拷貝、更新Excel工作薄

  接下來簡要介紹一下如何更新一個已經存在的工作薄,主要是下面二步操作,第一步是構造唯讀的Excel工作薄,第二步是利用已經創建的Excel工作薄創建新的可寫入的Excel工作薄,參考下面的代碼片段:(完整代碼見ExcelModifying.java)
//創建唯讀的Excel工作薄的物件
jxl.Workbook rw = jxl.Workbook.getWorkbook(new File(sourcefile));

//創建可寫入的Excel工作薄物件
jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile), rw);

//讀取第一張工作表
jxl.write.WritableSheet ws = wwb.getSheet(0);

//獲得第一個單格對象
jxl.write.WritableCell wc = ws.getWritableCell(0, 0);

//判斷單格的類型, 做出相應的轉化
if(wc.getType() == CellType.LABEL)
{
Label l = (Label)wc;
l.setString("The value has been modified.");
}

//寫入Excel對象
wwb.write();

//關閉可寫入的Excel對象
wwb.close();

//關閉唯讀的Excel對象
rw.close();

  之所以使用這種方式構建Excel物件,完全是因為效率的原因,因為上面的示例才是API的主要應用。為了提高性能,在讀取工作表時,與資料相關的一些輸出資訊,所有的格式資訊,如:字體、顏色等等,是不被處理的,因為我們的目的是獲得行資料的值,既使沒有了修飾,也不會對行資料的值產生什麼影響。唯一的不利之處就是,在記憶體中會同時保存兩個同樣的工作表,這樣當工作表體積比較大時,會佔用相當大的記憶體,但現在好像記憶體的大小並不是什麼關鍵因素了。

  一旦獲得了可寫入的工作表物件,我們就可以對單格物件進行更新的操作了,在這裏我們不必調用API提供的add()方法,因為單格已經於工作表當中,所以我們只需要調用相應的setXXX()方法,就可以完成更新的操作了。

  盡單格原有的格式化修飾是不能去掉的,我們還是可以將新的單格修飾加上去,以使單格的內容以不同的形式表現。

  新生成的工作表物件是可寫入的,我們除了更新原有的單格外,還可以添加新的單格到工作表中,這與示例2的操作是完全一樣的。

  最後,不要忘記調用write()方法,將更新的內容寫入到檔中,然後關閉工作薄物件,這裏有兩個工作薄物件要關閉,一個是唯讀的,另外一個是可寫入的。

[以上文章均為轉貼自香港IT網]

Java Excel Api - I

使用Windows作業系統的朋友對Excel(試算表)一定不會陌生,但是要使用Java語言來操縱Excel檔並不是一件容易的事。在Web應用日益盛行的今天,通過Web來操作Excel檔的需求越來越強烈,目前較為流行的操作是在JSP或Servlet 中創建一個CSV (comma separated values)檔,並將這個檔以MIME,text/csv類型返回給流覽器,接著流覽器調用Excel並且顯示CSV檔。這樣只是說可以訪問到Excel檔,但是還不能真正的操縱Excel檔,本文將給大家一個驚喜,向大家介紹一個開放源碼項目,Java Excel API,使用它大家就可以方便地操縱Excel檔了。

  Java Excel API簡介

  Java Excel是一開放源碼專案,通過它Java開發人員可以讀取Excel檔的內容、創建新的Excel檔、更新已經存在的Excel檔。使用該API非Windows作業系統也可以通過純Java應用來處理Excel資料表。因為是使用Java編寫的,所以我們在Web應用中可以通過JSP、Servlet來調用API實現對Excel資料表的訪問。

  現在發佈的穩定版本是V2.0,提供以下功能:

   從Excel 95、97、2000等格式的檔中讀取資料;
   讀取Excel公式(可以讀取Excel 97以後的公式);
   生成Excel資料表(格式為Excel 97);
   支援字體、數位、日期的格式化;
   支援單格的陰影操作,以及顏色操作;
   修改已經存在的資料表;

  現在還不支援以下功能,但不久就會提供了:

   不能夠讀取圖表資訊;
   可以讀,但是不能生成公式,任何類型公式最後的計算值都可以讀出;
 
   應用示例

  1、從Excel檔讀取資料表

  Java Excel API既可以從本地檔系統的一個檔(.xls),也可以從輸入流中讀取Excel資料表。讀取Excel資料表的第一步是創建Workbook(術語:工作薄),下面的代碼片段舉例說明了應該如何操作:(完整代碼見ExcelReading.java)
import java.io.*;
import jxl.*;
… … … …
try
{
//構建Workbook物件, 唯讀Workbook物件
//直接從本地檔創建Workbook
//從輸入流創建Workbook
InputStream is = new FileInputStream(sourcefile);
jxl.Workbook rwb = Workbook.getWorkbook(is);
}
catch (Exception e)
{
e.printStackTrace();
}

  一旦創建了Workbook,我們就可以通過它來訪問Excel Sheet(術語:工作表)。參考下面的代碼片段:
//獲取第一張Sheet表
Sheet rs = rwb.getSheet(0);

  我們既可能通過Sheet的名稱來訪問它,也可以通過下標來訪問它。如果通過下標來訪問的話,要注意的一點是下標從0開始,就像陣列一樣。

  一旦得到了Sheet,我們就可以通過它來訪問Excel Cell(術語:單格)。參考下面的代碼片段:
//獲取第一行,第一列的值
Cell c00 = rs.getCell(0, 0);
String strc00 = c00.getContents();

//獲取第一行,第二列的值
Cell c10 = rs.getCell(1, 0);
String strc10 = c10.getContents();

//獲取第二行,第二列的值
Cell c11 = rs.getCell(1, 1);
String strc11 = c11.getContents();

System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType());
System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType());
System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType());

  如果僅僅是取得Cell的值,我們可以方便地通過getContents()方法,它可以將任何類型的Cell值都作為一個字串返回。示例代碼中Cell(0, 0)是文本型,Cell(1, 0)是數字型,Cell(1,1)是日期型,通過getContents(),三種類型的返回值都是字元型。

  如果有需要知道Cell內容的確切類型,API也提供了一系列的方法。參考下面的代碼片段:
String strc00 = null;
double strc10 = 0.00;
Date strc11 = null;

Cell c00 = rs.getCell(0, 0);
Cell c10 = rs.getCell(1, 0);
Cell c11 = rs.getCell(1, 1);

if(c00.getType() == CellType.LABEL)
{
LabelCell labelc00 = (LabelCell)c00;
strc00 = labelc00.getString();
}
if(c10.getType() == CellType.NUMBER)
{
NmberCell numc10 = (NumberCell)c10;
strc10 = numc10.getvalue();
}
if(c11.getType() == CellType.DATE)
{
DateCell datec11 = (DateCell)c11;
strc11 = datec11.getDate();
}

System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " + c00.getType());
System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " + c10.getType());
System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " + c11.getType());

  在得到Cell物件後,通過getType()方法可以獲得該單格的類型,然後與API提供的基本類型相匹配,強制轉換成相應的類型,最後調用相應的取值方法getXXX(),就可以得到確定類型的值。API提供了以下基本類型,與Excel的資料格式相對應,如下圖所示:

  每種類型的具體意義,請參見Java Excel API document.

  當你完成對Excel試算表資料的處理後,一定要使用close()方法來關閉先前創建的物件,以釋放讀取資料表的過程中所佔用的記憶體空間,在讀取大量資料時顯得尤為重要。參考如下代碼片段:
//操作完成時,關閉物件,釋放佔用的記憶體空間
rwb.close();

  Java Excel API提供了許多訪問Excel資料表的方法,在這裏我只簡要地介紹幾個常用的方法,其他的方法請參考附錄中的Java Excel API document。

[以上文章均為轉貼自香港IT網]

2007/05/23

Subversion 最佳實務

Subversion 最佳實務 [轉貼自愛德華日誌]

這裡提供一組快速的指導原則,讓你能在每天的軟體開發工作中發揮 Subversion 的最大效用。
採用建全的儲存庫配置

儲存庫的目錄配置有許多方式。由於 branches 和 tags 只是一般的目錄,你必須在配置儲存庫的結構時,把它們考慮進去。

Subversion 官方文件建議採用專案根目錄的觀念,來代表專案在儲存庫中的掛載點。專案根目錄裡面僅包含三個子目錄:/trunk, /branches, 及 /tags。一個儲存庫裡面可包含一個或多個專案根目錄。

參考書籍: Choosing a Repository Layout.
以邏輯變更集(changesets)作為提交單位

當你將修改提交到儲存庫時,要確認你的更動反應的是單一的目的:修正一個特定的臭蟲、增加一個新的特性、或是一些特定的工作。你的提交將會產生一個版本號碼,這號碼在往後可用來作為該次變更的 "名稱"。你可以在臭蟲資料庫中記錄這個號碼,或把它拿來作為 svn merge (合併) 的參數。

參考書藉:"Subversion and Changesets" sidebar, within chapter 4.
善用事例追蹤軟體 (issue-tracker)

盡可能試著建立 Subversion 與 issue-tracker 資料庫之間的雙向連結:

* 盡可能在每個提交的登錄訊息 (log message) 中參引到明確的事例編號
* 在事例中附加訊息時 (描述進度,或是關閉事例),註記相應於此事例變更作業的版本號碼

手動追蹤合併

當提交合併的結果時,切記寫下解釋合併了些什麼的描述性資訊,像是:

將 /branches/foobranch 版號 3490:4120 合併至 /trunk。

參考書藉:Tracking merges manually, and Merging a whole branch to another.
了解混合版本的工作複本

存放工作複本的目錄及檔案可以處於不同的工作版號中:這種特意的設計讓你可以混編不同的新舊版號。但是有些事實是你必須注意的:

1. 每次的提交,都會讓你的工作複本包含不同的版號。你剛提交的變更是位於 HEAD 版號中,而其他的部份則屬於之前的版號。
2. 有許多的情況不允許提交:
* 若是某檔案或目錄沒有包含在 HEAD 的工作版號中,那你便不能提交其刪除動作。
* 若是某目錄沒有包含在 HEAD 的工作版號中,那你便不能提交其變更屬性的動作。
3. svn 更新 (update) 指令可以幫你取回整個工作版號的複本,而這也是第 2 個問題常用的解決方案。

參考書籍:The limitation of mixed revisions.
處理較大的檔案時要有耐心

Subversion 的優點之一是:在設計上,它並沒有對處理檔案的大小做限制。檔案以 "流(streamily)" 的形式在 Subversion client 及 server 兩端收送,而網路兩端只使用了少許的、定量的記憶體。

當然,有許多實務上的問題需要考量。雖然沒有必要擔心幾 K 位元組大小左右的檔案 (像是一般的原始檔),提交較大的檔案會花費大量的時間及空間 (像是幾十或幾百 mega 位元組大小的檔案)。

首先,記得 Subversion 的工作複本會在 .svn/text-base/ 目錄內儲存了所有接受版本控管檔案的初始複本(pristine copy)。這表示你的工作複本至少會占用原本資料集的兩倍磁碟空間。此外,Subversion client 會採用 (目前無法調整的) 演算法來提交檔案:

* 將檔案複製到 .svn/tmp/ (這會花一些時間,而暫存檔也會占用額外的磁碟空間)
* 對暫存檔與初始複本 (pristine copy) 進行二進位的差異比對,若是新增加的檔案則會拿暫存檔與空檔比對。(這可能會花很長的時間運算,即使最終只有很少量的資料會傳送到網路的另一端)
* 將差異送到伺服器,並將暫存檔移入 .svn/text-base/

因此雖然在理論上沒有檔案大小的限制,你還是得注意,當 client 程式在蹣跚處置較大檔案時,你得要耐著性子等待。然而,你可以放心的是,不像在 CVS,較大的檔案不會讓你的伺服器掛點,或影響到其他使用者。
因應那些不認得 copies/renames 動作的指令

在檔案或目錄複製或更名後,Subversion 儲存庫會追蹤歷程記錄。不幸的,在 Subversion 1.0 裡,善用這項特性的 client 端指令只有 svn log。許多其他指令 (例如 svn diff 及 svn cat) 應該要能自動追蹤更名歷程,但卻還沒這麼做。

面對這種情況,基本的因應之道是使用 'svn log -v' 指令找出舊版的檔案路徑。

例如,假設你在版號 200 中將 /trunk 複製到 /branches/mybranch,並在後續的版號中提交了對 /branches/mybranch/foo.c 的修改。現在你想比較該檔的 80 及 250 版號。

如果你有該分支的工作複本,並執行 svn diff -r80:250 foo.c,你會看到在版號 80 裡面並不存在 /branches/mybranch/foo.c 的錯誤訊息。補救方法是在你的分支或檔案上執行 svn log -v,以得知它在版號 200 之前稱為 /trunk/foo.c,接著就可以直接比較兩個 URL 了:

$ svn diff http://.../trunk/foo.c@80 http://.../branches/mybranch/foo.c@200
確定建立分支的時機

這是經常被爭論的話題,事實上這應該視軟體專案文化而定,而不是一套事先訂定的、放諸四海皆準的政策。我們將討論比較常見的三種型式:
從不分支的系統

(常用於還沒有可執行程式的初始專案)

* 使用者直接將每天的變更提交到 /trunk 中。
* 當某使用者開始提交一連串的複雜變更時,偶爾會造成 /trunk 的破壞 (無法編譯,或不能通過功能測試)。

優點:易於遵字的政策。新進開發人員進入門檻較低。沒有人需要學習如何操作分支及合併。

缺點:開發過程混亂,程式碼可能在任何時間產生不穩固的狀況。

附註:這種開發模式在 Subversion 中比 CVS 裡風險少一點點。因為 Subversion 的提交是單元式的 (atomic),即使當某人正在提交變更時,你也不可能僅取出 (checkout) 或更新 (update) 部分提交的變更。
總是分支的系統

(常用於傾向重度管理及監督的專案)

* 每個使用者在他自己所建立的分支上進行開發工作。
* 當實作完成後,某人 (原來的程式設計師,同儕,或經理) 複審所有私有分支的改變後,再將變更合併至 /trunk。

優點:可以保證 /trunk 在任何時間都相當穩固。

缺點:程式開發工作在此人為因素下與其他人分隔開來,可能產生更多不必要的合併衝突,而需要使用者進行許多額外的合併工作。
當需要時才分支的系統

(這是 Subversion 專案所採用的型式)

* 使用者將每天的工作提交到 trunk 上
* 規則 1:/trunk 必須在任何時間都能編譯,並通過回歸測試,違反此規則的提交者將在眾人面前無地自容。
* 規則 2:單一的提交 (changeset) 不應太大,免得同儕難以複審。
* 規則 3:若是規則 1 與規則 2 衝突 (例如,無法進行一連串的小提交同時保持 trunk 的穩固),那使用者就應建立一個分支,再於該分支上進行一連串的變更集小提交。這可以讓同儕順利進行複審,又保持 /trunk 的穩固性。

優點:可保證 /trunk 在任何時間都很穩固,也不用常常進行煩人的分支及合併。

缺點:會稍微增加使用者每天的工作負擔,他們在每次的提交前必須進行編譯及測試。

2007/04/23

Javascript - Regular Express

Regular Express 簡介

範例:

檢查日期格式 1900/1/12:/^\d{4}\/\d{1,2}\/\d{1,2}$/

檢查信用卡號 xxxx-xxxx-xxxx-xxxx:/^\d{4}-\d{4}-\d{4}-\d{4}$/

檢查身分證號碼 A000000000 : /^[A-Z]\d{9}$/

檢查IP格式 : /^\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b$/

檢查僅能輸入英文數字格式 : /^\w{1,}$/

2007/04/09

Windows - 最佳化虛擬記憶體

如果要讓 Windows 選擇最佳的分頁檔大小,請按一下 [系統管理大小]。
建議的最小值為您電腦上 RAM 的 1.5 倍,而最大值則為這個數字的 3 倍。
例如,假設您有 256 MB 的 RAM,則最小值應為 384 MB,最大值應為 1152 MB。

NGINX SSL/設定檔案

#user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #...