1用JAVA自帶的函數
publicstaticbooleanisNumeric(String str){
??for(inti=str.length();--i>=0;){???
???if(!Character.isDigit(str.charAt(i))){
????returnfalse;
??? }
?? }
??returntrue;
}
2用正則表達式
public static boolean isNumeric(String str){
???? Pattern pattern = Pattern.compile("[0-9]*");
???? return pattern.matcher(str).matches();????
}
3用ascii碼
public static booleanisNumeric(String str){
??for(inti=str.length();--i>=0;){
??????intchr=str.charAt(i);
?????? if(chr<48 || chr>57)
?????????return false;
??? }
???return true;
}
posted @
2007-10-14 01:31 jadmin 閱讀(76) |
評論 (0) |
編輯 收藏
import java.io.*;
public class ToFile
{
public static void main(String[] args)
{
?? try
?? {
??? String filename = "out.txt";
??? BufferedWriter bw = new BufferedWriter(new FileWriter(filename));
??? bw.write("Hello,China!");
??? bw.write("\n");
??? bw.write("Hello,World!");
??? bw.close();
?? }
?? catch(IOException e)
?? {
??? System.out.println("IOException");
??? e.printStackTrace();
?? }
}
}
posted @
2007-10-08 21:45 jadmin 閱讀(93) |
評論 (0) |
編輯 收藏
古之欲明明德于天下者,先治其國;
欲治其國者,先齊其家;欲齊其家者,先修其身;
欲修其身者,先正其心;欲正其心者,先誠其意;
欲誠其意者,先致其知,致知在格物。
posted @
2007-10-04 12:36 jadmin 閱讀(132) |
評論 (0) |
編輯 收藏
在網絡給我們的工作學習帶來極大方便的同時,病毒、木馬、后門以及黑客程序也嚴重影響著信息的安全。這些程序感染計算機的一個共同特點是在注冊表中寫入信息,來達到如自動運行、破壞和傳播等目的。以下是筆者在網上收集的,通過修改注冊表來對付病毒、木馬、后門以及黑客程序,保證個人計算機的安全。
1.清理訪問“網絡鄰居”后留下的字句信息
在HEKY_CURRENT_USER\Network\Recent下,刪除下面的主鍵。
2.取消登陸時自動撥號
在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Network\RealModeNet下修改右邊窗口中的“autologon”為“01 00 00 00 00”。
3.取消登錄時選擇用戶
已經刪除了所有用戶,但登錄時還要選擇用戶,我們要取消登錄時選擇用戶,就要在HKEY_LOCAL_MACHINENetworkLogon下,在右邊的窗口中,修改"UserProfiles"值為"0"。
4.隱藏上機用戶登錄的名字
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Winlogon下在右邊的窗口中新建字符串"DontDisplayLastUserName",設值為"1"。
5.預防Acid Battery v1.0木馬的破壞
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices下若在右邊窗口中如發現了“Explorer”鍵值,則說明中了YAI木馬,將它刪除。
6.預防YAI木馬的破壞
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices下若在右邊窗口中如發現了“Batterieanzeige”鍵值,則說明中了YAI木馬,將它刪除。
7.預防Eclipse 2000木馬的破壞
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices下若在右邊窗口中如發現了“bybt”鍵值,則將它刪除。
然后在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices下刪除右邊的鍵值“cksys”,重新啟動電腦。
8.預防BO2000的破壞
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices下若在右邊窗口中如發現了“umgr32.exe”鍵值,則說明中了BO2000,將它刪除。
9.預防愛蟲的破壞
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run下若在右邊窗口中如發現了“MSKernel32”鍵值,就將它刪除。
10.禁止出現IE菜單中“工具”欄里“interner選項”
把c:\windows\system下的名為inetcpl.cpl更名為inetcpl.old或則別的名字后就會出現禁止使用的情況把名字再換回來,就可以恢復使用。
11.預防BackDoor的破壞
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run下若在右邊窗口中如發現了“Notepad”鍵值,就將它刪除。
12.預防WinNuke的破壞
在HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\VxDMSTCP下在右邊的窗口中新建或修改字符串“BSDUrgent”,設其值為0。
13.預防KeyboardGhost的破壞
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunServices下如發現KG.EXE這一鍵值,就將它刪除,并查找KG.exe文件和kg.dat文件,將它們都刪除。
14.查找NetSpy黑客程序
在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run下,在右邊的窗口中尋找鍵"NetSpy",如果存在,就說明已經裝有NetSpy黑客程序,把它刪除。
posted @
2007-10-03 10:00 jadmin 閱讀(45) |
評論 (0) |
編輯 收藏
package com.zh.util;
import com.zh.conpool.Condata;
import java.sql.ResultSet;
import java.sql.SQLException;
public class page
{
???? ResultSet rs;
???? ResultSet rst;
???? private int intCountTopic;
???? public int intPageSize;
???? public int intPageCount;
???? public int intPage;
???? private String Countsql;
???? private String Pagisql;
???? private String str;
???? private String str_where;
???? private String str_parameter;
???? private String nowPage;
???? private String HttpFile;
???? Condata db;
???? public page()
???? {
???????? rs = null;
???????? rst = null;
???????? intCountTopic = 0;
???????? intPage = 0;
???????? Countsql = null;
???????? Pagisql = null;
???????? str = null;
???????? str_where = null;
???????? str_parameter = "";
???????? db = new Condata();
???? }
???? public static void main(String args[])
???? {
?????
???? }
???? public void setPages(int i)
???? {
???????? intPageSize = i;
???? }
???? public String getPagisql()
???? {
???????? return Pagisql;
???? }
???? public ResultSet setQuerysql(String s, String s1, String s2, String s3)
???????? throws SQLException
???? {
???????? ResultSet resultset = null;
???????? nowPage = s3;
???????? HttpFile = s2;
???????? Countsql = "select count(*) from " + s + " " + s1;
???????? Pagisql = "select * from " + s + " " + s1 + " order by id desc";
???????? try
???????? {
???????????? Condata _tmp = db;
???????????? Condata.getConnection();
???????? }
???????? catch(Exception exception)
???????? {
???????????? exception.getMessage();
???????? }
???????? try
???????? {
???????????? resultset = querySql(Countsql, Pagisql);
???????? }
???????? catch(SQLException sqlexception)
???????? {
???????????? sqlexception.getMessage();
???????? }
???????? return resultset;
???? }
???? public ResultSet querySql(String s, String s1)
???????? throws SQLException
???? {
???????? try
???????? {
???????????? Condata condata = db;
???????????? Condata.getConnection();
???????? }
???????? catch(Exception exception) { }
???????? if(nowPage == null)
???????? {
???????????? intPage = 1;
???????? } else
???????? {
???????????? intPage = Integer.parseInt(nowPage);
???????????? if(intPage < 1)
???????????????? intPage = 1;
???????? }
???????? rs = db.executeQuery(s);
???????? if(rs.next())
???????????? intCountTopic = rs.getInt(1);
???????? intPageCount = intCountTopic % intPageSize == 0 ? intCountTopic / intPageSize : intCountTopic / intPageSize + 1;
???????? if(intPage > intPageCount)
???????????? intPage = intPageCount;
???????? rs.close();
???????? rst = db.executeQuery(s1);
???????? return rst;
???? }
???? public int getCountTopic()
???? {
???????? return intCountTopic;
???? }
???? public int getPageCount()
???? {
???????? return intPageCount;
???? }
???? public int getIntPage()
???? {
???????? return intPage;
???? }
???? public String PageFooter()
???? {
???????? String s = "<form action=" + HttpFile + " name=form1 methord=post>";
???????? int i = intPage - 1;
???????? int j = intPage + 1;
???????? int k = (intPageSize * getIntPage() + 1) - intPageSize;
???????? if(k < 0)
???????????? k = 0;
???????? s = s + "<font style='font-size: 9pt'>\u603B\u8BA1<font color='red'>" + getCountTopic() + "</font>\u6761\u8BB0\u5F55," + "\u3010\u5171<font?? color='red'>" + getPageCount() + "</font>\u9875\u3011";
???????? s = s + "\u3010" + intPageSize + "\u6761/\u9875\u3011 \u5F53\u524D\u7B2C<font color='red'>" + getIntPage() + "</font>\u9875(\u5217\u51FA\u7B2C" + k + "\u5230\u7B2C" + getIntPage() * intPageSize + "\u6761) ";
???????? if(intPage > 1)
???????????? s = s + " <A href=" + HttpFile + "?pages=1" + str_parameter + ">\u9996\u9875</A> ";
???????? else
???????????? s = s + " \u9996\u9875 ";
???????? if(intPage > 1)
???????????? s = s + " <A href=" + HttpFile + "?pages=" + i + str_parameter + ">\u4E0A\u4E00\u9875</A> ";
???????? else
???????????? s = s + " \u4E0A\u4E00\u9875 ";
???????? if(intPage < intPageCount)
???????????? s = s + " <A href=" + HttpFile + "?pages=" + j + str_parameter + ">\u4E0B\u4E00\u9875</A> ";
???????? else
???????????? s = s + " \u4E0B\u4E00\u9875 ";
???????? if(intPageCount > 1 && intPage != intPageCount)
???????????? s = s + " <A href=" + HttpFile + "?pages=" + intPageCount + str_parameter + ">\u5C3E\u9875</A>";
???????? else
???????????? s = s + " \u5C3E\u9875</font>";
???????? s = s + "</form>";
???????? return s;
???? }
???? public void closeConn()
???? {
???????? db.close();
???? }
}
posted @
2007-10-02 21:32 jadmin 閱讀(62) |
評論 (0) |
編輯 收藏
============================JSP數據分頁顯示代碼(完整、高效)============================
<%@ page language="java" import="java.util.*,java.sql.*" %>
<%@ page contentType="text/html;charset=gb2312" %>
<jsp:useBean id="cn" scope="page" class="DBConnection.Conn" />
<%
//變量聲明
int intpagesize; //一頁顯示的記錄數
int introwcount; //記錄總數
int intpagecount; //總頁數
int intpage; //待顯示頁碼
//設置一頁顯示的記錄數
intpagesize = 20;
//設置當前網頁文件名
string strpageurl="show.jsp";
//取得待顯示頁碼
string strpage = request.getparameter("page");
if(strpage==null){
intpage = 1;
}
else{
//將字符串轉換成整型
intpage = java.lang.integer.parseint(strpage);
if(intpage<1) intpage = 1;
}
//獲取記錄總數
ResultSet rsc=cn.rsexecuteQuery("Select count(id) as AllRecord from tablename");
introwcount=rsc.getInt("AllRecord");
rsc.close();
//記算總頁數
intpagecount = (introwcount+intpagesize-1) / intpagesize;
if(intpage>intpagecount) intpage = intpagecount;
//取得記錄集
ResultSet rs=cn.rsexecuteQuery("select top "+intpagesize+" * from tablename where id not in (select top "+((intpage-1)
*intpagesize)+" id from tablename order by id desc) order by id desc");
while(rs.next) {
%>
********這里寫循環體*******
<%
}
//關閉結果集
rs.close();
%>
<%-- 下面為頁碼輸出代碼段 --%>
共<%=intpagecount%>頁 當前頁< %=intpage%>/<%=intpagecount%>
<%if(intpage>1){%><a href="<%=strpageurl%>&page=1">首頁</a><%}%> <a href="<%=strpageurl%>&page=<%=intpage-
1%>">上一頁</a>
<%if(intpage<intpagecount){%><a href="<%=strpageurl%>&page=<%=intpage+1%>">下一頁</a> <a href="<%=strpageurl%
>&page=<%=intpagecount%>">末頁</a><%}%>
============================jsp的分頁顯示代碼============================
<%@ page contentType="text/html;charset=gb2312" %>
<%@ page language="java" import="java.sql.*" %>
<script language="javascript">
function newwin(url) {
var
newwin=window.open(url,"newwin","toolbar=no,location=no,directories=no,status=no,
menubar=no,scrollbars=yes,resizable=yes,width=600,height=450");
newwin.focus();
return false;
}
</script>
<script LANGUAGE="javascript">
function submit10()
{
self.location.replace("fenye1.jsp")
}
</script>
<%//變量聲明
java.sql.Connection sqlCon; //數據庫連接對象
java.sql.Statement sqlStmt; //SQL語句對象
java.sql.ResultSet sqlRst; //結果集對象
java.lang.String strCon; //數據庫連接字符串
java.lang.String strSQL; //SQL語句
int intPageSize; //一頁顯示的記錄數
int intRowCount; //記錄總數
int intPageCount; //總頁數
int intPage; //待顯示頁碼
java.lang.String strPage;
int i;
//設置一頁顯示的記錄數
intPageSize = 4;
//取得待顯示頁碼
strPage = request.getParameter("page");
if(strPage==null){//表明在QueryString中沒有page這一個參數,此時顯示第一頁數據
intPage = 1;
}
else{//將字符串轉換成整型
intPage = java.lang.Integer.parseInt(strPage);
if(intPage<1) intPage = 1;
}
//裝載JDBC驅動程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//設置數據庫連接字符串
strCon = "jdbc:odbc:heyang";
//連接數據庫
sqlCon = java.sql.DriverManager.getConnection(strCon,"sa","");
//創建一個可以滾動的只讀的SQL語句對象
sqlStmt =
sqlCon.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,java.sql.Result
Set.CONCUR_READ_ONLY);//準備SQL語句
strSQL = "select user_id,user_name from userinfo order by user_id desc";
//執行SQL語句并獲取結果集
sqlRst = sqlStmt.executeQuery(strSQL);
//獲取記錄總數
sqlRst.last();//??光標在最后一行
intRowCount = sqlRst.getRow();//獲得當前行號
//記算總頁數
intPageCount = (intRowCount+intPageSize-1) / intPageSize;
//調整待顯示的頁碼
if(intPage>intPageCount) intPage = intPageCount;
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>會員管理</title>
</head>
<body>
<form method="POST" action="fenye1.jsp">
第<%=intPage%>頁 共<%=intPageCount%>頁
<%if(intPage<intPageCount){%><a
href="fenye1.jsp?page=<%=intPage+1%>">下一頁
</a><%}%> <%if(intPage>1){%><a href="fenye1.jsp?page=<%=intPage-1%>">
上一頁</a><%}%>
轉到第:<input type="text" name="page" size="8"> 頁
<span><input class=buttonface type=′submit′ value=′GO′ name=′cndok′></span>
</form>
<table border="1" cellspacing="0" cellpadding="0">
<tr>
<th>ID</th>
<th>用戶名</th>
<th width=′8%′>刪除</th>
</tr>
<%
if(intPageCount>0){
//將記錄指針定位到待顯示頁的第一條記錄上
sqlRst.absolute((intPage-1) * intPageSize + 1);
//顯示數據
i = 0;
String user_id,user_name;
while(i<intPageSize && !sqlRst.isAfterLast()){
user_id=sqlRst.getString(1);
user_name=sqlRst.getString(2);
%>
<tr>
<td><%=user_id%></td>
<td><%=user_name%></td>
<td width=′8%′ align=′center′><a href="delete.jsp?user_id=<%=user_id%>"
onClick="return newwin(this.href);">刪除</a></td>
</tr>
<%
sqlRst.next();
i++;
}
}
%>
</table>
</body>
</html>
<%
//關閉結果集
sqlRst.close();
//關閉SQL語句對象
sqlStmt.close();
//關閉數據庫
sqlCon.close();
%>
posted @
2007-10-02 20:49 jadmin 閱讀(62) |
評論 (0) |
編輯 收藏
前言
在使用數據庫的過程中,不可避免的需要使用到分頁的功能,可是JDBC的規范對此卻沒有很好的解決。對于這個需求很多朋友都有自己的解決方案,比如使用Vector等集合類先保存取出的數據再分頁。但這種方法的可用性很差,與JDBC本身的接口完全不同,對不同類型的字段的支持也不好。這里提供了一種與JDBC兼容性非常好的方案。
JDBC和分頁
Sun的JDBC規范的制定,有時很讓人哭笑不得,在JDBC1.0中,對于一個結果集(ResultSet)你甚至只能執行next()操作,而無法讓其向后滾動,這就直接導致在只執行一次SQL查詢的情況下無法獲得結果集的大小。所以,如果你使用的是JDBC1.0的驅動,那么是幾乎無法實現分頁的。
好在Sun的JDBC2規范中很好的彌補了這一個不足,增加了結果集的前后滾動操作,雖然仍然不能直接支持分頁,但我們已經可以在這個基礎上寫出自己的可支持分頁的ResultSet了。
和具體數據庫相關的實現方法
有一些數據庫,如Mysql, Oracle等有自己的分頁方法,比如Mysql可以使用limit子句,Oracle可以使用ROWNUM來限制結果集的大小和起始位置。這里以Mysql為例,其典型代碼如下:
// 計算總的記錄條數
String SQL = "SELECT Count(*) AS total " + this.QueryPart;
rs = db.executeQuery(SQL);
if (rs.next())
Total = rs.getInt(1);
// 設置當前頁數和總頁數
TPages = (int)Math.ceil((double)this.Total/this.MaxLine);
CPages = (int)Math.floor((double)Offset/this.MaxLine+1);
// 根據條件判斷,取出所需記錄
if (Total > 0) {
SQL = Query + " LIMIT " + Offset + " , " + MaxLine;
rs = db.executeQuery(SQL);
}
return rs;
}
毫無疑問,這段代碼在數據庫是Mysql時將會是漂亮的,但是作為一個通用的類(事實上我后面要提供的就是一個通用類庫中的一部分),需要適應不同的數據庫,而基于這個類(庫)的應用,也可能使用不同的數據庫,所以,我們將不使用這種方法。
另一種繁瑣的實現方法
我看過一些人的做法(事實上包括我在內,一開始也是使用這種方法的),即不使用任何封裝,在需要分頁的地方,直接操作ResultSet滾到相應的位置,再讀取相應數量的記錄。其典型代碼如下:
<%
sqlStmt = sqlCon.createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,
java.sql.ResultSet.CONCUR_READ_ONLY);
strSQL = "select name,age from test";
//執行SQL語句并獲取結果集
sqlRst = sqlStmt.executeQuery(strSQL);
//獲取記錄總數
sqlRst.last();
intRowCount = sqlRst.getRow();
//記算總頁數
intPageCount = (intRowCount+intPageSize-1) / intPageSize;
//調整待顯示的頁碼
if(intPage>intPageCount) intPage = intPageCount;
%>
<table border="1" cellspacing="0" cellpadding="0">
<tr>
<th>姓名</th>
<th>年齡</th>
</tr>
<%
if(intPageCount>0){
//將記錄指針定位到待顯示頁的第一條記錄上
sqlRst.absolute((intPage-1) * intPageSize + 1);
//顯示數據
i = 0;
while(i<intPageSize && !sqlRst.isAfterLast()){
%>
<tr>
<td><%=sqlRst.getString(1)%></td>
<td><%=sqlRst.getString(2)%></td>
</tr>
<%
sqlRst.next();
i++;
}
}
%>
</table>
很顯然,這種方法沒有考慮到代碼重用的問題,不僅代碼數量巨大,而且在代碼需要修改的情況下,將會無所適從。
使用Vector進行分頁
還見過另一些實現分頁的類,是先將所有記錄都select出來,然后將ResultSet中的數據都get出來,存入Vector等集合類中,再根據所需分頁的大小,頁數,定位到相應的位置,讀取數據。或者先使用前面提到的兩種分頁方法,取得所需的頁面之后,再存入Vector中。
扔開代碼的效率不說,單是從程序結構和使用的方便性上講,就是很糟糕的。比如,這種做法支持的字段類型有限,int, double, String類型還比較好處理,如果碰到Blob, Text等類型,實現起來就很麻煩了。這是一種更不可取的方案。
一個新的Pageable接口及其實現
很顯然,看過上面三種實現方法后,我們對新的分頁機制有了一個目標,即:不與具體數據庫相關;盡可能做到代碼重用;盡可能與原JDBC接口的使用方法保持一致;盡可能高的效率。
首先,我們需要提供一個與java.sql.ResultSet向下兼容的接口,把它命名為Pageable,接口定義如下:
public interface Pageable extends java.sql.ResultSet{
/**返回總頁數
*/
int getPageCount();
/**返回當前頁的記錄條數
*/
int getPageRowsCount();
/**返回分頁大小
*/
int getPageSize();
/**轉到指定頁
*/
void gotoPage(int page) ;
/**設置分頁大小
*/
void setPageSize(int pageSize);
/**返回總記錄行數
*/
int getRowsCount();
/**
* 轉到當前頁的第一條記錄
* @exception java.sql.SQLException 異常說明。
*/
void pageFirst() throws java.sql.SQLException;
/**
* 轉到當前頁的最后一條記錄
* @exception java.sql.SQLException 異常說明。
*/
void pageLast() throws java.sql.SQLException;
/**返回當前頁號
*/
int getCurPage();
}
這是一個對java.sql.ResultSet進行了擴展的接口,主要是增加了對分頁的支持,如設置分頁大小,跳轉到某一頁,返回總頁數等等。
接著,我們需要實現這個接口,由于這個接口繼承自ResultSet,并且它的大部分功能也都和ResultSet原有功能相同,所以這里使用了一個簡單的Decorator模式。
PageableResultSet2的類聲明和成員聲明如下:
public class PageableResultSet2 implements Pageable {
protected java.sql.ResultSet rs=null;
protected int rowsCount;
protected int pageSize;
protected int curPage;
protected String command = "";
}
可以看到,在PageableResultSet2中,包含了一個ResultSet的實例(這個實例只是實現了ResultSet接口,事實上它是由各個數據庫廠商分別實現的),并且把所有由ResultSet繼承來的方法都直接轉發給該實例來處理。
PageableResultSet2中繼承自ResultSet的主要方法:
//……
public boolean next() throws SQLException {
return rs.next();
}
//……
public String getString(String columnName) throws SQLException {
try {
return rs.getString(columnName);
}
catch (SQLException e) {//這里是為了增加一些出錯信息的內容便于調試
throw new SQLException (e.toString()+" columnName="
+columnName+" SQL="+this.getCommand());
}
}
//……
只有在Pageable接口中新增的方法才需要自己的寫方法處理。
/**方法注釋可參考Pageable.java
*/
public int getCurPage() {
return curPage;
}
public int getPageCount() {
if(rowsCount==0) return 0;
if(pageSize==0) return 1;
//calculate PageCount
double tmpD=(double)rowsCount/pageSize;
int tmpI=(int)tmpD;
if(tmpD>tmpI) tmpI++;
return tmpI;
}
public int getPageRowsCount() {
if(pageSize==0) return rowsCount;
if(getRowsCount()==0) return 0;
if(curPage!=getPageCount()) return pageSize;
return rowsCount-(getPageCount()-1)*pageSize;
}
public int getPageSize() {
return pageSize;
}
public int getRowsCount() {
return rowsCount;
}
public void gotoPage(int page) {
if (rs == null)
return;
if (page < 1)
page = 1;
if (page > getPageCount())
page = getPageCount();
int row = (page - 1) * pageSize + 1;
try {
rs.absolute(row);
curPage = page;
}
catch (java.sql.SQLException e) {
}
}
public void pageFirst() throws java.sql.SQLException {
int row=(curPage-1)*pageSize+1;
rs.absolute(row);
}
public void pageLast() throws java.sql.SQLException {
int row=(curPage-1)*pageSize+getPageRowsCount();
rs.absolute(row);
}
public void setPageSize(int pageSize) {
if(pageSize>=0){
this.pageSize=pageSize;
curPage=1;
}
}
PageableResultSet2的構造方法:
public PageableResultSet2(java.sql.ResultSet rs) throws java.sql.SQLException {
if(rs==null) throw new SQLException("given ResultSet is NULL","user");
rs.last();
rowsCount=rs.getRow();
rs.beforeFirst();
this.rs=rs;
}
這里只是簡單的取得一個總記錄數,并將記錄游標移回初始位置(before first),同時將參數中的ResultSet賦給成員變量。
Pageable的使用方法
因為Pageable接口繼承自ResultSet,所以在使用方法上與ResultSet一致,尤其是在不需要分頁功能的時候,可以直接當成ResultSet使用。而在需要分頁時,只需要簡單的setPageSize, gotoPage,即可。
PreparedStatement pstmt=null;
Pageable rs=null;
……//構造SQL,并準備一個pstmt.
rs=new PageableResultSet2(pstmt.executeQuery());//構造一個Pageable
rs.setPageSize(20);//每頁20個記錄
rs.gotoPage(2);//跳轉到第2頁
for(int i=0; i<rs.getPageRowsCount(); i++){//循環處理
int id=rs.getInt(“ID”);
……//繼續處理
}
總結
一個好的基礎類應該是便于使用,并且具備足夠的可移植性,同時要保證其功能的完善。在上面的實現中,我們從java.sql.ResultSet接口繼承出Pageable,并實現了它。這就保證了在使用中與JDBC原有操作的一致性,同時對原有功能沒有縮減。
同時它也是易于使用的,因為封裝了一切必要的操作,所以在你的代碼中唯一顯得"難看"和"不舒服"的地方就是需要自己去構造一個PageableResultSet2。不過只要你愿意,這也是可以解決的。
當然它也有具有充分的可移植性,當你將數據庫由Oracle變為Mysql或者SQLServer的時候,你仍然可以使用這些分頁的代碼。它在使用中(或者說在移植的過程中)唯一的限制就是你必須要使用一個支持JDBC2的驅動(現在明白為什么我把類命名為PageableResultSet2了吧。:P),不過,好在JDBC2已經成為標準了,絕大多數的數據庫(如Oracle, Mysql, SQLServer)都有自己的或者第三方提供的JDBC2的驅動。
OK,這個分頁的實現是否對你的編程有幫助呢?仔細看看,其實真正自己寫的代碼并不多的,大部分都只是簡單的轉發操作。一個合適的模式應用可以幫你很大忙。
posted @
2007-10-02 20:37 jadmin 閱讀(50) |
評論 (0) |
編輯 收藏
??????????????????? 1、不說“不可能”三個字;
??????????????????? 2、凡事第一反應:找方法,而不是找借口;
??????????????????? 3、遇到挫折對自己大聲說:太棒了;
??????????????????? 4、不說消極的話,不落入消極情緒,一旦出現立即正面處理;
??????????????????? 5、凡事先訂立目標,并且盡量制作“夢想版”;
??????????????????? 6、凡事預先作計劃,盡量前目標視覺化;
??????????????????? 7、六點優先工作制,每一分,每一秒做生產力的事情;
??????????????????? 8、隨時用零碎的時間(如等人、排隊等)做零碎的小活;
??????????????????? 9、守時;
??????????????????? 10、寫下來,不要太依靠腦袋記憶;
??????????????????? 11、隨時記錄靈感;
??????????????????? 12、把重要的觀念、方法寫下來,并貼起來,以隨時提示自己;
??????????????????? 13、走路比平時快30%。走路時,腳尖稍用力推進;肢體語言健康有力,不懶散;
??????????????????? 14、每天出門照鏡子,給自己一個自信的笑容;
??????????????????? 15、每天自我反省一次;
??????????????????? 16、每天堅持一次運動;
??????????????????? 17、聽心跳1分鐘。指在做重要事前,疲勞時,心情煩燥時,緊張時;
??????????????????? 18、開會坐在前排;
??????????????????? 19、微笑;
??????????????????? 20、用心傾聽,不打斷對方說話;
??????????????????? 21、說話時,聲音有力。感覺自己聲音似乎能產生有感染力的磁場;
??????????????????? 22、同理心。說話之前,先考慮一下對方的感覺;
??????????????????? 23、每天有意識、真誠地贊美別人三次以上;
??????????????????? 24、及時寫感謝卡,哪怕是用便條寫;
??????????????????? 25、不用訓斥、指責的口吻跟別人說話;
??????????????????? 26、控制住不要讓自己做出為自己辯護的第一反應;
??????????????????? 27、每天多做一件“分外事”
??????????????????? 28、不管任何方面,每天必須至少做一次“進步一點點”;
??????????????????? 29、每天提前15分鐘上班,推遲30分鐘下班;
??????????????????? 30、每天在下班前5分鐘的時間做一天的整理性工作;
??????????????????? 31、定期存錢;
??????????????????? 32、節儉;
??????????????????? 33,當你有創意的時候用筆記下來,并努力去實現它。
posted @
2007-10-02 08:55 jadmin 閱讀(57) |
評論 (0) |
編輯 收藏
【放棄】把握的反面就是放棄,選擇了一個機會,就等于放棄了其他所有的可能。當新的機會擺在面前的時候,敢于放棄已經獲得的一切,這不是功虧一簣,這不是半途而廢,這是為了謀求更大的發展空間;或者什么都不為,只因為喜歡這樣做,因為,年輕就是最大的機會。人,只有在三十歲之前才會有這個膽量,有這個資本,有這個資格。
【失戀】不是不在乎,是在乎不起。三十歲前最怕失去的不是已經擁有的東西,而是夢想。愛情如果只是一個過程,那么正是這個年齡應當經歷的,如果要承但結果,三十歲以后,可能會更有能力,更有資格。其實,三十歲之前我們要做的事情很多,稍縱即逝,過久地沉溺在已經干涸的愛河的河床中,與這個年齡的生命節奏不合。
【離婚】不是不在乎,是一切還來得及。一位三十八歲的女友與老公結婚十五年,冷戰十三年,終于分手。她說:“如果說后來不愿意離婚是為了孩子,那第他第一次提出離婚我沒有同意,現在想來真不知道為什么。如果那個時候早分手,我的生活絕不會是今天這個樣子。現在再重新開始,總覺得一切都晚了。”
【漂泊】漂泊不是一種不幸,而是一種資格。趁著沒有家室拖累,趁著身體健康,此時不飄何時飄?當然,漂泊的不一定是身體,也許只是幻想和夢境。新世紀的時尚領袖是飄一代,渴望漂泊的人惟一不飄的是那顆心。
【失業】三十歲以前就嘗到失業的滋味當然是一件不幸的事,但不一定是壞事。三十歲之前就過早地固定在一個職業上終此一生也許才是最大的不幸。失業也許讓你想起埋藏很久而塵封的夢想,也許會喚醒連你自己都從未知道的潛能。也許你本來就沒什么夢想,這時候也會逼著你去做夢。
【時尚】不要追趕時尚。按說青年人應該是最時尚的,但是獨立思考和個性生活更重要。在這個物質社會,其實對時尚的追求早已經成為對金錢的追求。今天,時尚是物欲和世俗的同義語。
【格調】這是小資的東西,"小資"這個詞在今天又二度流行,追求格調就是他們的專利。小資們說,有格調要滿足四大要件:智慧、素養、自信和金錢。格調就是把"高尚"理解成穿著、氣質、愛好的品位和室內裝潢。也就是大老粗只會表現談吐的庸俗,"小資"們已經有能力庸俗他們的心靈了。主流觀念倒不是非要另類,另類已經成為年輕人觀念的主流了,在今天,老土倒顯得另類。關鍵是當今社會是一個創造觀念的時代,而不是一個固守陳舊觀念的時代。
???? 【評價】我們最不應該做出的犧牲就是因為別人的評價而改變自我,因為那些對你指手畫腳的人自己也不知道他們遵從的規則是什么。千萬不要只遵從規矩做事,規矩還在創造之中,要根據自己的判斷做每一件事,雖然這樣會麻煩一點。
【幼稚】不要怕人說我們幼稚,這正說明你還年輕,還充滿活力。"成熟"是個嚇人的詞兒,也是個害人的詞兒。成熟和幼稚是對一個人最大而無當、最不負責任、最沒用的概括。那些庸人,絕不會有人說他們幼稚。不信,到哪天你被生活壓得老氣橫秋,暮氣沉沉的時候,人們一定會說你成熟了,你就會知道"成熟"是個什么東西。
【不適應】在一首搖滾里有這么一句:"這個城市改變了我,這個城市不需要我。"不要盲目地適應你生存的環境,因為很可能這環境自身已經不適應這個社會的發展了。
【失敗】我的老師曾經跟我說,一個人起碼要在感情上失戀一次,在事業上失敗一次,在選擇上失誤一次,才能長大。不要說失敗是成功之母那樣的老話,失敗來得越早越好,要是三十歲,四十歲之后再經歷失敗,有些事,很可能就來不及了。
【錯誤】這是年輕人的專利。
【淺薄】如果每看一次《泰坦尼克號》就流一次眼淚,每看一次《大話西游》就笑得直不起腰,就會有人笑你淺薄。其實那只能說明你的神經依舊非常敏銳,對哪怕非常微弱的刺激都會迅速做出適應的反應;等你的感覺遲鈍了,人們就會說你深沉了。
【明星】不是不必在乎,是不能在乎。明星在商品社會是一種消費品,花了錢,聽了歌,看了電影,明星們的表現再好,不過是物超所值而己,也不值得崇拜呀?就像你在地攤上花五十塊錢買的裙子,別人都猜是八百塊錢買的,物超所值了吧?你就崇拜上這身裙子了?
【代價】不是不計代價,而是要明白做任何事都要付出代價。對我們這個年齡的人來說,這絕不是一句廢話。否則,要到三十歲的時候才會明白自己曾經付出了多少代價,卻不明白為什么付出,更不明白自己得到了多少,得到什么。
【孤獨】這是為自由付出的代價。
【失意】包括感情上的,事業上的,也許僅僅是今天花了冤枉錢沒買到可心的東西,朋友家高朋滿座自己卻插不上一句話。過分在乎失意的感受不是拿命運的捉弄來捉弄自己,就是拿別人的錯誤來懲罰自己。
【缺陷】也許你個子矮,也許你長得不好看,也許你的嗓音像唐老鴨……那么你的優勢就是你不會被自己表面的淺薄的亮點所耽擱,少花一些時間,少走一些彎,直接發現你內在的優勢,直接挖掘自己深層的潛能。
???? 【誤會】如果出于惡意,那么解釋也沒有用;如果出于善意,就不需要解釋。專門說到"誤會"倒不是為一個人在三十歲之前被人誤會的時候更多,而是這個年齡的人想不開的時候更多。
【謠言】這是一種傳染病,沉默是最好的疫苗。除非你能找出傳染源,否則解釋恰恰會成為病毒傳播最理想的條件。
【瘋狂】這是年輕人最好的心理調適,只能說明你精力旺盛,身心健康。說你"瘋狂"是某些生活壓抑、心力交瘁的中老年人惡意的評價,他們就像一部年久修的機器,最需要調試,但只能微調,一次大修就會讓他們完全報廢。
【穩定】三十歲之前就在乎穩定的生活,那只有兩種可能,要么就是中了彩票,要么就是未老先衰。
【壓力】中年人能夠承受多大壓力檢驗的是他的韌性;年輕人能承受多大壓力,煥發的是他的潛能。
【出國】也許是個機會,也許是個陷阱。除非從考大學的那一刻你就抱著這個目標,否則,對待出國的態度應該像對待愛情一樣,努力爭取成敗隨緣。
【薪水】只要是給人打工,薪水再高也高不到哪兒去。所以在三十歲之前,機會遠比金錢重要,事業遠比金錢重要,將來遠比金錢重要。對大多數人來說,三十歲之前干事業的首要目標絕不是掙錢,而是掙未來。
【存款】這倒不一定是因為我們錢少,年輕人現在誰都知道錢是有生命的。機會這么多,條件這么好,可以拿錢去按揭,做今天的事,花明天的錢;也可以拿錢去投資,拿錢去"充電"。錢只有在它流通的過程中才是錢,否則只是一沓世界上質量最好的廢紙。
【房子】除非你買房子是為了升值,要么就是你結婚了。我有個同學,家在外地,大學畢業之后,單位沒有宿舍,家里就給他買了一套房子。他曾經有過去北京工作的機會,但是他覺得剛買了房子就離開這座城市說不過去,就放棄了。到現在他工作穩定,但一事無成。唯一的成就就是結婚了,并且有了孩子,因為他覺得該讓這房子永遠空著,所以房子變成了家。房子是都市生活的寓言,這個寓言不應該過早的和我們相關。
【年齡】女孩子一過二十五就開始隱瞞自己的年齡,其實大可不必。現在青年期都延遲到四十五歲了,二十五又算得了什么呢?
【在乎】這是一種拿不起、放不下的心態,它的反面不是放棄,而是天馬行空,自由自在,永遠保持革命樂觀主義的精神。
posted @
2007-10-02 08:51 jadmin 閱讀(57) |
評論 (0) |
編輯 收藏
在基于 Java 語言的編程中,我們經常碰到漢字的處理及顯示的問題。一大堆看不懂的亂碼肯定不是我們愿意看到的顯示效果,怎樣才能夠讓那些漢字正確顯示呢?Java語言默認的編碼方式是UNICODE,而我們中國人通常使用的文件和數據庫都是基于GB2312或者BIG5等方式編碼的,怎樣才能夠恰當地選擇漢字編碼方式并正確地處理漢字的編碼呢?本文將從漢字編碼的常識入手,結合Java編程實例,分析以上兩個問題并提出解決它們的方案。
現在 Java 編程語言已經廣泛應用于互聯網世界,早在 Sun 公司開發 Java 語言的時候,就已經考慮到對非英文字符的支持了。Sun 公司公布的 Java 運行環境(JRE)本身就分英文版和國際版,但只有國際版才支持非英文字符。不過在 Java 編程語言的應用中,對中文字符的支持并非如同 Java Soft 的標準規范中所宣稱的那樣完美,因為中文字符集不只一個,而且不同的操作系統對中文字符的支持也不盡相同,所以會有許多和漢字編碼處理有關的問題在我們進行應用開發中困擾著我們。有很多關于這些問題的解答,但都比較瑣碎,并不能夠滿足大家迫切解決問題的愿望,關于 Java 中文問題的系統研究并不多,本文從漢字編碼常識出發,分析 Java 中文問題,希望對大家解決這個問題有所幫助。
漢字編碼的常識
我們知道,英文字符一般是以一個字節來表示的,最常用的編碼方法是 ASCII 。但一個字節最多只能區分256個字符,而漢字成千上萬,所以現在都以雙字節來表示漢字,為了能夠與英文字符分開,每個字節的最高位一定為1,這樣雙字節最多可以表示64K格字符。我們經常碰到的編碼方式有 GB2312、BIG5、UNICODE 等。關于具體編碼方式的詳細資料,有興趣的讀者可以查閱相關資料。我膚淺談一下和我們關系密切的 GB2312 和 UNICODE。GB2312 碼,中華人民共和國國家標準漢字信息交換用編碼,是一個由中華人民共和國國家標準總局發布的關于簡化漢字的編碼,通行于中國大陸地區及新加坡,簡稱國標碼。兩個字節中,第一個字節(高字節)的值為區號值加32(20H),第二個字節(低字節)的值為位號值加32(20H),用這兩個值來表示一個漢字的編碼。UNICODE 碼是微軟提出的解決多國字符問題的多字節等長編碼,它對英文字符采取前面加“0”字節的策略實現等長兼容。如 “A” 的 ASCII 碼為0x41,UNICODE 就為0x00,0x41。利用特殊的工具各種編碼之間可以互相轉換。
Java 中文問題的初步認識
我們基于 Java 編程語言進行應用開發時,不可避免地要處理中文。Java 編程語言默認的編碼方式是 UNICODE,而我們通常使用的數據庫及文件都是基于 GB2312 編碼的,我們經常碰到這樣的情況:瀏覽基于 JSP 技術的網站看到的是亂碼,文件打開后看到的也是亂碼,被 Java 修改過的數據庫的內容在別的場合應用時無法繼續正確地提供信息。
String sEnglish = “apple”;
String sChinese = “蘋果”;
String s = “蘋果 apple ”;
sEnglish 的長度是5,sChinese的長度是4,而 s 默認的長度是14。對于 sEnglish來說, Java 中的各個類都支持得非常好,肯定能夠正確顯示。但對于 sChinese 和 s 來說,雖然 Java Soft 聲明 Java 的基本類已經考慮到對多國字符的支持(默認 UNICODE 編碼),但是如果操作系統的默認編碼不是 UNICODE ,而是國標碼等。從 Java 源代碼到得到正確的結果,要經過 “Java 源代碼-> Java 字節碼-> ; 虛擬機->操作系統->顯示設備”的過程。在上述過程中的每一步驟,我們都必須正確地處理漢字的編碼,才能夠使最終的顯示結果正確。
“ Java 源代碼-> Java 字節碼”,標準的 Java 編譯器 javac 使用的字符集是系統默認的字符集,比如在中文 Windows 操作系統上就是 GBK ,而在 Linux 操作系統上就是ISO-8859-1,所以大家會發現在 Linux 操作系統上編譯的類中源文件中的中文字符都出了問題,解決的辦法就是在編譯的時候添加 encoding 參數,這樣才能夠與平臺無關。用法是
javac ?Cencoding GBK。
“ Java 字節碼->虛擬機->操作系統”, Java 運行環境 (JRE) 分英文版和國際版,但只有國際版才支持非英文字符。 Java 開發工具包 (JDK) 肯定支持多國字符,但并非所有的計算機用戶都安裝了 JDK 。很多操作系統及應用軟件為了能夠更好的支持 Java ,都內嵌了 JRE 的國際版本,為自己支持多國字符提供了方便。
“操作系統->顯示設備”,對于漢字來說,操作系統必須支持并能夠顯示它。英文操作系統如果不搭配特殊的應用軟件的話,是肯定不能夠顯示中文的。
還有一個問題,就是在 Java 編程過程中,對中文字符進行正確的編碼轉換。例如,向網頁輸出中文字符串的時候,不論你是用
out.println(string);
還是用<%=string%>,都必須作 UNICODE 到 GBK 的轉換,或者手動,或者自動。在 JSP 1.0中,可以定義輸出字符集,從而實現內碼的自動轉換。用法是
<%@page contentType=”text/html; charset=gb2312” %>
但是在一些 JSP 版本中并沒有提供對輸出字符集的支持,(例如 JSP 0.92),這就需要手動編碼輸出了,方法非常多。最常用的方法是
String s1 = request.getParameter(“keyword”);
String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);
getBytes 方法用于將中文字符以“ISO-8859-1”編碼方式轉化成字節數組,而“GBK” 是目標編碼方式。我們從以ISO-8859-1方式編碼的數據庫中讀出中文字符串 s1 ,經過上述轉換過程,在支持 GBK 字符集的操作系統和應用軟件中就能夠正確顯示中文字符串 s2 。
Java 中文問題的表層分析及處理
背景
開發環境 JDK1.15 Vcafe2.0 JPadPro
服務器端 NT IIS Sybase System Jconnect(JDBC)
客戶端 IE5.0 Pwin98
.CLASS 文件存放在服務器端,由客戶端的瀏覽器運行 APPLET , APPLET 只起調入 FRAME 類等主程序的作用。界面包括 Textfield ,TextArea,List,Choice 等。
I.用 JDBC 執行 SELECT 語句從服務器端讀取數據(中文)后,將數據用 APPEND 方法加到 TextArea(TA) ,不能正確顯示。但加到 List 中時,大部分漢字卻可正確顯示。
將數據按“ISO-8859-1” 編碼方式轉化為字節數組,再按系統缺省編碼方式 (Default Character Encoding) 轉化為 STRING ,即可在 TA 和 List 中正確顯示。
程序段如下:
dbstr2 = results.getString(1);
//After reading the result from DB server,converting it to string.
dbbyte1 = dbstr2.getBytes(“iso-8859-1”);
dbstr1 = new String(dbbyte1);
在轉換字符串時不采用系統默認編碼方式,而直接采用“ GBK” 或者 “GB2312” ,在 A 和 B 兩種情況下,從數據庫取數據都沒有問題。
II.處理方式與“取中文”相逆,先將 SQL 語句按系統缺省編碼方式轉化為字節數組,再按“ISO-8859-1”編碼方式轉化為 STRING ,最后送去執行,則中文信息可正確寫入數據庫。
程序段如下:
sqlstmt = tf_input.getText();
//Before sending statement to DB server,converting it to sql statement.
dbbyte1 = sqlstmt.getBytes();
sqlstmt = newString(dbbyte1,”iso-8859-1”);
_stmt = _con.createStatement();
_stmt.executeUpdate(sqlstmt);
……
問題:如果客戶機上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 時(稱為 A 情況),上述程序代碼可正確執行。但是如果客戶機只有瀏覽器,而沒有 JDK 和 CLASSPATH 時(稱為 B 情況),則漢字無法正確轉換。
我們的分析:
1.經過測試,在 A 情況下,程序運行時系統的缺省編碼方式為 GBK 或者 GB2312 。在 B 情況下,程序啟動時瀏覽器的 JAVA 控制臺中出現如下錯誤信息:
Can't find resource for sun.awt.windows.awtLocalization_zh_CN
然后系統的缺省編碼方式為“8859-1”。
2.如果在轉換字符串時不采用系統缺省編碼方式,而是直接采用 “GBK” 或“GB2312”,則在 A 情況下程序仍然可正常運行,在 B 情況下,系統出現錯誤:
UnsupportedEncodingException。
3.在客戶機上,把 JDK 的 CLASSES.ZIP 解壓后,放在另一個目錄中, CLASSPATH 只包含該目錄。然后一邊逐步刪除該目錄中的 .CLASS 文件,另一邊運行測試程序,最后發現在一千多個 CLASS 文件中,只有一個是必不可少的,該文件是:
sun.io.CharToByteDoubleByte.class。
將該文件拷到服務器端和其它的類放在一起,并在程序的開頭 IMPORT 它,在 B 情況下程序仍然無法正常運行。
4.在 A 情況下,如果在 CLASSPTH 中去掉 sun.io.CharToByteDoubleByte.class ,則程序運行時測得默認編碼方式為“8859-1”,否則為 “GBK” 或 “GB2312” 。
如果 JDK 的版本為1.2以上的話,在 B 情況下遇到的問題得到了很好的解決,測試的步驟同上,有興趣的讀者可以嘗試一下。
Java 中文問題的根源分析及解決
在簡體中文 MS Windows 98 + JDK 1.3 下,可以用 System.getProperties() 得到 Java 運行環境的一些基本屬性,類 PoorChinese 可以幫助我們得到這些屬性。
類 PoorChinese 的源代碼:
public class PoorChinese {}
執行 java PoorChinese 后,我們會得到:
系統變量 file.encoding 的值為 GBK ,user.language 的值為 zh , user.region 的值為 CN ,這些系統變量的值決定了系統默認的編碼方式是 GBK 。
在上述系統中,下面的代碼將 GB2312 文件轉換成 Big5 文件,它們能夠幫助我們理解 Java 中漢字編碼的轉化:
import java.io.*;
import java.util.*;
public class gb2big5
{
static int iCharNum=0;
public static void main(String[] args) {
System.out.println("Input GB2312 file, output Big5 file.");
if (args.length!=2)
{
System.err.println("Usage: jview gb2big5 gbfile big5file");
System.exit(1);
String inputString = readInput(args[0]);
writeOutput(inputString,args[1]);
System.out.println("Number of Characters in file: "+iCharNum+".");
}
static void writeOutput(String str, String strOutFile)
{
try
{
FileOutputStream fos = new FileOutputStream(strOutFile);
Writer out = new OutputStreamWriter(fos, "Big5");
out.write(str);
out.close();
}
catch (IOException e)
{
e.printStackTrace();
e.printStackTrace();
}
}
static String readInput(String strInFile)
{
StringBuffer buffer = new StringBuffer();
try
{
FileInputStream fis = new FileInputStream(strInFile);
InputStreamReader isr = new InputStreamReader(fis, "GB2312");
Reader in = new BufferedReader(isr);
int ch;
while ((ch = in.read()) > -1)
{
iCharNum += 1; buffer.append((char)ch);
}
in.close();
return buffer.toString();
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
編碼轉化的過程如下:
GB2312------------------>Unicode------------->Big5
執行 java gb2big5 gb.txt big5.txt ,如果 gb.txt 的內容是“今天星期三”,則得到的文件 big5.txt 中的字符能夠正確顯示;而如果 gb.txt 的內容是“情人節快樂”,則得到的文件 big5.txt 中對應于“節”和“樂”的字符都是符號“?”(0x3F),可見 sun.io.ByteToCharGB2312 和 sun.io.CharToByteBig5 這兩個基本類并沒有編好。
正如上例一樣, Java 的基本類也可能存在問題。由于國際化的工作并不是在國內完成的,所以在這些基本類發布之前,沒有經過嚴格的測試,所以對中文字符的支持并不像 Java Soft 所聲稱的那樣完美。前不久,我的一位技術上的朋友發信給我說,他終于找到了 Java Servlet 中文問題的根源。兩周以來,他一直為 Java Servlet 的中文問題所困擾,因為每面對一個含有中文字符的字符串都必須進行強制轉換才能夠得到正確的結果(這好象是大家公認的唯一的解決辦法)。
后來,他確實不想如此繼續安分下去了,因為這樣的事情確實不應該是高級程序員所要做的工作,他就找出 Servlet 解碼的源代碼進行分析,因為他懷疑問題就出在解碼這部分。經過四個小時的奮斗,他終于找到了問題的根源所在。原來他的懷疑是正確的, Servlet 的解碼部分完全沒有考慮雙字節,直接把 %XX 當作一個字符。(原來 Java Soft 也會犯這幺低級的錯誤!)
如果你對這個問題有興趣或者遇到了同樣的煩惱的話,你可以按照他的步驟 對Servlet.jar 進行修改:
找到源代碼 HttpUtils 中的 static private String parseName ,在返回前將 sb(StringBuffer) 復制成 byte bs[] ,然后 return new String(bs,”GB2312”)。作上述修改后就需要自己解碼了:
HashTable form=HttpUtils .parseQueryString(request.getQueryString())或者
form=HttpUtils.parsePostData(……)
千萬別忘了編譯后放到 Servlet.jar 里面。
關于 Java 中文問題的總結
Java 編程語言成長于網絡世界,這就要求 Java 對多國字符有很好的支持。 Java 編程語言適應了計算的網絡化的需求,為它能夠在網絡世界迅速成長奠定了堅實的基礎。 Java 的締造者 (Java Soft) 已經考慮到 Java 編程語言對多國字符的支持,只是現在的解決方案有很多缺陷在里面,需要我們付諸一些補償性的措施。而世界標準化組織也在努力把人類所有的文字統一在一種編碼之中,其中一種方案是 ISO10646 ,它用四個字節來表示一個字符。當然,在這種方案未被采用之前,還是希望 Java Soft 能夠嚴格地測試它的產品,為用戶帶來更多的方便。
附一個用于從數據庫和網絡中取出 中文亂碼的處理函數,入參是有問題的字符串,出參是問題已經解決了的字符串。
posted @
2007-10-02 08:17 jadmin 閱讀(66) |
評論 (0) |
編輯 收藏