星期四, 六月 07, 2007
java实现FTP功能
下边是从CSDN转的:
---- 在JAVA的编程中,您也许会遇到FTP方面的编程,本文就来演示如何实现它。
---- 本程序是由JBUILDER2.0来开发的,为了节约篇幅我只列出主要的三个部份。FtpList 部分是用来显示FTP服务器上的文件(附图略)。GetButton部分为从FTP服务器下传一个文件。PutButton 部分为向FTP服务器上传一个文件。别忘了在程序中还要引入两个库文件(import sun.net.*,import sun.net.ftp.*)。以下是这三部分的JAVA源程序。
---- 1)显示FTP服务器上的文件
void ftpList_actionPerformed(ActionEvent e) {
String server=serverEdit.getText();
//输入的FTP服务器的IP地址
String user=userEdit.getText ();
//登录FTP服务器的用户名
String password=passwordEdit.getText();
//登录FTP服务器的用户名的口令
String path=pathEdit.getText();
//FTP服务器上的路径
try {
FtpClient ftpClient=new FtpClient();
//创建FtpClient对象
ftpClient.openServer (server);
//连接FTP服务器
ftpClient.login(user, password);
//登录FTP服务器
if (path.length()!=0) ftpClient.cd(path);
TelnetInputStream is=ftpClient.list();
int c;
while ((c=is.read())!=-1) {
System.out.print ((char) c);}
is.close();
ftpClient.closeServer();//退出FTP服务器
} catch (IOException ex) {;}
}
2)从FTP服务器上下传一个文件
void getButton_actionPerformed(ActionEvent e) {
String server=serverEdit.getText ();
String user=userEdit.getText();
String password=passwordEdit.getText();
String path=pathEdit.getText();
String filename=filenameEdit.getText();
try {
FtpClient ftpClient=new FtpClient();
ftpClient.openServer (server);
ftpClient.login(user, password);
if (path.length()!=0) ftpClient.cd(path);
ftpClient.binary();
TelnetInputStream is=ftpClient.get(filename);
File file_out=new File(filename);
FileOutputStream os=new
FileOutputStream(file_out);
byte[] bytes=new byte[1024];
int c;
while ((c=is.read(bytes))!=-1) {
os.write(bytes,0,c);
}
is.close();
os.close();
ftpClient.closeServer();
} catch (IOException ex) {;}
}
3)向FTP服务器上上传一个文件
void putButton_actionPerformed(ActionEvent e) {
String server=serverEdit.getText();
String user=userEdit.getText();
String password=passwordEdit.getText();
String path= pathEdit.getText();
String filename=filenameEdit.getText();
try {
FtpClient ftpClient=new FtpClient();
ftpClient.openServer(server);
ftpClient.login(user, password);
if (path.length()!=0) ftpClient.cd(path);
ftpClient.binary();
TelnetOutputStream os=ftpClient.put(filename);
File file_in=new File(filename);
FileInputStream is=new FileInputStream(file_in);
byte[] bytes=new byte[1024];
int c;
while ((c=is.read (bytes))!=-1){
os.write(bytes,0,c);}
is.close();
os.close();
ftpClient.closeServer();
} catch (IOException ex) {;}
}
}
原文地址: http://dev.csdn.net/author/Jason009/a20da6acb30441f6886c03adbb5996c4.html
星期五, 六月 01, 2007
db2 sample address
- sqllib/samples/java
- すべてのサブディレクトリー内の Java サンプル・プログラムの README ファイルが入っています。
- sqllib/samples/java/jdbc
- JDBC サンプル・プログラム・ファイルが入っています。
- sqllib/samples/java/sqlj
- SQLJ サンプル・プログラムが入っています。
- sqllib/samples/xml/java
- JDBC および SQLJ XML サンプルのサブディレクトリーが入っています。
- sqllib/samples/xml/java/jdbc
- README ファイルと JDBC XML サンプル・プログラムが入っています。
- sqllib/samples/xml/java/sqlj
- README ファイルと SQLJ XML サンプル・プログラムが入っています。
- sqllib/samples/java/Websphere
- WebSphere サンプル・プログラムが入っています。
- sqllib/samples/java/plugin
- DB2 コントロール・センターのプラグイン例のファイルが入っています。
- sqllib/samples/java/plugin/doc
- プラグイン・インターフェース用の javadoc ファイルが入っています。
- sqllib¥samples¥java
- すべてのサブディレクトリー内の Java サンプル・プログラムの README ファイルが入っています。
- sqllib¥samples¥java¥jdbc
- JDBC サンプル・プログラムが入っています。
- sqllib¥samples¥java¥sqlj
- SQLJ サンプル・プログラムが入っています。
- sqllib¥samples¥xml¥java
- JDBC および SQLJ XML サンプルのサブディレクトリーが入っています。
- sqllib¥samples¥xml¥java¥jdbc
- README ファイルと JDBC XML サンプル・プログラムが入っています。
- sqllib¥samples¥xml¥java¥sqlj
- README ファイルと SQLJ XML サンプル・プログラムが入っています。
- sqllib¥samples¥java¥Websphere
- WebSphere サンプル・プログラムが入っています。
- sqllib¥samples¥java¥plugin
- DB2 コントロール・センターのプラグイン例のファイルが入っています。
- sqllib¥samples¥java¥plugin¥doc
- プラグイン・インターフェース用の javadoc ファイルが入っています。
java调用db2管理API——export,Import
import java.lang.*;
import java.util.*;
import java.sql.*;
class AdmCmdExport
{
public static void main(String argv[])
{
Connection con = null;
int rows_exported;
String msg_retrieval = null;
String msg_removal = null;
String sqlcode = null;
String msg = null;
CallableStatement callStmt1 = null;
ResultSet rs1 = null;
PreparedStatement stmt1 = null;
ResultSet rs2 = null;
CallableStatement callStmt2 = null;
if (argv.length < 1)
{
System.out.println("\n Usage : java AdmCmdExport <path for export>");
}
else
{
try
{
// initialize DB2Driver and establish database connection.
COM.ibm.db2.jdbc.app.DB2Driver db2Driver =
(COM.ibm.db2.jdbc.app.DB2Driver )
Class.forName("COM.ibm.db2.jdbc.app.DB2Driver").newInstance();
con = DriverManager.getConnection("jdbc:db2:SAMPLE");
System.out.println("HOW TO PERFORM EXPORT USING ADMIN_CMD.\n");
// prepare the CALL statement for OUT_LANGUAGE
String sql = "CALL SYSPROC.ADMIN_CMD(?)";
callStmt1 = con.prepareCall(sql);
String param = "export to "+ argv[0] + "org_ex.ixf ";
param = param + "of ixf messages on server select * from org" ;
// set the imput parameter
callStmt1.setString(1, param);
System.out.println("CALL ADMIN_CMD('" + param + "')");
// execute export by calling ADMIN_CMD
callStmt1.execute();
rs1 = callStmt1.getResultSet();
// retrieve the resultset
if( rs1.next())
{
// the numbers of rows exported
rows_exported = rs1.getInt(1);
// retrieve the select stmt for message retrival
// containing SYSPROC.ADMIN_GET_MSGS
msg_retrieval = rs1.getString(2);
// retrive the stmt for message cleanup
// containing CALL of SYSPROC.ADMIN_REMOVE_MSGS
msg_removal = rs1.getString(3);
// display the output
System.out.println("Total number of rows exported : " + rows_exported);
System.out.println("SQL for retrieving the messages: " + msg_retrieval);
System.out.println("SQL for removing the messages : " + msg_removal);
}
stmt1 = con.prepareStatement(msg_retrieval);
System.out.println("\n" + "Executing " + msg_retrieval);
// message retrivel
rs2 = stmt1.executeQuery();
// retrieve the resultset
while(rs2.next())
{
// retrieve the sqlcode
sqlcode = rs2.getString(1);
// retrieve the error message
msg = rs2.getString(2);
System.out.println ("Sqlcode : " +sqlcode);
System.out.println("Msg : " +msg);
}
System.out.println("\nExecuting " + msg_removal);
callStmt2 = con.prepareCall (msg_removal);
// executing the message retrivel
callStmt2.execute();
}
catch(Exception e)
{
JdbcException jdbcExc = new JdbcException(e);
jdbcExc.handle ();
}
finally
{
try
{
// close the statements
callStmt1.close();
callStmt2.close();
stmt1.close();
// close the resultsets
rs1.close();
rs2.close();
// roll back any changes to the database made by this sample
con.rollback();
// close the connection
con.close();
}
catch (Exception x)
{
System.out.print("\n Unable to Rollback/Disconnect ");
System.out.println("from 'sample' database");
}
}
}
} // main
} // AdmCmdExport
import java.lang.*;
import java.util.*;
import java.sql.*;
class AdmCmdImport
{
public static void main(String argv[])
{
Connection con = null;
CallableStatement callStmt1 = null;
CallableStatement callStmt2 = null;
ResultSet rs1 = null;
ResultSet rs2 = null;
PreparedStatement stmt1 = null;
Statement stmt2 = null;
int rows_read;
int rows_skipped;
int rows_loaded;
int rows_rejected;
int rows_deleted;
int rows_committed;
String msg_retrieval = null;
String msg_removal = null;
String sqlcode = null;
String msg = null;
if (argv.length < 1)
{
System.out.println("\n Usage : java AdmCmdImport <path for import>");
}
else
{
try
{
// Initialize DB2Driver and establish database connection.
COM.ibm.db2.jdbc.app.DB2Driver db2Driver =
(COM.ibm.db2.jdbc.app.DB2Driver)
Class.forName ("COM.ibm.db2.jdbc.app.DB2Driver").newInstance();
con = DriverManager.getConnection("jdbc:db2:SAMPLE");
System.out.println("HOW TO DO IMPORT USING ADMIN_CMD.\n");
// prepare the CALL statement for OUT_LANGUAGE
String sql = "CALL SYSPROC.ADMIN_CMD(?)";
callStmt1 = con.prepareCall(sql);
// argv[0] is the path for the file to be imported
String param = "IMPORT FROM " + argv[0] + "org_ex.ixf OF IXF MESSAGES ";
param = param + "ON SERVER CREATE INTO ORG_IMPORT" ;
// setting the imput parameter
callStmt1.setString(1, param);
System.out.println("CALL ADMIN_CMD('" + param + "')");
// executing import by calling ADMIN_CMD
callStmt1.execute ();
rs1 = callStmt1.getResultSet();
// retrieving the resultset
if( rs1.next())
{
// retrieve the no of rows read
rows_read = rs1.getInt(1);
// retrieve the no of rows skipped
rows_skipped = rs1.getInt(2);
// retrieve the no of rows loaded
rows_loaded = rs1.getInt(3);
// retrieve the no of rows rejected
rows_rejected = rs1.getInt(4);
// retrieve the no of rows deleted
rows_deleted = rs1.getInt(5);
// retrieve the no of rows committed
rows_committed = rs1.getInt (6);
// retrieve the select stmt for message retrival
// containing SYSPROC.ADMIN_GET_MSGS
msg_retrieval = rs1.getString(7);
// retrive the stmt for message cleanup
// containing CALL of SYSPROC.ADMIN_REMOVE_MSGS
msg_removal = rs1.getString(8);
// Displaying the resultset
System.out.print("\nTotal number of rows read : ");
System.out.println(rows_read);
System.out.print("Total number of rows skipped : ");
System.out.println( rows_skipped);
System.out.print("Total number of rows loaded : ");
System.out.println(rows_loaded);
System.out.print("Total number of rows rejected : ");
System.out.println(rows_rejected);
System.out.print("Total number of rows deleted : ");
System.out.println(rows_deleted);
System.out.print("Total number of rows committed : ");
System.out.println(rows_read);
System.out.print("SQL for retrieving the messages: ");
System.out.println(msg_retrieval);
System.out.print("SQL for removing the messages : ");
System.out.println(msg_removal);
}
stmt1 = con.prepareStatement (msg_retrieval);
System.out.println("\n" + "Executing " + msg_retrieval);
// message retrivel
rs2 = stmt1.executeQuery();
// retrieving the resultset
while(rs2.next())
{
// retrieving the sqlcode
sqlcode = rs2.getString(1);
//retrieving the error message
msg = rs2.getString(2);
System.out.println("Sqlcode : " +sqlcode);
System.out.println("Msg : " +msg);
}
System.out.println("\n Executing " + msg_removal);
callStmt2 = con.prepareCall(msg_removal);
// executing the message retrivel
callStmt2.execute();
System.out.println("\n Executing DROP TABLE ORG_IMPORT");
stmt2 = con.createStatement();
stmt2.executeUpdate("DROP TABLE ORG_IMPORT");
}
catch(Exception e)
{
JdbcException jdbcExc = new JdbcException(e);
jdbcExc.handle ();
}
finally
{
try
{
//closing the statements and resultset
callStmt1.close();
callStmt2.close();
stmt1.close();
stmt2.close();
rs1.close();
rs2.close();
// roll back any changes to the database made by this sample
con.rollback();
// closing the connection
con.close();
}
catch (Exception x)
{
System.out.print(x);
System.out.print("\n Unable to Rollback/Disconnect ");
System.out.println ("from 'sample' database");
}
}
}
} // main
} // AdmCmdImport
星期五, 五月 25, 2007
去除list中的重复元素
HashSet set = new HashSet();
while(it.hasNext()){
set.add(it.next());
}
it = set.iterator();
while(it.hasNext()){
list.add(it.next());
}
或者是
星期四, 五月 24, 2007
java 读 properties格式文件
package hddqcs.datamining.venus.venusfile;
import hddqcs.datamining.venus.common.DMLogger;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.apache.log4j.Logger;
/**
*
* COPYRIGHT(C) Hitachi Global Storage Technologies, Inc.
* All Rights Reserved.
*
* This Class is to reading the process config file
*
* eg. etl_venusProcess.properties
*
* @author liuqact
*/
public class ReadingProcessProsFile {
Logger logger = Logger.getLogger(ReadingProcessProsFile.class.getName());
public Properties getProperties(String dir,String fileName)throws FileNotFoundException,IOException,Exception {
// TODO Auto-generated method stub
try{
Properties pros = new Properties();
InputStream prosFile = new FileInputStream("Log4j.properties");
pros.load(prosFile);
return pros;
}catch(FileNotFoundException e){
logger.error("Properties file inputted is not exist");
throw e;
}catch(IOException e){
logger.error("Reading Properties file inputted failed");
throw e;
}catch(Exception e){
logger.error("get values from Properties file inputted failed");
throw e;
}
}
}
关于serialVersionUID
在定义一个实现接口java.io.Serializable 的类时
CTRL+1
看看出现在什么
中间有一个是生成serialVersionUID的
星期三, 五月 23, 2007
Java操作Excel的一些可以参考的资源
http://sourceforge.net/projects/jexcelapi
JExcelApi is a java library which provides the ability to read, write, and modify
Microsoft Excel spreadsheets. This project mirrors the files on http://www.jexcelapi.org,
which has been known to go down on occasion.
http://sourceforge.net/projects/excelutils
ExcelUtils, easy export report in excel by excelutils.It like velocity or freemarker, but
it's script is written in excel to control excel format and data.
Templating system for Microsoft Excel files in Java.
JavaOffice is a pure Java library to read and write MS Word files in the new WordML (format) and
MS Excel files in the new SpreadsheetML format. WordML and SpreadsheetML are xml formats for word
and excel files supported from Office 2003 and above.
Each element of the collection goes in a row and the columns are based on the properties you define
through an XML config file.
Caxton is a general purpose package written in Java that is used to render HTML, PDF (using FOP),
RTF (using JFOR), and Excel (using POI) using stylesheets. There are some additional tools for
providing easy access to XML, merging XSL stylesheets
星期二, 五月 22, 2007
JDK1.5中的线程池使用简介(转)
在多线程大师Doug Lea的贡献下,在JDK1.5中加入了许多对并发特性的支持,例如:线程池。这里介绍的就是1.5种的线程池的简单使用方法。 |
一、简介
线程池类为 java.util.concurrent.ThreadPoolExecutor,常用构造方法为:ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
- corePoolSize
线程池维护线程的最少数量- maximumPoolSiz
线程池维护线程的最大数量- keepAliveTime
线程池维护线程所允许的空闲时间- unit
线程池维护线程所允许的空闲时间的单位- workQueue
线程池所使用的缓冲队列- handler
线程池对拒绝任务的处理策略一个任务通过 execute(Runnable)方法被添加到线程池,任务就是一个 Runnable类型的对象,任务的执行方法就是 Runnable类型对象的run()方法。
当一个任务通过execute(Runnable)方法欲添加到线程池时:也就是:处理任务的优先级为:
- 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
- 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
- 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
- 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
unit可选的参数为java.util.concurrent.TimeUnit中的几个静态属性:
NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS。
workQueue我常用的是:java.util.concurrent.ArrayBlockingQueue
handler有四个选择:
- ThreadPoolExecutor.AbortPolicy()
抛出java.util.concurrent.RejectedExecutionException异常- ThreadPoolExecutor.CallerRunsPolicy()
重试添加当前的任务,他会自动重复调用execute()方法- ThreadPoolExecutor.DiscardOldestPolicy()
抛弃旧的任务- ThreadPoolExecutor.DiscardPolicy()
抛弃当前的任务
二、一般用法举例 [下载源代码]
package cn.simplelife.exercise;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class TestThreadPool {
private static int produceTaskSleepTime = 2;
public static void main(String[] args) {
//构造一个线程池
ThreadPoolExecutor producerPool = new ThreadPoolExecutor(2, 4, 0,
TimeUnit.SECONDS , new ArrayBlockingQueue(3),
new ThreadPoolExecutor.DiscardOldestPolicy());
//每隔produceTaskSleepTime的时间向线程池派送一个任务。
int i=1;
while(true){
try {
Thread.sleep(produceTaskSleepTime);
String task = "task@ " + i;
System.out.println("put " + task);
producerPool.execute(new ThreadPoolTask(task));
i++;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package cn.simplelife.exercise;
import java.io.Serializable;
/**
* 线程池执行的任务
* @author hdpan
*/
public class ThreadPoolTask implements Runnable,Serializable{
//JDK1.5中,每个实现Serializable接口的类都推荐声明这样的一个ID
private static final long serialVersionUID = 0;
private static int consumeTaskSleepTime = 2000;
private Object threadPoolTaskData;
ThreadPoolTask(Object tasks){
this.threadPoolTaskData = tasks;
}
//每个任务的执行过程,现在是什么都没做,除了print和sleep,:)
public void run(){
System.out.println("start .."+threadPoolTaskData);
try {
//便于观察现象,等待一段时间
Thread.sleep(consumeTaskSleepTime);
} catch (Exception e) {
e.printStackTrace();
}
threadPoolTaskData = null;
}
}
对这两段程序的说明:
- 在这段程序中,一个任务就是一个Runnable类型的对象,也就是一个ThreadPoolTask类型的对象。
- 一般来说任务除了处理方式外,还需要处理的数据,处理的数据通过构造方法传给任务。
- 在这段程序中,main()方法相当于一个残忍的领导,他派发出许多任务,丢给一个叫 threadPool的任劳任怨的小组来做。
- 这个小组里面队员至少有两个,如果他们两个忙不过来, 任务就被放到任务列表里面。
- 如果积压的任务过多,多到任务列表都装不下(超过3个)的时候,就雇佣新的队员来帮忙。但是基于成本的考虑,不能雇佣太多的队员, 至多只能雇佣 4个。
- 如果四个队员都在忙时,再有新的任务, 这个小组就处理不了了,任务就会被通过一种策略来处理,我们的处理方式是不停的派发, 直到接受这个任务为止(更残忍!呵呵)。
- 因为队员工作是需要成本的,如果工作很闲,闲到 3SECONDS都没有新的任务了,那么有的队员就会被解雇了,但是,为了小组的正常运转,即使工作再闲,小组的队员也不能少于两个。
- 通过调整 produceTaskSleepTime和 consumeTaskSleepTime的大小来实现对派发任务和处理任务的速度的控制, 改变这两个值就可以观察不同速率下程序的工作情况。
- 通过调整4中所指的数据,再加上调整任务丢弃策略, 换上其他三种策略,就可以看出不同策略下的不同处理方式。
- 对于其他的使用方法,参看jdk的帮助,很容易理解和使用。
附:jdk1.5中关于ThreadPoolExecutor的javadoc地址
星期日, 五月 20, 2007
星期五, 五月 18, 2007
Java SE 6中JDBC 4.0的增强特性(转)
Java SE 6包含了对Java数据库互连(JDBC)API的一些增强特性。这些增强特性的版本将定为JDBC version 4.0。JDBC新特性的目的是提供更简单的设计和更好的开发体验。本文将概述JDBC 4.0的增强特性和为企业级Java开发人员带来的好处。我们将通过一个用Apache Derby作为后台数据库的贷款处理应用范例来探究JDBC的新特性。
Java SE 6包含了对Java数据库互连(JDBC)API的一些增强特性。这些增强特性的版本将定为JDBC version 4.0。JDBC新特性的目的是提供更简单的设计和更好的开发体验。本文将概述JDBC 4.0的增强特性和为企业级Java开发人员带来的好处。我们将通过一个用Apache Derby作为后台数据库的贷款处理应用范例来探究JDBC的新特性。
Java SE 6.0
Java SE 6.0版以兼容性、稳定性和品质作为设计目标。本版本中有不少值得关注的增强特性,特别是JMX、web services、脚本语言支持(采用Rhino脚本引擎JSR 223把JavaScript技术与Java源码进行集成)、数据库连接、支持annotations和安全部分。另外,在JDBC API中还有不少新的特性,包括RowId支持和新增的SQLException子类。
JDBC 4.0的特性
得益于Mustang中的Java SE 服务提供商机制,Java开发人员再也不必用类似Class.forName()的代码注册JDBC驱动来明确加载JDBC。当调用DriverManager.getConnection()方法时,DriverManager类将自动设置合适的驱动程序。该特性向后兼容,因此无需对现有的JDBC代码作任何改动。
通过对Java应用程序访问数据库代码的简化,使得JDBC 4.0有更好的开发体验。JDBC 4.0同时也提供了工具类来改进数据源和连接对象的管理,也改进了JDBC驱动加载和卸载机制。
有了JDBC 4.0传承自Java SE 5.0 (Tiger)版对元数据的支持功能,Java开发人员可用Annotations明确指明SQL查询。基于标注的SQL查询允许我们通过在Java代码中使用Annotation关键字正确指明SQL查询字符串。这样,我们不必查看JDBC代码和他所调用的数据库两份不同的文件。例如,用一个名为getActiveLoans()方法在贷款处理数据库中获取一个活跃贷款清单,你可以添加@Query(sql="SELECT * FROM LoanApplicationDetails WHERE LoanStatus = 'A'")标注来修饰该方法。
并且,最终版的Java SE 6开发包(JDK 6)以及其相应的执行期环境(JRE 6)会捆绑一个基于Apache Derby的数据库。这使得Java开发人员无需下载、安装和配置一款单独的数据库产品就能探究JDBC的新特性。
JDBC 4.0中增加的主要特性包括:
1. JDBC驱动类的自动加载
2. 连接管理的增强
3. 对RowId SQL类型的支持
4. SQL的DataSet实现使用了Annotations
5. SQL异常处理的增强
6. 对SQL XML的支持
另外,对BLOB/CLOB 的改进支持以及对国际字符集的支持也是JDBC 4.0的特性。这些特性将在随后章节中详细讨论。
JDBC驱动自动加载
在JDBC 4.0中,我们不必再使用Class.forName()方法明确加载JDBC驱动。当调用getConnection方法时,DriverManager会尝试从初始化时已经加载的JDBC驱动程序库中选择合适的驱动,以及他在当前应用的同一个类加载器中明确加载使用过的驱动。
DriverManager中的getConnection和getDrivers方法已作了改进,以支持Java SE 服务提供商机制(SPM)。根据SPM,所谓服务就是一组广为人知的接口和抽象类的集合,而服务提供商就是对某一服务的特定实现。SPM还指明了服务提供商的配置文件存放于META-INF/services目录下。JDBC 4.0的驱动程序库必须包含META-INF/services/java.sql.Driver文件。该文件包含对java.sql.Driver 实现的JDBC驱动文件名。例如,通过JDBC驱动连接Apache Derby数据库,META-INF/services/java.sql.Driver将含有以下路径:
org.apache.derby.jdbc.EmbeddedDriver
我们再来快速地看一下如何使用这一新特性加载一个JDBC驱动管理。以下显示的是我们用以加载JDBC驱动的典型范例代码。这里我们假设连接的是Apache Derby数据库,因为该数据库将在本文随后的范例应用中用到:
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
Connection conn =
DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
但在JDBC 4.0中,我们不必写Class.forName()这一行,我们只需要调用getConnection()方法取得数据库连接。
请注意,仅在完全独立的模式下可使用该方法取得数据库的连接。如果你使用一些类似数据库连接池等技术管理连接,那么代码将有所不同。
连接管理
在JDBC 4.0之前,我们依靠JDBC URL来定义一个数据源连接。现在有了JDBC 4.0,我们只需为标准连接工厂机制提供一组参数,就能获取与任何数据源的连接。Connection和Statement接口增添的新方法为池环境中管理Statement对象提供了更好的连接状态跟踪机制和更大的灵活度。元数据工具(JSR-175)被用来管理活跃连接。我们还能获得元数据信息,如:活跃连接状态,并能指明XA事务的某一连接是标准式(Connection,在独立应用的情况下)、池式(PooledConnection)还是分布式(XAConnection)。该接口仅在诸如WebLogic、WebSphere和JBoss等Java EE应用服务器的事务管理中使用。
RowId支持
JDBC 4.0增加了RowID接口以支持ROWID数据类型,Oracle和DB2数据库支持该数据类型。在你需要把大量缺少唯一标识符字段的查询记录放入一个不允许重复对象的Collection容器(如Hashtable)的情况下,RowId很有用。我们可以用ResultSet的getRowId()方法获取RowId,用PreparedStatement的setRowId()方法在查询中使用RowId。
关于RowId对象需要记住的一件重要事项是,RowId值在数据源之间不可移植。当在PreparedStatement和ResultSet中单独使用set或update方法时,需要想到指明数据源。因此,RowId对象不应被不同的Connection和ResultSet对象共享。
DatabaseMetaData中的getRowIdLifetime()方法可被用来确定RowId对象的有效存活时间。该方法的可能返回值如表1所列:
RowId值 描述
ROWID_UNSUPPORTED Doesn't support ROWID data type.
ROWID_VALID_OTHER Lifetime of the RowID is dependent on database vendor implementation.
ROWID_VALID_TRANSACTION Lifetime of the RowID is within the current transaction as long as the row in the database table is not deleted.
ROWID_VALID_SESSION Lifetime of the RowID is the duration of the current session as long as the row in the database table is not deleted.
ROWID_VALID_FOREVER Lifetime of the RowID is unlimited as long as the row in the database table is not deleted.
基于标注的SQL查询
JDBC 4.0对标注(Java SE 5新增)作了进一步规范和补充,他允许开发人员不必再写大量代码就能达到联系SQL查询和Java类的目的。并且,通过使用Generics(JSR 014)和元数据(JSR 175) API,我们只要指明查询的输入和输出参数就能将SQL查询与Java对象进行关联。我们还可以将查询结果捆绑在Java类上以加快查询输出的处理。将查询对象置于Java对象之中,我们可以不必像往常一样写所有代码。在Java代码中指明SQL查询,经常用到两种标注:
Select标注
Select标注用于在Java类中指明一个选择查询,使get方法能从数据库表中取回数据。表2显示的是Select标注的不同属性及其作用:
变量 类型 描述
sql String SQL Select query string.
value String Same as sql attribute.
tableName String Name of the database table against which the sql will be invoked.
readOnly, connected, scrollable Boolean Flags used to indicate if the returned DataSet is read-only or updateable, is connected to the back-end database, and is scrollable when used in connected mode respectively.
allColumnsMapped Boolean Flag to indicate if the column names in the sql annotation element are mapped 1-to-1 with the fields in the DataSet.
这里有一个应用Select标注从贷款数据库中获取所有活跃贷款的例子:
interface LoanAppDetailsQuery extends BaseQuery {
@Select("SELECT * FROM LoanDetais where LoanStatus = 'A'")
DataSet<LoanApplication> getAllActiveLoans();
}
Sql标注同样允许I/O参数(参数标记以一个问号后跟一个整型数据表示)。这里是一个参数化sql查询的例子:
interface LoanAppDetailsQuery extends BaseQuery {
@Select(sql="SELECT * from LoanDetails
where borrowerFirstName= ?1 and borrowerLastName= ?2")
DataSet<LoanApplication> getLoanDetailsByBorrowerName(String borrFirstName,
String borrLastName);
}
Update标注
Update标注用于修饰Query接口方法以更新数据库表中的一条或多条记录。Update标注必须包含一个sql标注类型元素。这里是一个Update标注的例子:
interface LoanAppDetailsQuery extends BaseQuery {
@Update(sql="update LoanDetails set LoanStatus = ?1
where loanId = ?2")
boolean updateLoanStatus(String loanStatus, int loanId);
}
SQL异常处理的增强特性
异常处理是Java编程的一个重要部分,特别是对后台关系数据库进行连接或查询时。SQLException是我们用以指出与数据库相关错误的类。JDBC 4.0在SQLException处理中有不少增强。为了在处理SQLException时获得更好的开发体验,JDBC 4.0版作了如下增强:
1. 新的SQLException子类
2. 对因果关系的支持
3. 对改进的for-each循环的支持
新的SQLException类
SQLException的新子类提供了一种方法,使Java开发人员能写出更方便改动的错误处理代码。JDBC 4.0介绍了两个新的SQLException型别:
• SQL non-transient exception
• SQL transient exception
Non-Transient Exception:除非修正引发SQLException异常的代码,否则该异常在再次尝试相同JDBC操作失败后被抛出。表3显示了JDBC 4.0新增的SQLNonTransientException异常子类(SQL 2003规范中定义了SQLState类的值):
Exception class SQLState value
SQLFeatureNotSupportedException 0A
SQLNonTransientConnectionException 08
SQLDataException 22
SQLIntegrityConstraintViolationException 23
SQLInvalidAuthorizationException 28
SQLSyntaxErrorException 42
Transient Exception:当先前执行失败的JDBC操作在没有任何应用级功能干涉的情况下可能成功执行时,该异常被抛出。继承自SQLTransientException的新异常如表4所列:
Exception class SQLState value
SQLTransientConnectionException 08
SQLTransactionRollbackException 40
SQLTimeoutException None
因果关系
SQLException类现在支持Java SE链式异常机制(又称因果工具),它使我们能在一个JDBC操作中处理多条SQLException异常(如果后台数据库支持多条异常特性)。这种情形发生在执行一条可能会抛出多条SQLException异常的语句时。
我们可以调用SQLException中的getNextException()方法在异常链中进行迭代。这里是一些处理getNextException()因果关系的范例代码:
catch(SQLException ex) {
while(ex != null) {
LOG.error("SQL State:" + ex.getSQLState());
LOG.error("Error Code:" + ex.getErrorCode());
LOG.error("Message:" + ex.getMessage());
Throwable t = ex.getCause();
while(t != null) {
LOG.error("Cause:" + t);
t = t.getCause();
}
ex = ex.getNextException();
}
}
增强的For-Each环
Java SE 5中,SQLException类通过实现Iterable接口,增加了for-each循环支持的特性。这个循环的轨迹将会包括SQLException和其异常成因。这里的代码片断展示了SQLException中增加的增强型for-each环特性。
catch(SQLException ex) {
for(Throwable e : ex ) {
LOG.error("Error occurred: " + e);
}
}
对国际字符集转换的支持
以下是JDBC类处理国际字符集的新增特性:
1. JDBC数据类型:新增NCHAR、NVARCHAR、LONGNVARCHAR和NCLOB数据类型。
2. PreparedStatement:新增setNString、setNCharacterStream和setNClob方法。
3. CallableStatement:新增getNClob、getNString和getNCharacterStream方法。
4. ResultSet:ResultSet接口新增updateNClob、updateNString和updateNCharacterStream方法。
对大对象(BLOBs and CLOBs)支持的改进
以下是JDBC 4.0处理LOBs的新增特性:
1. Connection:新增方法(createBlob()、createClob()和createNClob())以创建BLOB、CLOB和NCLOB对象新实例。
2. PreparedStatement:新增方法setBlob()、setClob()和setNClob()以使用InputStream对象插入BLOB对象,使用Reader对象插入CLOB和NCLOB对象。
3. LOBs:在Blob、Clob和NClob接口中新增方法(free())以释放这些对象所持有的资源。
现在,让我们来看一看java.sql和javax.jdbc包的新类,以及他们所提供的服务。
JDBC 4.0 API:新类
RowId (java.sql)
正如先前所介绍的,该接口是对数据库中SQL ROWID值的展示。ROWID是一种SQL内建的数据类型,用来标识数据库中的一行特定数据。ROWID经常用于从表中返回查询结果,而这些结果行往往缺少唯一ID字段。
getRowId和setRowId等CallableStatement、PreparedStatement和ResultSet接口的方法允许程序员访问SQL ROWID值。RowId接口还提供了一个方法(叫getBytes())把ROWID值作为一个byte型数组返回。DatabaseMetaData接口有一个名为getRowIdLifetime的新方法,用以确定某一RowId对象的存活时间。RowId的存活时间范围可以是如下三种类型:
1. 创建RowId的数据库事务持续时间
2. 创建RowId的会话持续时间
3. 数据库对应的记录还未被删除的持续时间
DataSet (java.sql)
DataSet接口提供了对执行SQL Query后所返回数据类型的安全检查。DataSet还可以运行在连接或非连接模式。在连接模式下,DataSet类似于ResultSet的功能;而在非连接模式下,他类似于CachedRowSet的功能。由于DataSet继承自List接口,因此我们能对查询返回的记录行进行迭代。
对已有的类,JDBC 4.0也新增了不少方法。比如,Connection新增了createSQLXML和createSQLXML方法,ResultSet新增了getRowId方法。
范例应用
本文所示的范例应用是一个贷款处理应用软件,他有一个贷款搜索页面,用户可以通过输入贷款ID提交查询表,以获取贷款详情。贷款搜索页面调用一个控制器对象,而该对象又调用一个DAO对象访问后台数据库,以取回贷款详情。这些详情包括贷款人、贷款数额、贷款截至日期等信息,并显示在贷款详情屏幕上。后台数据库中,我们有一个名为LoanApplicationDetails的表,来存储贷款软件的详情。
该范例应用的用例是通过指定贷款ID来获取贷款详情。当贷款已经登记并将抵押物与利息挂钩后,贷款详情就可以被获取。表5显示了贷款处理应用软件项目的详情。
Name Value
Project Name JdbcApp
Project Directory c:\dev\projects\JdbcApp
DB Directory c:\dev\dbservers\apache\derby
JDK Directory c:\dev\java\jdk_1.6.0
IDE Directory c:\dev\tools\eclipse
Database Apache Derby 10.1.2.1
JDK 6.0 (beta 2 release)
IDE Eclipse 3.1
Unit Testing JUnit 4
Build Ant 1.6.5
下表所列的是我们连接贷款详情Apache Derby数据库所需的JDBC参数。这些参数存放于一个名为derby.properties的文本文件中,并置于项目的etc/jdbc目录下(见表6)。
Name Value
JDBC Driver File LoanApp\META-INF\services\java.sql.driver
Driver org.apache.derby.ClientDriver
URL jdbc:derby:derbyDB
User Id user1
Password user1
请注意:Apache Derby数据库提供了两种JDBC驱动:嵌入式驱动(org.apache.derby.jdbc.EmbeddedDriver)和客户端/服务器驱动(org.apache.derby.jdbc.ClientDriver)。我在范例应用中使用客户端/服务器版驱动。
以下是使用ij工具来启动Derby数据库服务器并创建新数据库的命令。
要启动Derby网络服务器,需开启一个命令行窗口,并运行如下命令(请根据你本机的环境改写DERBY_INSTALL和JAVA_HOME环境变量)。
set DERBY_INSTALL=C:\dev\dbservers\db-derby-10.1.2.1-bin
set JAVA_HOME=C:\dev\java\jdk1.6.0
set DERBY_INSTALL=C:\dev\dbservers\db- derby-10.1.3.1-bin
set CLASSPATH=%CLASSPATH%;%DERBY_INSTALL%\lib\derby.jar;
%DERBY_INSTALL%\lib\derbytools.jar;
%DERBY_INSTALL%\lib\derbynet.jar;
cd %DERBY_INSTALL%\frameworks\NetworkServer\bin
startNetworkServer.bat
要连接数据库服务器并创建测试数据库,需开启另一个命令行窗口并运行以下命令。请确保DERBY_INSTALL和JAVA_HOME环境变量符合你本机的环境。
set JAVA_HOME=C:\dev\java\jdk1.6.0
set DERBY_INSTALL=C:\dev\dbservers\db-derby-10.1.3.1-bin
set CLASSPATH=%DERBY_INSTALL%\lib\derbyclient.jar;
%DERBY_INSTALL%\lib\derbytools.jar;.
%JAVA_HOME%\bin\java org.apache.derby.tools.ij
connect 'jdbc:derby://localhost:1527/LoanDB;create=true';
测试
要编译Java源代码,classpath需包括derby.jar和junit4.jar文件,这两个文件在项目的lib目录下。Classpath还需包括etc、etc/jdbc和etc/log4j目录,这样应用程序才能访问JDBC属性文件和Log4J配置文件。我创建了一个Ant构建脚本(在JdbcApp/build目录下)来自动完成编译和打包Java源代码的工作。
用于测试贷款详情数据库访问对象的测试类名为LoanAppDetailsDAOTest。我们传入贷款ID和贷款人参数就可以获取贷款详情。
以下部分显示了JDBC 4.0中自动加载JDBC驱动和基于标注的SQL查询特性的代码范例。
JDBC驱动的自动加载
BaseDAO抽象类有一个名为getConnection的方法用以获得一个数据库连接。以下代码片断显示了该方法(注意,我们不必注册JDBC驱动)。只要java.sql.Driver文件中有合适的驱动程序类名(org.apache.derby.jdbc.ClientDriver ),JDBC驱动将被自动加载。
protected Connection getConnection() throws DAOException {
// Load JDBC properties first
if (jdbcUrl == null || jdbcUser == null ||
jdbcPassword == null) {
loadJdbcProperties();
}
// Get Connection
Connection conn = null;
try {
conn = DriverManager.getConnection(jdbcUrl, jdbcUser,
jdbcPassword);
} catch (SQLException sqle) {
throw new DAOException("Error in getting a DB connection.",
sqle);
}
return conn;
}
SQL标注
LoanAppDetailsQuery接口有标注了的SQL查询,用以获取活跃贷款清单(criteria is loanstatus="A")和某贷款人的贷款详情(在一个贷款人有多笔贷款的情况下)。在上文中,我们已经了解过了这些SQL标注。这里的范例代码显示了我们如何使用标注来调用已定义的SQL查询。
public DataSet<LoanAppDetails> getAllActiveLoans() throws Exception {
// Get Connection
Connection conn = getConnection();
LoanAppDetailsQuery query = null;
DataSet<LoanAppDetails> loanDetails = null;
query = QueryObjectFactory.createQueryObject (
LoanAppDetailsQuery.class, conn);
loanDetails = query.getAllActiveLoans();
return loanDetails;
}
public DataSet<LoanAppDetails> getLoanDetailsByBorrowerName(
String borrFirstName, String borrLastName) throws Exception {
// Get Connection
Connection conn = getConnection();
LoanAppDetailsQuery query = null;
DataSet<LoanAppDetails> loanDetails = null;
query = QueryObjectFactory.createQueryObject(
LoanAppDetailsQuery.class, conn);
loanDetails = query.getLoanDetailsByBorrowerName(
borrFirstName,borrLastName);
return loanDetails;
}
结论
JDBC 4.0在SQL方面为开发者提供了更好的开发体验。JDBC 4.0的另一个目标是为API增加更丰富的工具以提供企业级JDBC特性管理JDBC资源。并且,JDBC 4.0 API还提供了JDBC驱动的移植方式,使其符合J2EE连接器架构(JCA)规范。这为JDBC厂商提供了向JDBC连接器迁移的能力。在面向企业服务的架构(SPA)中使用JDBC数据源,该移植方式很重要。在SOA中,JDBC数据源可被部署在另一个企业服务总线(ESB)架构内,而不需要为JDBC数据源另写一份ESB实现代码。
本文中,我们了解了RowId支持,JDBC驱动加载和基于标注的SQL等JDBC 4.0的增强特性。未来,JDBC 4.0还将增加更多特性以支持SQL:2003。请参阅特性文档,以获取更多有关JDBC 4.0特性的信息。
Resources
Matrix-与Java共舞
Sample Application Code
Srini Penchikala是Flagstar Bank的一位信息系统问题专家。
ajax名家杂谈之一二
星期三, 五月 16, 2007
用List传递Resultset对象 得到的不同类型对象
public static ArrayList<LinkedHashMap> delRes(String sql) {
ArrayList<LinkedHashMap> list = new ArrayList<LinkedHashMap>();
Connection con = null;
PreparedStatement stmt = null;
ResultSetMetaData metaData=null;
try {
con = ConDB.getCon();
stmt = (PreparedStatement) con.prepareStatement(sql);
ResultSet result = stmt.executeQuery();
metaData=result.getMetaData();
while (result.next()) {
LinkedHashMap v = new LinkedHashMap();
for (int i = 1; i <= metaData.getColumnCount (); i++)
v.put(metaData.getColumnLabel(i),result.getObject(i));
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
if (stmt != null) {
stmt.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
return list;
}
Object domain=null;
while(rs.next()){
domain=Class.forName("Domain").newInstance();
for(int i=1;i<=rsm.getColumnCount();i++){
String recordValue= rs.getString(rsm.getColumnName(i));
Method m=domain.getClass().getMethod("set"+rsm.getColumnName(i),new Class[]{recordValue.getClass()});
m.invoke(domain,new Object[]{recordValue});
}
list.add(domain);
}
星期三, 四月 25, 2007
按文件日期排序
利用Collections的sort函数,实现一个Comparator
按时间倒序的Comparator
import java.io.File; import java.util.Comparator; /** * 比较文件时间:倒序. * * @author scud http://www.javascud.org * */ public class FileDateTimeComparator implements Comparator { public int compare(Object fileA, Object fileB) { File realFileA = (File) fileA; File realFileB = (File) fileB; return (realFileA.lastModified()<realFileB.lastModified())?1:-1; } }
其他方法的排序的自己参考编写吧
调用方法:
Collections.sort(fileList,new FileDateTimeComparator());
其中fileList里面存的是File类型的对象.
比较,复制文件,移动文件,重命名文件,文件与String互转,打印文件相关信息
import java.io.*;
/**
*Title: Javas from hartech.cn
*
*Description: JTL's File ToolKit
*Copyright: Copyright (c) 2006 hartech.cn
* Website: www.hartech.cn
*
* @author JTL.zheng@gmail.com
* @version 1.0
*/
public class JFile {
/**
* print the informations of the file input
* @param f File
*/
public static void fileInfo(String name) {
fileInfo(new File(name));
}
public static void fileInfo(File f) {
J.p("--------- Attributes of the files ----------");
if (f == null) {
J.pw("a null reference!!");
}
else if (!f.exists()) {
J.pw(f.toString() + " file Not Found!");
}
else if (f.isFile()) {
StringBuffer length = new StringBuffer(String.valueOf(f.length()));
int i = length.length() - 3;
while (i > 0) {
length.insert(i, ",");
i -= 3;
}
J.p("\"" + f.toString() + "\" is a File.");
J.p("Name: \t\t" + f.getName());
J.p("Readable: \t" + f.canRead());
J.p("Writable: \t" + f.canWrite());
J.p("AbsolutePath:\t" + f.getAbsolutePath());
J.p("Parent:\t\t" + f.getAbsoluteFile().getParent());
J.p("Length:\t\t" + length + " bytes");
}
else {
J.p("\"" + f.toString() + "\" is a Directory");
J.p("Name: \t\t" + f.getName());
J.p("Readable: \t" + f.canRead());
J.p("Writable: \t" + f.canWrite());
J.p("AbsolutePath:\t" + f.getAbsolutePath());
J.p("Parent:\t\t" + f.getAbsoluteFile().getParent());
J.p("Subfiles:\t" + f.list().length);
}
J.p("-------------- fileInfo END ---------------");
}
/**
* compare file byte by byte
* can compare any file(binary file,text file...)
* @param file1 File
* @param file2 File
* @return boolean
*/
public static boolean compareFile(String file1, String file2) {
return compareFile(new File(file1), new File(file2));
}
public static boolean compareFile(File file1, File file2) {
BufferedInputStream in1 = null, in2 = null;
try {
in1 = new BufferedInputStream(new FileInputStream(
file1));
in2 = new BufferedInputStream(new FileInputStream(
file2));
int i;
while ( (i = in1.read()) != -1) {
if (i != in2.read()) {
return false;
}
}
if (in2.read() != -1) {
return false;
}
return true;
}
catch (FileNotFoundException ex) {
J.pw("File not found!");
}
catch (IOException ex) {
J.pw("IOException!");
}
finally {
try {
in1.close();
in2.close();
}
catch (IOException ex1) {
J.pw("IOException when closing!");
}
}
return false;
}
/**
* the java.io.File.renameTo(File,String newname)
* actually move the file to newname's path and rename it which is inconvenient.
* this method just rename the file and keep where it is,ignore the move
* and return the new File's reference
* eg. file = renameFile(file,"NewName.xxx");
* @param file File
* @param name String the newName
* @return File the new File's reference
*/
public static File renameFile(String file, String name) {
return renameFile(new File(file), name);
}
public static File renameFile(File file, String name) {
File newname;
if (file == null !file.exists()) {
J.pw("File not found!");
return null;
}
if (file.getParent() == null) {
newname = new File(name);
file.renameTo(newname);
}
else {
newname = new File(file.getParentFile(), name);
file.renameTo(newname);
}
J.p("Rename is done: " + file + " -> " + newname);
return newname;
}
/**
* use java.io.File.renameTo(File,String newname) to move file
* parameters must be a file and a directory
* return a reference point to the new file
* @param scr String
* @param dir String
* @return File a reference point to the new file
*/
public static File moveFile(String scr, String dir) {
return moveFile(new File(scr), new File(dir));
}
public static File moveFile(File scr, File dir) {
if (scr == null dir == null) {
J.pw("a null reference!");
return null;
}
if (!scr.exists() !dir.exists() scr.isDirectory() dir.isFile()) {
J.pw("not file or directory or not exist!");
return null;
}
File f = new File(dir, scr.getName());
if (f.exists()) {
J.pw("target file has existed!");
}
scr.renameTo(f);
J.p("move file done: " + scr + " -> " + f);
return f;
}
/**
* turn file to String
* maybe you can use it to access file randomly through the string
* but it maybe fault when trun a big file to string
* @param file String
* @return String
*/
public static String fileToString(String file) {
String lineStr = "", string = "";
int i;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
while ( (i = in.read()) != -1) {
string += (char) i;
}
string = string.trim();
return string;
}
catch (FileNotFoundException ex) {
J.pw("File Not Found!");
}
catch (IOException ex) {
J.pw("IO exception!");
}
finally {
try {
in.close();
}
catch (IOException ex1) {
J.pw("IOException when closing!");
}
}
return null;
}
/**
* write the string to file
* if fail return false else return true
* @param src String
* @param file String
* @return boolean
*/
public static boolean stringToFile(String src, String file) {
BufferedWriter out = null;
try {
out = new BufferedWriter(new FileWriter(file));
out.write(src);
return true;
}
catch (Exception ex) {
J.pw("IO exception!");
}
finally {
try {
out.close();
}
catch (IOException ex) {
J.pw("IOException when closing!");
}
}
return false;
}
/**
* only used to copy character files
* local char -> int -> unicode -> int -> local char
* @param src String
* @param dest String
*/
static public void copyFileByChar(String src, String dest) {
String lineStr;
BufferedReader in = null;
BufferedWriter out = null;
try {
in = new BufferedReader(new FileReader(src));
out = new BufferedWriter(new FileWriter(dest));
while ( (lineStr = in.
readLine()) != null) {
out.write(lineStr);
out.newLine();
}
J.p("copy is done !");
}
catch (FileNotFoundException ex) {
J.pw("File Not Found!");
}
catch (IOException ex) {
J.pw("IO exception!");
}
finally {
try {
in.close();
out.close();
}
catch (IOException ex1) {
J.pw("IOException when closing!");
}
}
}
/**
* copy file by byte
* can copy any file,because any file is made of bytes
* bytes -> int -> bytes
* @param src String
* @param dest String
*/
public static void copyFile(String src, String dest) {
copyFile(new File(src), new File(dest));
}
public static void copyFile(File src, File dest) {
int b;
BufferedInputStream in = null;
BufferedOutputStream out = null;
try {
in = new BufferedInputStream(new FileInputStream(src));
out = new BufferedOutputStream(new FileOutputStream(
dest));
while ( (b = in.read()) != -1) {
out.write(b);
}
J.p("CopyFile is done: " + src + " -> " + dest);
}
catch (FileNotFoundException ex) {
J.pw("File Not Found!");
}
catch (IOException ex) {
J.pw("IO exception!");
}
finally {
try {
in.close();
out.close();
}
catch (IOException ex1) {
J.pw("IOException when closing!");
}
}
}
static public void transformFile(String src, String dest) {
String lineStr;
int i = 0;
BufferedReader in = null;
BufferedWriter out = null;
try {
in = new BufferedReader(new FileReader(src));
out = new BufferedWriter(new FileWriter(dest));
while ( (lineStr = in.
readLine()) != null) {
// add transform codes here
// line by line
// eg. String lineStr=function(lineStr)
i = 0;
if (!lineStr.equals("")) {
while (lineStr.charAt(i) == J.SPACEC) {
lineStr = lineStr.replaceFirst(J.SPACES, J.TABS);
i++;
}
}
// code end
out.write(lineStr);
out.newLine();
}
J.p("Transform File is done: " + src + " -> " + dest);
}
catch (FileNotFoundException ex) {
J.pw("File Not Found!");
}
catch (IOException ex) {
J.pw("IO exception!");
}
finally {
try {
in.close();
out.close();
}
catch (IOException ex) {
J.pw("IOException when closing!");
}
}
}
public static String getIO() {
java.io.BufferedReader br;
br = new BufferedReader(new InputStreamReader(System.in));
try {
return br.readLine();
}
catch (IOException ex) {
return null;
}
}
public static void main(String[] arg) {
transformFile("scr/hartech/J.java", "dest.txt");
}
}
java 下复制,移动文件
public class FileOperate {
public FileOperate() {
}
/**
* 新建目录
* @param folderPath String 如 c:/fqf
* @return boolean
*/
public void newFolder(String folderPath) {
try {
String filePath = folderPath;
filePath = filePath.toString();
java.io.File myFilePath = new java.io.File(filePath);
if (!myFilePath.exists()) {
myFilePath.mkdir();
}
}
catch (Exception e) {
System.out.println("新建目录操作出错");
e.printStackTrace();
}
}
/**
* 新建文件
* @param filePathAndName String 文件路径及名称 如c:/fqf.txt
* @param fileContent String 文件内容
* @return boolean
*/
public void newFile(String filePathAndName, String fileContent) {
try {
String filePath = filePathAndName;
filePath = filePath.toString();
File myFilePath = new File(filePath);
if (!myFilePath.exists()) {
myFilePath.createNewFile();
}
FileWriter resultFile = new FileWriter(myFilePath);
PrintWriter myFile = new PrintWriter(resultFile);
String strContent = fileContent;
myFile.println(strContent);
resultFile.close();
}
catch (Exception e) {
System.out.println("新建目录操作出错");
e.printStackTrace();
}
}
/**
* 删除文件
* @param filePathAndName String 文件路径及名称 如c:/fqf.txt
* @param fileContent String
* @return boolean
*/
public void delFile(String filePathAndName) {
try {
String filePath = filePathAndName;
filePath = filePath.toString();
java.io.File myDelFile = new java.io.File(filePath);
myDelFile.delete();
}
catch (Exception e) {
System.out.println("删除文件操作出错");
e.printStackTrace();
}
}
/**
* 删除文件夹
* @param filePathAndName String 文件夹路径及名称 如c:/fqf
* @param fileContent String
* @return boolean
*/
public void delFolder(String folderPath) {
try {
delAllFile(folderPath); //删除完里面所有内容
String filePath = folderPath;
filePath = filePath.toString();
java.io.File myFilePath = new java.io.File(filePath);
myFilePath.delete(); //删除空文件夹
}
catch (Exception e) {
System.out.println("删除文件夹操作出错");
e.printStackTrace();
}
}
/**
* 删除文件夹里面的所有文件
* @param path String 文件夹路径 如 c:/fqf
*/
public void delAllFile(String path) {
File file = new File(path);
if (!file.exists()) {
return;
}
if (!file.isDirectory()) {
return;
}
String[] tempList = file.list();
File temp = null;
for (int i = 0; i < tempList.length; i++) {
if (path.endsWith(File.separator)) {
temp = new File(path + tempList[i]);
}
else {
temp = new File(path + File.separator + tempList[i]);
}
if (temp.isFile()) {
temp.delete();
}
if (temp.isDirectory()) {
delAllFile(path+"/"+ tempList[i]);//先删除文件夹里面的文件
delFolder(path+"/"+ tempList[i]);//再删除空文件夹
}
}
}
/**
* 复制单个文件
* @param oldPath String 原文件路径 如:c:/fqf.txt
* @param newPath String 复制后路径 如:f:/fqf.txt
* @return boolean
*/
public void copyFile(String oldPath, String newPath) {
try {
int bytesum = 0;
int byteread = 0;
File oldfile = new File(oldPath);
if (oldfile.exists()) { //文件存在时
InputStream inStream = new FileInputStream(oldPath); //读入原文件
FileOutputStream fs = new FileOutputStream(newPath);
byte[] buffer = new byte[1444];
int length;
while ( (byteread = inStream.read(buffer)) != -1) {
bytesum += byteread; //字节数 文件大小
System.out.println(bytesum);
fs.write(buffer, 0, byteread);
}
inStream.close();
}
}
catch (Exception e) {
System.out.println("复制单个文件操作出错");
e.printStackTrace();
}
}
/**
* 复制整个文件夹内容
* @param oldPath String 原文件路径 如:c:/fqf
* @param newPath String 复制后路径 如:f:/fqf/ff
* @return boolean
*/
public void copyFolder(String oldPath, String newPath) {
try {
(new File(newPath)).mkdirs(); //如果文件夹不存在 则建立新文件夹
File a=new File(oldPath);
String[] file=a.list();
File temp=null;
for (int i = 0; i < file.length; i++) {
if(oldPath.endsWith(File.separator)){
temp=new File(oldPath+file[i]);
}
else{
temp=new File(oldPath+File.separator+file[i]);
}
if(temp.isFile()){
FileInputStream input = new FileInputStream(temp);
FileOutputStream output = new FileOutputStream(newPath + "/" +
(temp.getName()).toString());
byte[] b = new byte[1024 * 5];
int len;
while ( (len = input.read(b)) != -1) {
output.write(b, 0, len);
}
output.flush();
output.close();
input.close();
}
if(temp.isDirectory()){//如果是子文件夹
copyFolder(oldPath+"/"+file[i],newPath+"/"+file[i]);
}
}
}
catch (Exception e) {
System.out.println("复制整个文件夹内容操作出错");
e.printStackTrace();
}
}
/**
* 移动文件到指定目录
* @param oldPath String 如:c:/fqf.txt
* @param newPath String 如:d:/fqf.txt
*/
public void moveFile(String oldPath, String newPath) {
copyFile(oldPath, newPath);
delFile(oldPath);
}
/**
* 移动文件到指定目录
* @param oldPath String 如:c:/fqf.txt
* @param newPath String 如:d:/fqf.txt
*/
public void moveFolder(String oldPath, String newPath) {
copyFolder(oldPath, newPath);
delFolder(oldPath);
}
}
星期二, 四月 24, 2007
列表排序(转)
你能够使用java.util.Collections类中的sort()方法对List元素进行排序。你既可以给方法传递一个List对象,也可以传递一个List和一个Comparator。如果列表中的元素全都是相同类型的类,并且这个类实现了Comparable接口,你可以简单的调用Collections.sort()。如果这个类没有实现Comparator,你也可以传递一个Comparator到方法sort()中,进行排序。如果你不想使用缺省的分类顺序进行排序,你同样可以传递一个Comparator到方法sort()中来进行排序。如果列表中的元素并不都是相同类型的类,你在进行排序的时候就不是这样幸运了。除非你编写一个专用的跨类的Comparator。
排序的顺序怎么样呢?如果元素是String对象,却省的排序顺序是按照字符编码进行的,基本上是每个字符的ASCII/Unicode值。如果严格的限制在处理英文,却省的排序顺序通常是足够的,因为它首先排A-Z,然后是小写字母a-z。然而如果你处理非英文字,或者你只是想使用不同的排序顺序,这样Collections.sort()就出现了第二种变化。例如,你想使用字符串的反序进行排序。为了实现这个功能,你可以在Collections类中通过reverseOrder()来获取一个反序Comparator。然后,你将反序Comparator传递给sort()方法。换句话说,你作如下工作:
List list = ...;
Comparator comp = Collections.reverseOrder();
Collections.sort(list, comp);
如果列表包含项目:Man, man, Woman, 和woman,排序好的列表将是Man, Woman, man, woman。这里没有什么复杂的。需要注意的非常重要的一点是Collections.sort()是进行原位排序。如果你需要保留原序,需要先对原集合进行复制,在排序,就像这样:
List list = ...;
List copyOfList = new ArrayList(list);
Collections.sort(copyOfList);
这里,排好序的列表是:Man, Woman, man, woman,但是原始列表(Man, man, Woman, woman)被保留了。
到目前为止,排序是区分大小写的。你如何进行不去分大小写的排序呢?一种实现方式是象这样实现Comparator:
public static class CaseInsensitiveComparator
implements Comparator {
public int compare(Object element1,
Object element2) {
String lower1 =
element1.toString().toLowerCase();
String lower2 =
element2.toString().toLowerCase();
return lower1.compareTo(lower2);
}
}
你确实不需要手工的创建这个类。而是,你可以是用以存在的Comparator,CASE_INSENSIVTIVE_ORDER,它是在String类中定义的。
这种实现方式有一点小小的问题。Sort()算法提供稳定的排序,并保持与原有序列相同的元素。这意味着一个包含两个元素”woman”和”Woman”的列表将有不同的排序,而这种不同是根据两个元素在列表中出现的先后次序决定的。
语言的不同又会怎么样呢?java.text包提供了Collector和CollectionKey类来进行区分语言的排序。这里是例子:
注意,如果你的文本是本地语言,而不是缺省语言,你需要传递一个本地语种给getInstance()方法,就象:
public static class CollatorComparator
implements Comparator {
Collator collator = Collator.getInstance();
public int compare(Object element1,
Object element2) {
CollationKey key1 = collator.getCollationKey(
element1.toString());
CollationKey key2 = collator.getCollationKey(
element2.toString());
return key1.compareTo(key2);
}
}
你是在对集合关键字进行排序,而不是实际的字符串。这不仅提供固定的不区分大小写的排序,而且它是跨语种的排序。换句话说,如果你对西班牙文和非西班牙文的混合词进行排序,词ma?ana (tomorrow)将排在mantra的前面。如果你不使用Collector,ma?ana将排在mantra的后面。
下面这个程序对一个列表进行不同类型的排序(缺省的、区分大小写的、区分语种的):
import java.awt.BorderLayout;
import java.awt.Container;
import java.io.*;
import java.text.*;
import java.util.*;
import javax.swing.*;
public class SortIt {
public static class CollatorComparator
implements Comparator {
Collator collator = Collator.getInstance();
public int compare(Object element1,
Object element2) {
CollationKey key1 = collator.getCollationKey(
element1.toString());
CollationKey key2 = collator.getCollationKey(
element2.toString());
return key1.compareTo(key2);
}
}
public static class CaseInsensitiveComparator
implements Comparator {
public int compare(Object element1,
Object element2) {
String lower1 = element1.toString().
toLowerCase();
String lower2 = element2.toString().
toLowerCase();
return lower1.compareTo(lower2);
}
}
public static void main(String args[]) {
String words[] =
{"man", "Man", "Woman", "woman",
"Manana", "manana", "ma?ana", "Ma?ana",
"Mantra", "mantra", "mantel", "Mantel"
};
// Create frame to display sortings
JFrame frame = new JFrame("Sorting");
frame.setDefaultCloseOperation(
JFrame.EXIT_ON_CLOSE);
Container contentPane = frame.getContentPane();
JTextArea textArea = new JTextArea();
JScrollPane pane = new JScrollPane(textArea);
contentPane.add(pane, BorderLayout.CENTER);
// Create buffer for output
StringWriter buffer = new StringWriter();
PrintWriter out = new PrintWriter(buffer);
// Create initial list to sort
List list = new ArrayList(Arrays.asList(words));
out.println("Original list:");
out.println(list);
out.println();
// Perform default sort
Collections.sort(list);
out.println("Default sorting:");
out.println(list);
out.println();
// Reset list
list = new ArrayList(Arrays.asList(words));
// Perform case insensitive sort
Comparator comp = new CaseInsensitiveComparator();
Collections.sort(list, comp);
out.println("Case insensitive sorting:");
out.println(list);
out.println();
// Reset list
list = new ArrayList(Arrays.asList(words));
// Perform collation sort
comp = new CollatorComparator();
Collections.sort(list, comp);
out.println("Collator sorting:");
out.println(list);
out.println();
// Fill text area and display
textArea.setText(buffer.toString());
frame.pack();
frame.show();
}
}
如果你的主要问题是顺序访问,可能列表不是你的好的数据结构选择。只要你的集合没有重复,你可以在树(TreeSet)中保存你的元素(提供或不提供Comparator)。这样,元素将总是排序形式的。
作者Blog:http://blog.csdn.net/chensheng913/
星期一, 四月 23, 2007
Java编码规范 (转)
1. Java 命名约定
除了以下几个特例之外,命名时应始终采用完整的英文描述符。此外,一般应采用小写字母,但类名、接口名以及任何非初始单词的第一个字母要大写。
1.1 一般概念
n 尽量使用完整的英文描述符
n 采用适用于相关领域的术语
n 采用大小写混合使名字可读
n 尽量少用缩写,但如果用了,要明智地使用,且在整个工程中统一
n 避免使用长的名字(小于 15 个字母是个好主意)
n 避免使用类似的名字,或者仅仅是大小写不同的名字
n 避免使用下划线(除静态常量等)
1.2 示范
包(Package) 采用完整的英文描述符,应该都是由小写字母组成。对于全局包,将你的 Internet 域名反转并接上包名。 java.awt,com.ambysoft.www.persistence
类(Class) 采用完整的英文描述符,所有单词的第一个字母大写。 Customer, SavingsAccount
接口(Interface) 采用完整的英文描述符说明接口封装,所有单词的第一个字母大写。习惯上,名字后面加上后缀 able, ible 或者 er,但这不是必需的。 Contactable,Prompter
组件/部件(Component) 使用完整的英文描述来说明组件的用途,末端应接上组件类型。 okButton, customerList,fileMenu
异常(Exception) 通常采用字母 e 表示异常。 e
类变量 字段采用完整的英文描述,第一个字母小写,任何中间单词的首字母大写。 firstName, lastName
实参/参数 同字段/属性的命名规则 public void setFirstName(String firstName){ this.firstName = firstName;}
局部变量 同字段/属性的命名规则
获取成员函数 被访问字段名的前面加上前缀 get。 getFirstName(), getLastName()
布尔型的获取成员函数 所有的布尔型获取函数必须用单词 is 做前缀。 isPersistent(), isString()
设置成员函数 被访问字段名的前面加上前缀 set。 setFirstName(), setLastName(),setWarpSpeed()
普通成员函数 采用完整的英文描述说明成员函数功能,第一个单词尽可能采用一个生动的动词,第一个字母小写。 openFile(), addAccount()
静态常量字段(static final) 全部采用大写字母,单词之间用下划线分隔。 MIN_BALANCE, DEFAULT_DATE
循环计数器 通常采用字母 i,j,k 或者 counter 都可以接受。 i, j, k, counter
数组 数组应该总是用下面的方式来命名:objectType[]。 byte[] buffer;
2. Java 注释约定
一个很好的可遵循的有关注释的经验法则是:问问你自己,你如果从未见过这段代码,要在合理的时间内有效地明白这段代码,你需要哪些信息。
2.1. 一般概念
n 注释应该增加代码的清晰度
n 保持注释的简洁
n 在写代码之前写注释
n 注释出为什么做了一些事,而不仅仅是做了什么
2.2. 示范
文档注释 在紧靠接口、类、成员函数和字段声明的前面注释它们。 /** 客户:客户是我们将服务和产品卖给的人或机构。*/
C 语言风格 采用 C 语言风格的注释去掉不再使用但你仍想保留的代码。仍想保留是因为用户万一会改变想法,或者在调试过程中想让它暂时失效。 /* 这部分代码因为已被它之前的代码取代,由 B.Gustafsson, 于 1999 年 6 月 4 日注释掉。如果两年之后还未使用,将其删除。. . . (源代码)*/
单行 在成员函数内采用单行注释,来说明业务逻辑、代码段和暂时变量的声明。注释符"//"后必须紧跟一个空格,然后才是注释信息。 // 遵照 Sarek 的规定,给所有// 超过 $1000 的发货单// 打 5% 的折扣。让利活// 动于 1995年 2 月开始.
2.3. 注释哪些部分
类 类的目的、即类所完成的功能,注释出采用的不变量。
接口 设置接口的目的、它应如何被使用以及如何不被使用。
成员函数注释 对于设置与获取成员函数,在成员变量已有说明的情况下,可以不加注释;普通成员函数要求说明完成什么功能,参数含义是什么返回什么;
普通成员函数内部注释 控制结构,代码做了些什么以及为什么这样做,处理顺序等。
实参/参数 参数含义、及其它任何约束或前提条件
字段/属性 字段描述
局部变量 无特别意义的情况下不加注释
3. Java 文件样式约定
所有的 Java(*.java) 文件都必须遵守如下的样式规则:
1) 版权信息
版权信息必须在 java 文件的开头,比如:
/** * Copyright ? 2000 Shanghai XXX Co. Ltd. * All right reserved. */
其他不需要出现在 javadoc 的信息也可以包含在这里。
2) Package/Imports
package 行要在 import 行之前,import 中标准的包名要在本地的包名之前,而且按照字母顺序排列。如果 import 行中包含了同一个包中的不同子目录,则应该用 * 来处理。
package hotlava.net.stats;import java.io.*;import java.util.Observable;import hotlava.util.Application;
这里 java.io.* 是用来代替InputStream and OutputStream 的。
3) Class
接下来的是类的注释,一般是用来解释类的。
/** * A class representing a set of packet and byte counters * It is observable to allow it to be watched, but only * reports changes when the current set is complete */
接下来是类定义,包含了在不同的行的 extends 和 implements
public class CounterSet extends Observable implements Cloneable{……}
4) Class Fields
接下来是类的成员变量:
/** * Packet counters */protected int[] packets;
public 的成员变量必须生成文档(JavaDoc)。proceted、private和 package 定义的成员变量如果名字含义明确的话,可以没有注释。
5) 存取方法(类的设置与获取成员函数)
接下来是类变量的存取的方法。它只是简单的用来将类的变量赋值获取值的话,可以简单的写在一行上,如类的成员变量已经有注释,类变量的存取方法可以没有注释。
public int[] getPackets() { return this.packets; }public void setPackets(int[] packets) { this.packets = packets; }……
要求说明的是,对于集合,加入成员函数来插入和删除项;另其它的方法不要写在一行上。
6) 构造函数
接下来是构造函数,它应该用递增的方式写(比如:参数多的写在后面)。
public CounterSet(int size){ this.size = size;}
7) 克隆方法
如果这个类是可以被克隆的,那么下一步就是 clone 方法:
public Object clone() { try { …… }catch(CloneNotSupportedException e) { …… }}
8) 类方法 (类的普通成员函数)
下面开始写类的方法:
/** * Set the packet counters * param r1 - …… * param r2 - …… * …… */protected final void setArray(int[] r1, int[] r2, int[] r3, int[] r4) throws IllegalArgumentException{ // Ensure the arrays are of equal size ……}
9) toString 方法
一般情况下,每一个类都应该定义 toString 方法:
public String toString() { ……}
10) main 方法
普通类,考虑置入一个main()方法,其中包含用于测试那个类的代码,如果包含了main() 方法, 那么它应该写在类的底部。
4. Java编码其它约定
n 文档化
必须用 javadoc 来为类生成文档。不仅因为它是标准,这也是被各种 java 编译器都认可的方法。使用 @author 标记是不被推荐的,因为代码不应该是被个人拥有的。
n 缩进
缩进应该是每行2个空格。 不要在源文件中保存Tab字符, 在使用不同的源代码管理工具时Tab字符将因为用户设置的不同而扩展为不同的宽度。
如果你使用 UltrEdit 作为你的 Java 源代码编辑器的话,你可以通过如下操作来禁止保存Tab字符, 方法是通过 UltrEdit中先设定 Tab 使用的长度室2个空格,然后用 Format|Tabs to Spaces 菜单将 Tab 转换为空格。
n 页宽
页宽应该设置为80字符。 源代码一般不会超过这个宽度, 并导致无法完整显示, 但这一设置也可以灵活调整。 在任何情况下, 超长的语句应该在一个逗号或者一个操作符后折行。 一条语句折行后, 应该比原来的语句再缩进2个字符。
n {} 对
{} 中的语句应该单独作为一行。 例如, 下面的第1行是错误的, 第2行是正确的:
if (i>0) { i ++ }; // 错误, { 和 } 在同一行 if (i>0) { i ++ }; // 正确, 单独作为一行
n 括号
左括号和后一个字符之间不应该出现空格; 同样, 右括号和前一个字符之间也不应该出现空格。 下面的例子说明括号和空格的错误及正确使用:
CallProc( AParameter ); // 错误
CallProc(AParameter); // 正确
不要在语句中使用无意义的括号,括号只应该为达到某种目的而出现在源代码中。
n JSP文件命名
采用完整的英文描述说明JSP所完成的功能,尽可能包括一个生动的动词,第一个字母小写,如:viewMessage.jsp、editUser.jsp或者forumChooser.jsp等。
n Servlet类命名
一般对应于所服务的对象加后缀Service来命名,如:UserService,TradeService等。
5. 一些编程建议
n 使用 StringBuffer 对象
在处理 String 的时候要尽量使用 StringBuffer 类,StringBuffer 类是构成 String 类的基础。String 类将 StringBuffer 类封装了起来,(以花费更多时间为代价)为开发人员提供了一个安全的接口。当我们在构造字符串的时候,我们应该用 StringBuffer 来实现大部分的工作,当工作完成后将 StringBuffer 对象再转换为需要的 String 对象。比如:如果有一个字符串必须不断地在其后添加许多字符来完成构造,那么我们应该使用 StringBuffer 对象和它的 append() 方法。如果我们用 String 对象代替 StringBuffer 对象的话,会花费许多不必要的创建和释放对象的 CPU 时间。
n 避免太多的使用 synchronized 关键字
避免不必要的使用关键字 synchronized,应该在必要的时候再使用它,这是一个避免死锁的好方法。 必须使用时,也尽量控制范围,最好在块级控制。
n 避免使用 java.util.Vector 类
因为"Unlike the new collection implementations, Vector is synchronized.",所以使用java.util.Vector类在性能上会有所减低。
n 尽量使用接口而不是一个具体的类
比方如下需求,给定一个SQL语句,返回一个对象的列表,实现中用java.util.ArrayList实现,于是定义方法为:
public java.util.ArrayList getObjectItems(String sql)
上面的方法存在一个问题,当getObjectItems内改用Vector或LinkedList实现,外部类必须做相应更改。一个更好的方法是定义返回值为java.util.AbstractList更合适:
public java.util.AbstractList getObjectItems(String sql)
这样即使更改实现,外部类也不必做相应更改。
n 避免使用索引来调用数据库中间层组件返回的结果集
如:
for(int i=1; i<=dt.getRowCount(); i++){ String field1 = dt.getField(i, 0).toString(); ……}
而应用字段名来存取结果集:
for(int i=1; i<=dt.getRowCount(); i++){ String field1 = dt.getField(i, "field1").toString(); ……}
这样在数据库设计更改或查询的SQL语句发生变化时,不会影响到程序的执行。
注:因几次均未能联系上原创作者,故擅自专稿,如有异议,请联系本人,定及时从个人blog中删除。
星期五, 四月 20, 2007
jdbc 连接数据库
1. MySQL(http://www.mysql.com)mm.mysql-2.0.2-bin.jar
Class.forName( "org.gjt.mm.mysql.Driver" );
cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );
2. PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar
Class.forName( "org.postgresql.Driver" );
cn = DriverManager.getConnection( "jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );
3. Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip
Class.forName( "oracle.jdbc.driver.OracleDriver" );
cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd );
4. Sybase(http://jtds.sourceforge.net)jconn2.jar
Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" );
cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd );
//(Default-Username/Password: "dba"/"sql")
5. Microsoft SQLServer(http://jtds.sourceforge.net)
Class.forName( "net.sourceforge.jtds.jdbc.Driver" );
cn = DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd );
6. Microsoft SQLServer(http://www.microsoft.com)
Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" );
cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master", sUsr, sPwd );
7. ODBC
Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" );
Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );
8.DB2(新添加)
Class.forName("com.ibm.db2.jdbc.net.DB2Driver");
String url="jdbc:db2://192.9.200.108:6789/SAMPLE"
cn = DriverManager.getConnection( url, sUsr, sPwd );
9.Microsoft SQL Server series (6.5, 7.x and 2000) and Sybase 10
JDBC Name: jTDS
URL: http://jtds.sourceforge.net/
Version: 0.5.1
Download URL: http://sourceforge.net/project/showfiles.php?group_id=33291
语法:
Class.forName("net.sourceforge.jtds.jdbc.Driver ");
Connection con = DriverManager.getConnection("jdbc:jtds:sqlserver://host:port/database","user","password");
or
Connection con = DriverManager.getConnection("jdbc:jtds:sybase://host:port/database","user","password");
10.Postgresql
JDBC Name: PostgreSQL JDBC
URL: http://jdbc.postgresql.org/
Version: 7.3.3 build 110
Download URL: http://jdbc.postgresql.org/download.html
语法:
Class.forName("org.postgresql.Driver");
Connection con=DriverManager.getConnection("jdbc:postgresql://host:port/database","user","password");
11.IBM AS400主机在用的JDBC语法
有装V4R4以上版本的Client Access Express
可以在C:\Program Files\IBM\Client Access\jt400\lib
找到 driver 档案 jt400.zip,并更改扩展名成为 jt400.jar
语法:
java.sql.DriverManager.registerDriver (new com.ibm.as400.access.AS400JDBCDriver ());
Class.forName("com.ibm.as400.access.AS400JDBCConnection");
con = DriverManager.getConnection("jdbc:as400://IP","user","password");
12.informix
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url =
"jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword";
Lib:jdbcdrv.zip
Class.forName( "com.sybase.jdbc.SybDriver" )
url="jdbc:sybase:Tds:127.0.0.1:2638/asademo";
SybConnection connection= (SybConnection)DriverManager.getConnection(url,"dba","sql");
13.SAP DB
Class.forName ("com.sap.dbtech.jdbc.DriverSapDB");
java.sql.Connection connection = java.sql.DriverManager.getConnection ( "jdbc:sapdb://" + host + "/" + database_name,user_name, password)
14.InterBase
String url = "jdbc:interbase://localhost/e:/testbed/database/employee.gdb";
Class.forName("interbase.interclient.Driver");
//Driver d = new interbase.interclient.Driver (); /* this will also work if you do not want the line above */
Connection conn = DriverManager.getConnection( url, "sysdba", "masterkey" );
15.HSqlDB
url: http://hsqldb.sourceforge.net/
driver: org.hsqldb.jdbcDriver
连接方式有4种,分别为:
con-str(内存): jdbc:hsqldb.
con-str(本地): jdbc:hsqldb:/path/to/the/db/dir
con-str(http): jdbc:hsqldb:http://dbsrv
con-str(hsql): jdbc:hsqldb:hsql://dbsrv