﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-java技术-随笔分类-java 基础</title><link>http://www.blogjava.net/spark/category/15766.html</link><description>智慧是第一生产力</description><language>zh-cn</language><lastBuildDate>Thu, 21 Jan 2010 01:14:18 GMT</lastBuildDate><pubDate>Thu, 21 Jan 2010 01:14:18 GMT</pubDate><ttl>60</ttl><item><title>ftp实现上传下载，解决了编码问题。</title><link>http://www.blogjava.net/spark/archive/2010/01/19/310032.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Tue, 19 Jan 2010 01:16:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2010/01/19/310032.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/310032.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2010/01/19/310032.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/310032.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/310032.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp;&nbsp;很多人都碰到ftp的上传下载文件的实现，很容易碰到一些问题，最难解决的是乱码的问题，在网上搜索了挺多，也没人能讲得清楚详细的，这里把自己实现的程序贴出来，供大家参考。以后碰到这些问题，可以自己多看看java的API，还是很有帮助的。&nbsp;&nbsp;&nbsp;&nbsp;另外在实现ftp上传下载的时候，还要多考虑一下上传下载失败或...&nbsp;&nbsp;<a href='http://www.blogjava.net/spark/archive/2010/01/19/310032.html'>阅读全文</a><img src ="http://www.blogjava.net/spark/aggbug/310032.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2010-01-19 09:16 <a href="http://www.blogjava.net/spark/archive/2010/01/19/310032.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 实现ftp上传下载(转)</title><link>http://www.blogjava.net/spark/archive/2009/09/22/295975.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Tue, 22 Sep 2009 03:02:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2009/09/22/295975.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/295975.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2009/09/22/295975.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/295975.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/295975.html</trackback:ping><description><![CDATA[<table style="width: 820px; height: 7137px; background-color: #f8fff0" cellspacing="2" cellpadding="2" width="820" border="0">
    <tbody>
        <tr>
            <td>
            <p>package com.why.ftp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.io.DataInputStream;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.io.File;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.io.FileInputStream;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.io.FileOutputStream;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.io.IOException;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.io.OutputStream;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.util.ArrayList;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.util.List;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import java.util.StringTokenizer;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import sun.net.TelnetInputStream;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import sun.net.TelnetOutputStream;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            import sun.net.ftp.FtpClient;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;* ftp上传，下载&nbsp;&nbsp;&nbsp; <br />
            &nbsp;* @author why 2009-07-30&nbsp;&nbsp;&nbsp; <br />
            &nbsp;*&nbsp;&nbsp;&nbsp; <br />
            &nbsp;*/&nbsp;&nbsp;&nbsp;&nbsp; <br />
            public class FtpUtil {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; private String ip = "";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; private String username = "";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; private String password = "";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; private int port = -1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; private String path = "";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; FtpClient ftpClient = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; OutputStream os = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; FileInputStream is = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public FtpUtil(String serverIP, String username, String password) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ip = serverIP;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.username = username;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.password = password;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public FtpUtil(String serverIP, int port, String username, String password) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ip = serverIP;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.username = username;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.password = password;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.port = port;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * 连接ftp服务器&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @throws IOException&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public boolean connectServer(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient = new FtpClient();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(this.port != -1){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.openServer(this.ip,this.port);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.openServer(this.ip);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.login(this.username, this.password);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.path.length() != 0){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.cd(this.path);// path是ftp服务下主目录的子目录&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.binary();// 用2进制上传、下载&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("已登录到\"" + ftpClient.pwd() + "\"目录");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch (IOException e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * 断开与ftp服务器连接&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @throws IOException&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public boolean closeServer(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (is != null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (os != null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ftpClient != null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.closeServer();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("已从服务器断开");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(IOException e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * 检查文件夹在当前目录下是否存在&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @param dir&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; private boolean isDirExist(String dir){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String pwd = "";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pwd = ftpClient.pwd();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.cd(dir);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.cd(pwd);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * 在当前目录下创建文件夹&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @param dir&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @throws Exception&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; private boolean createDir(String dir){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.ascii();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringTokenizer s = new StringTokenizer(dir, "/"); //sign&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s.countTokens();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String pathName = ftpClient.pwd();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(s.hasMoreElements()){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pathName = pathName + "/" + (String) s.nextElement();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.sendServer("MKD " + pathName + "\r\n");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception e) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.readServerResponse();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.binary();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch (IOException e1){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e1.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * ftp上传&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 如果服务器段已存在名为filename的文件夹，该文件夹中与要上传的文件夹中同名的文件将被替换&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param filename 要上传的文件（或文件夹）名&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @throws Exception&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public boolean upload(String filename){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String newname = "";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(filename.indexOf("/") &gt; -1){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newname = filename.substring(filename.lastIndexOf("/") + 1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newname = filename;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return upload(filename, newname);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * ftp上传&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 如果服务器段已存在名为newName的文件夹，该文件夹中与要上传的文件夹中同名的文件将被替换&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param fileName 要上传的文件（或文件夹）名&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param newName 服务器段要生成的文件（或文件夹）名&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; public boolean upload(String fileName, String newName){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String savefilename = new String(fileName.getBytes("ISO-8859-1"), "GBK");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File file_in = new File(savefilename);//打开本地待长传的文件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!file_in.exists()){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception("此文件或文件夹[" + file_in.getName() + "]有误或不存在!");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(file_in.isDirectory()){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; upload(file_in.getPath(),newName,ftpClient.pwd());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uploadFile(file_in.getPath(),newName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(is != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(os != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(Exception e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.err.println("Exception e in Ftp upload(): " + e.toString());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }finally{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(is != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(os != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch(IOException e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * 真正用于上传的方法&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param fileName&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param newName&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @param path&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; * @throws Exception&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; private void upload(String fileName, String newName,String path) throws Exception{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String savefilename = new String(fileName.getBytes("ISO-8859-1"), "GBK");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File file_in = new File(savefilename);//打开本地待长传的文件&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!file_in.exists()){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception("此文件或文件夹[" + file_in.getName() + "]有误或不存在!");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(file_in.isDirectory()){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!isDirExist(newName)){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; createDir(newName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.cd(newName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File sourceFile[] = file_in.listFiles();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; sourceFile.length; i++){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!sourceFile[i].exists()){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(sourceFile[i].isDirectory()){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.upload(sourceFile[i].getPath(),sourceFile[i].getName(),path+"/"+newName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.uploadFile(sourceFile[i].getPath(),sourceFile[i].getName());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; uploadFile(file_in.getPath(),newName);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpClient.cd(path);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; *&nbsp; upload 上传文件&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @param filename 要上传的文件名&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @param newname 上传后的新文件名&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @return -1 文件不存在 &gt;=0 成功上传，返回文件的大小&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @throws Exception&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public long uploadFile(String filename, String newname) throws Exception{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long result = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TelnetOutputStream os = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileInputStream is = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.io.File file_in = new java.io.File(filename);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!file_in.exists())&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os = ftpClient.put(newname);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = file_in.length();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is = new FileInputStream(file_in);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] bytes = new byte[1024];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int c;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((c = is.read(bytes)) != -1){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.write(bytes, 0, c);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }finally{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(is != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(os != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * 从ftp下载文件到本地&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @param filename 服务器上的文件名&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @param newfilename 本地生成的文件名&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @throws Exception&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public long downloadFile(String filename, String newfilename){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long result = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TelnetInputStream is = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FileOutputStream os = null;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is = ftpClient.get(filename);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; java.io.File outfile = new java.io.File(newfilename);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os = new FileOutputStream(outfile);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] bytes = new byte[1024];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int c;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while ((c = is.read(bytes)) != -1) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.write(bytes, 0, c);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result = result + c;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch (IOException e){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }finally{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(is != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; is.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(os != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; os.close();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (IOException e) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * 取得相对于当前连接目录的某个目录下所有文件列表&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; *&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @param path&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; * @return&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public List getFileList(String path){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List list = new ArrayList();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataInputStream dis;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dis = new DataInputStream(ftpClient.nameList(this.path + path));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String filename = "";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((filename = dis.readLine()) != null){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list.add(filename);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (IOException e) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.printStackTrace();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return list;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; public static void main(String[] args){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FtpUtil ftp = new FtpUtil("133.224.202.2","tstbill","tstbill");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftp.connectServer();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean result = ftp.upload("C:/test_why", "test_why/test");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(result?"上传成功！":"上传失败！");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; List list = ftp.getFileList("test_why/test");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;list.size();i++){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String name = list.get(i).toString();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(name);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftp.closeServer();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FTP远程命令列表&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; USER&nbsp;&nbsp;&nbsp; PORT&nbsp;&nbsp;&nbsp; RETR&nbsp;&nbsp;&nbsp; ALLO&nbsp;&nbsp;&nbsp; DELE&nbsp;&nbsp;&nbsp; SITE&nbsp;&nbsp;&nbsp; XMKD&nbsp;&nbsp;&nbsp; CDUP&nbsp;&nbsp;&nbsp; FEAT&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PASS&nbsp;&nbsp;&nbsp; PASV&nbsp;&nbsp;&nbsp; STOR&nbsp;&nbsp;&nbsp; REST&nbsp;&nbsp;&nbsp; CWD&nbsp;&nbsp;&nbsp;&nbsp; STAT&nbsp;&nbsp;&nbsp; RMD&nbsp;&nbsp;&nbsp;&nbsp; XCUP&nbsp;&nbsp;&nbsp; OPTS&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ACCT&nbsp;&nbsp;&nbsp; TYPE&nbsp;&nbsp;&nbsp; APPE&nbsp;&nbsp;&nbsp; RNFR&nbsp;&nbsp;&nbsp; XCWD&nbsp;&nbsp;&nbsp; HELP&nbsp;&nbsp;&nbsp; XRMD&nbsp;&nbsp;&nbsp; STOU&nbsp;&nbsp;&nbsp; AUTH&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; REIN&nbsp;&nbsp;&nbsp; STRU&nbsp;&nbsp;&nbsp; SMNT&nbsp;&nbsp;&nbsp; RNTO&nbsp;&nbsp;&nbsp; LIST&nbsp;&nbsp;&nbsp; NOOP&nbsp;&nbsp;&nbsp; PWD&nbsp;&nbsp;&nbsp;&nbsp; SIZE&nbsp;&nbsp;&nbsp; PBSZ&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; QUIT&nbsp;&nbsp;&nbsp; MODE&nbsp;&nbsp;&nbsp; SYST&nbsp;&nbsp;&nbsp; ABOR&nbsp;&nbsp;&nbsp; NLST&nbsp;&nbsp;&nbsp; MKD&nbsp;&nbsp;&nbsp;&nbsp; XPWD&nbsp;&nbsp;&nbsp; MDTM&nbsp;&nbsp;&nbsp; PROT&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在服务器上执行命令,如果用sendServer来执行远程命令(不能执行本地FTP命令)的话，所有FTP命令都要加上\r\n&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpclient.sendServer("XMKD /test/bb\r\n"); //执行服务器上的FTP命令&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ftpclient.readServerResponse一定要在sendServer后调用&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nameList("/test")获取指目录下的文件列表&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XMKD建立目录，当目录存在的情况下再次创建目录时报错&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; XRMD删除目录&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DELE删除文件&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; */&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp; <br />
            }&nbsp;&nbsp;</p>
            </td>
        </tr>
    </tbody>
</table>
<br />
<p>下面是FtpClient类的一些介绍：</p>
<p>sun.net.ftp.FtpClient.，该类库主要提供了用于建立FTP连接的类。利用这些类的方法，编程人员可以远程登录到FTP服务器，列举该服务器上的目录，设置传输协议，以及传送文件。FtpClient类涵盖了几乎所有FTP的功能，FtpClient的实例变量保存了有关建立"代理"的各种信息。下面给出了这些实例变量：</p>
<p>　　public static boolean useFtpProxy<br />
　　这个变量用于表明FTP传输过程中是否使用了一个代理，因此，它实际上是一个标记，此标记若为TRUE，表明使用了一个代理主机。</p>
<p>　　public static String ftpProxyHost<br />
　　此变量只有在变量useFtpProxy为TRUE时才有效，用于保存代理主机名。</p>
<p>　　public static int ftpProxyPort<br />
　　此变量只有在变量useFtpProxy为TRUE时才有效，用于保存代理主机的端口地址。</p>
<p>　　FtpClient有三种不同形式的构造函数，如下所示：</p>
<p>　　1、public FtpClient(String hostname,int port)<br />
　　　此构造函数利用给出的主机名和端口号建立一条FTP连接。</p>
<p>　　2、public FtpClient(String hostname)<br />
　　此构造函数利用给出的主机名建立一条FTP连接，使用默认端口号。</p>
<p>　　3、FtpClient()<br />
　　此构造函数将创建一FtpClient类，但不建立FTP连接。这时，FTP连接可以用openServer方法建立。</p>
<p>　　一旦建立了类FtpClient，就可以用这个类的方法来打开与FTP服务器的连接。类ftpClient提供了如下两个可用于打开与FTP服务器之间的连接的方法。</p>
<p>　　public void openServer(String hostname)<br />
　　这个方法用于建立一条与指定主机上的FTP服务器的连接，使用默认端口号。</p>
<p>　　public void openServer(String host,int port)<br />
　　这个方法用于建立一条与指定主机、指定端口上的FTP服务器的连接。</p>
<p>　　打开连接之后，接下来的工作是注册到FTP服务器。这时需要利用下面的方法。</p>
<p>　　public void login(String username，String password)<br />
　　此方法利用参数username和password登录到FTP服务器。使用过Intemet的用户应该知道，匿名FTP服务器的登录用户名为anonymous，密码一般用自己的电子邮件地址。</p>
<p>　　下面是FtpClient类所提供的一些控制命令。</p>
<p>　　public void cd(String remoteDirectory)：该命令用于把远程系统上的目录切换到参数remoteDirectory所指定的目录。<br />
　　public void cdUp()：该命令用于把远程系统上的目录切换到上一级目录。<br />
　　public String pwd()：该命令可显示远程系统上的目录状态。<br />
　　public void binary()：该命令可把传输格式设置为二进制格式。<br />
　　public void ascii()：该命令可把传输协议设置为ASCII码格式。<br />
　　public void rename(String string，String string1)：该命令可对远程系统上的目录或者文件进行重命名操作。</p>
<p>　　除了上述方法外，类FtpClient还提供了可用于传递并检索目录清单和文件的若干方法。这些方法返回的是可供读或写的输入、输出流。下面是其中一些主要的方法。</p>
<p>　　public TelnetInputStream list()<br />
　　返回与远程机器上当前目录相对应的输入流。</p>
<p>　　public TelnetInputStream get(String filename)<br />
　　获取远程机器上的文件filename，借助TelnetInputStream把该文件传送到本地。</p>
<p>　　public TelnetOutputStream put(String filename)<br />
　　以写方式打开一输出流，通过这一输出流把文件filename传送到远程计算机</p>
<img src ="http://www.blogjava.net/spark/aggbug/295975.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2009-09-22 11:02 <a href="http://www.blogjava.net/spark/archive/2009/09/22/295975.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>javax.naming.NameNotFoundException: Name jdbc is not bound in this Context</title><link>http://www.blogjava.net/spark/archive/2009/09/08/294339.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Tue, 08 Sep 2009 09:47:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2009/09/08/294339.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/294339.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2009/09/08/294339.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/294339.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/294339.html</trackback:ping><description><![CDATA[在tomcat中发布web项目，可能是因为spring中配置了jndi（只配置了jndi，其他的有工具包封装了）。<br />
启动的时候报错（在项目目录下，在tomcat中配置context指向项目目录就没问题，打包发布到<br />
tomcat就报错了），抛的异常是：<br />
javax.naming.NameNotFoundException: Name jdbc is not bound in this Context<br />
<br />
在web.xml中添加配置如下：<br />
&lt;resource-ref&gt;<br />
&nbsp;&nbsp;&lt;description&gt;DB Connection&lt;/description&gt;<br />
&nbsp;&nbsp;&lt;res-ref-name&gt;jdbc/test&lt;/res-ref-name&gt;<br />
&nbsp;&nbsp;&lt;res-type&gt;javax.sql.DataSource&lt;/res-type&gt;<br />
&nbsp;&nbsp;&lt;res-auth&gt;Container&lt;/res-auth&gt;<br />
&nbsp;&lt;/resource-ref&gt;<br />
<img src ="http://www.blogjava.net/spark/aggbug/294339.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2009-09-08 17:47 <a href="http://www.blogjava.net/spark/archive/2009/09/08/294339.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java web应用程序转exe</title><link>http://www.blogjava.net/spark/archive/2009/05/21/274556.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Thu, 21 May 2009 14:28:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2009/05/21/274556.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/274556.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2009/05/21/274556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/274556.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/274556.html</trackback:ping><description><![CDATA[<p>&nbsp; 最近做了一个小的web应用，客户那边都不常用java环境，让他们安装、配置java、tomcat环境对他们来说太难为他们了，<br />
所以花了点时间研究了下exe文件的制作，将java web应用制作成exe文件，并打包了jre环境，最后生成启动服务器的快捷方式、<br />
打开IE的快捷方式，感觉这样就成了傻瓜型的了，^!^ 由于上网找资料花了不少时间，想着方便那些有类似需要的朋友，就<br />
在此总结一下，希望能帮助到别人吧。<br />
<br />
&nbsp; 在一个没有java环境的系统中(此处只应用于windows)，要执行web应用，需要jdk、tomcat（服务器），我是将机器上装的jdk目录、<br />
tomcat目录拷贝到一个目录，还有数据库客户端，这里用的hsql，就不详细说了。这里主要注意的问题主要就是环境变量的设置，<br />
在tomcat\bin目录中我们需要设置java_home和CATALINA_HOME，设置方法如下：<br />
打开tomcat\bin\startup.bat,对其中if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHome这样的语句都移动到下面代码的后面：<br />
set CURRENT_DIR=%cd%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #3366ff">&nbsp;注释</span>：取得当前目录tomcat\bin<br />
set CATALINA_HOME=%CURRENT_DIR%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
cd ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注释：到上一级目录tomcat&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
set CATALINA_HOME=%cd%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
cd ..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注释：到上一级目录delply<br />
set JAVA_HOME=%cd%\jdk&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注释：设置JAVA_HOME<br />
set JRE_HOME=%cd%\jdk\jre&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注释：设置JRE_HOME<br />
<span style="color: #ff0000">其实这里的关键就是不使用以前的判断，直接设置CATALINA_HOME、JAVA_HOME等到你打包的目录<br />
</span>注意我的目录结构如下，大家可根据需要适当调整上面的代码：<br />
deploy<br />
-------&gt;tomcat<br />
-------&gt;jdk<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;再一点就是NSIS的使用，可以使用它提供的VNISEdit编译环境中的 新建脚本：向导进行配置，其中要注意的问题是<br />
1. 选择目录的时候，设置的是目录下的内容，不包括目录；<br />
2. 通过向导配置的快捷方式有点问题，需要手工改动编码，主要是下面的内容：<br />
Section "<span style="color: #0000ff">yourapp</span>" SEC01<br />
&nbsp; SetOutPath "$INSTDIR"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">&nbsp;(这里是你的根目录，我这里是deploy)<br />
</span>&nbsp; SetOverwrite ifnewer<br />
<span style="color: #0000ff">&nbsp; File /r "..\deploy\*.*"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (注意这里的格式)<br />
</span>SectionEnd<br />
<br />
Section -AdditionalIcons<br />
<span style="color: #0000ff">&nbsp; SetOutPath "$INSTDIR\tomcat\bin"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (这里是你快捷方式的起始位置，即快捷方式指向的那个文件的目录，前面设置的是根目录，这里需要重新设置，如果在前面设置的话，你的根目录就变成了你的快捷方式指向的那个文件的目录了，一定要注意这里的问题)<br />
</span>&nbsp; CreateDirectory "$SMPROGRAMS\IBS"<br />
&nbsp; CreateShortCut "$desktop\StartServer.lnk"<span style="color: #0000ff">&nbsp;"$INSTDIR\tomcat\bin\startup.bat" "" "$INSTDIR\tomcat\start-server.ico"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;（我这里是把tomcat里的startup.bat建立了桌面快捷方式，后面是我设置的图标）<br />
</span>&nbsp; CreateShortCut "$desktop\StartIBS.lnk" <span style="color: #0000ff">"http://localhost:9000/appname" "" "$INSTDIR\tomcat\app_ie.ico"&nbsp; （这里是我建立的桌面快捷方式，点击就打开的是我制定的网址）<br />
</span>&nbsp; CreateShortCut "$SMPROGRAMS\IBS\Uninstall.lnk" "$INSTDIR\uninst.exe"<br />
SectionEnd<br />
<br />
总结上面的内容，就是我们在打包java web系统时，主要是把tomcat、jdk放到一个目录下，使用NSIS工具将其压缩即可，需要注意的就是两点，一是tomcat中<br />
对CATALINA_HOME、java_home的设置，二就是nsis脚本中的目录设置、快捷方式的设置了。。</p>
<img src ="http://www.blogjava.net/spark/aggbug/274556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2009-05-21 22:28 <a href="http://www.blogjava.net/spark/archive/2009/05/21/274556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA新手学习指南[转]</title><link>http://www.blogjava.net/spark/archive/2009/02/10/254094.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Tue, 10 Feb 2009 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2009/02/10/254094.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/254094.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2009/02/10/254094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/254094.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/254094.html</trackback:ping><description><![CDATA[<span class="oblog_text">每个人的学习方法是不同的，一个人的方法不见得适合另一个人，我只能是谈自己的学习方法。因为我学习Java是完全自学的，从来没有问过别人，所以学习的过程基本上完全是自己摸索出来的。我也不知道这种方法是否是比较好的方法，只能给大家提供一点参考了。 <br />
<br />
学习Java的第一步是安装好JDK，写一个Hello World， 其实JDK的学习没有那么简单，关于JDK有两个问题是很容易一直困扰 Java程序员的地方：一个是CLASSPATH的问题，其实从原理上来说，是要搞清楚JRE的ClassLoader是如何加载Class的；另一个问题是package和import问题，如何来寻找类的路径问题。把这两个问题摸索清楚了，就扫除了学习Java和使用JDK的最大障碍。推荐看一下王森的《Java深度历险》，对这两个问题进行了深入的探讨。 <br />
<br />
第二步是学习Java的语法。Java的语法是类C++的，基本上主流的编程语言不是类C，就是类C++的，没有什么新东西，所以语法的学习，大概就是半天的时间足够了。唯一需要注意的是有几个不容易搞清楚的关键字的用法，public，protected，private，static，什么时候用，为什么要用，怎么用，这可能需要有人来指点一下，我当初是完全自己琢磨出来的，花了很久的时间。不过后来我看到《Thinking in Java》这本书上面是讲了这些概念的。 <br />
<br />
第三步是学习Java的面向对象的编程语言的特性的地方。比如继承，构造器，抽象类，接口，方法的多态，重载，覆盖，Java的异常处理机制。对于一个没有面向对象语言背景的人来说，我觉得这个过程需要花很长很长时间，因为学习Java之前没有C++的经验，只有C的经验，我是大概花了一个月左右吧，才彻底把这些概念都搞清楚，把书上面的例子反复的揣摩，修改，尝试，把那几章内容反复的看过来，看过去，看了不下5遍，才彻底领悟了。不过我想如果有 C++经验的话，应该一两天时间足够了。那么在这个过程中，可以多看看《Thinking in Java》这本书，对面向对象的讲解非常透彻。可惜的是我学习的时候，并没有看到这本书，所以自己花了大量的时间，通过自己的尝试和揣摩来学会的。 <br />
<br />
第四步就是开始熟悉Java的类库。Java的基础类库其实就是JDK安装目录下面jre\lib\rt.jar这个包。学习基础类库就是学习rt.jar。基础类库里面的类非常非常多。据说有3000多个，我没有统计过。但是真正对于我们来说最核心的只有4个，分别是 <br />
java.lang.*; <br />
java.io.*; <br />
java.util.*; <br />
java.sql.*; <br />
<br />
这四个包的学习，每个包的学习都可以写成一本厚厚的教材，而O'reilly也确实是这样做的。我觉得如果时间比较紧，是不可能通过读四本书来学习。我觉得比较好的学习方法是这样的： <br />
首先要通读整个package的框架，了解整个package的class，interface，exception的构成，最好是能够找到介绍整个包框架的文章。这些专门介绍包的书籍的前几章应该就是这些总体的框架内容介绍。 <br />
<br />
对包整体框架的把握并不是要熟悉每个类的用法，记住它有哪些属性，方法。想记也记不住的。而是要知道包有哪些方面的类构成的，这些类的用途是什么，最核心的几个类分别是完成什么功能的。我在给人培训的时候一般是一次课讲一个包，所以不可能详细的介绍每个类的用法，但是我反复强调，我给你们讲这些包的不是要告诉你们类的方法是怎么调用的，也不要求你们记住类的方法调用，而是要你们了解，Java给我们提供了哪些类，每个类是用在什么场合，当我遇到问题的时候，我知道哪个类，或者哪几个类的组合可以解决我的问题，That'all！，当我们具体写程序的时候，只要你知道该用哪个类来完成你的工作就足够了。编码的时候，具体的方法调用，是边写代码，边查Documentation，所有的东西都在Documentation里面，不要求你一定记住，实际你也记不住3000多个类的总共将近10万个方法调用。所以对每个包的总体框架的把握就变得极为重要。 <br />
<br />
第五步，通过上面的学习，如果学的比较扎实的话，就打好了Java的基础了，剩下要做的工作是扫清Documentation里面除了上面4个包之外的其他一些比较有用处的类。相信进展到这一步，Java的自学能力已经被培养出来了，可以到了直接学习Documentation的水平了。除了要做 GUI编程之外，JDK里面其他会有用处的包是这些： <br />
java.text.*; <br />
java.net.*; <br />
javax.naming.*; <br />
这些包里面真正用的比较多的类其实很少，只有几个，所以不需要花很多时间。 <br />
<br />
第六步，Java Web 编程 <br />
Web编程的核心是HTTP协议，HTTP协议和Java无关，如果不熟悉HTTP协议的话，虽然也可以学好Servlet/JSP编程，但是达不到举一反三，一通百通的境界。所以HTTP协议的学习是必备的。如果熟悉了HTTP协议的话，又有了Java编程的良好的基础，学习 Servlet/JSP简直易如反掌，我学习Servlet/JSP就用了不到一周的时间，然后就开始用JSP来做项目了。 <br />
<br />
在Servlet/JSP的学习中，重头仍然是Servlet Documentation。Servlet API最常用的类很少，花比较少的时间就可以掌握了。把这些类都看一遍，多写几个例子试试。Servlet/JSP编程本质就是在反复调用这些类来通过HTTP协议在Web Server 和Brower之间交谈。另外对JSP，还需要熟悉几个常用JSP的标记，具体的写法记不住的话，临时查就是了。 <br />
<br />
此外Java Web编程学习的重点要放在Web Application的设计模式上，如何进行业务逻辑的分析，并且进行合理的设计，按照 MVC设计模式的要求，运用Servlet和JSP分别完成不同的逻辑层，掌握如何在Servlet和JSP之间进行流程的控制和数据的共享，以及 Web Application应该如何配置和部署。 <br />
<br />
第七步，J2EE编程 <br />
以上的学习过程如果是比较顺利的话，进行到这一步，难度又陡然提高。因为上面的知识内容都是只涉及一个方面，而像EJB，JMS，JTA等核心的J2EE规范往往是几种Java技术的综合运用的结晶，所以掌握起来难度比较大。 <br />
<br />
首先一定要学习好JNDI，JNDI是App Server定位服务器资源（EJB组件，Datasouce，JMS）查找方法，如果对JNDI 不熟悉的话，EJB，JMS这些东西几乎学不下去。JNDI其实就是javax.naming.*这个包，运用起来很简单。难点在于服务器资源文件的配置。对于服务器资源文件的配置，就需要看看专门的文档规范了，比如web.xml的写法，ejb-jar.xml的写法等等。针对每种不同的 App Server，还有自己的服务资源配置文件，也是需要熟悉的。 <br />
<br />
然后可以学习JTA，主要是要理解JTA对于事务的控制的方法，以及该在什么场合使用JTA。这里可以简单的举个例子，我们知道一般情况可以对于一个数据库连接进行事务控制(conn.setAutoCommit(false),....,conn.commit())，做为一个原子操作，但是假设我的业务需求是要把对两个不同数据库的操作做为一个原子操作，你能做的到吗？这时候只能用JTA了。假设操作过程是先往A数据库插一条记录，然后删除B 数据库另一个记录，我们自己写代码是控制不了把整个操作做为一个原子操作的。用JTA的话，由App Server来完成控制。 <br />
<br />
在学习EJB之前要学习对象序列化和RMI，RMI是EJB的基础。接着学习JMS和EJB，对于EJB来说，最关键是要理解EJB是如何通过RMI来实现对远端对象的调用的，以及在什么情况下要用到EJB。 <br />
<br />
在学习完EJB，JMS这些东西之后，你可能会意识到要急不可待学习两个领域的知识，一个是UML，另一个是Design Pattern。 Java企业软件的设计非常重视框架(Framework)的设计，一个好的软件框架是软件开发成功的必要条件。在这个时候，应该开始把学习的重点放在设计模式和框架的学习上，通过学习和实际的编程经验来掌握EJB的设计模式和J2EE的核心模式。 <br />
<br />
J2EE规范里面，除了EJB，JMS，JTA，Servlet/JSP，JDBC之外还有很多很多的企业技术，这里不一一进行介绍了。 <br />
<br />
另外还有一个最新领域Web Services。Web Services也完全没有任何新东西，它像是一种黏合剂，可以把不同的服务统一起来提供一个统一的调用接口，作为使用者来说，我只要获得服务提供者给我的WSDL（对服务的描述），就够了，我完全不知道服务器提供者提供的服务究竟是EJB 组件，还是.Net组件，还是什么CORBA组件，还是其他的什么实现，我也不需要知道。Web Services最伟大的地方就在于通过统一的服务提供方式和调用方式，实现了整个Internet服务的共享，是一个非常令人激动的技术领域。Web Services好像目前还没有什么很好的书籍，但是可以通过在网络上面查资料的方式来学习。</span>
<img src ="http://www.blogjava.net/spark/aggbug/254094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2009-02-10 15:35 <a href="http://www.blogjava.net/spark/archive/2009/02/10/254094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle中的数据锁定机制全面解析</title><link>http://www.blogjava.net/spark/archive/2007/07/10/129288.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Tue, 10 Jul 2007 03:12:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2007/07/10/129288.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/129288.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2007/07/10/129288.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/129288.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/129288.html</trackback:ping><description><![CDATA[为了得到最大的性能，一般数据库都有并发机制，不过带来的问题就是数据访问的冲突。为了解决这个问题，大多数数据库用的方法就是数据的锁定。
<div id=pip><iframe marginWidth=0 marginHeight=0 src="http://www.techtarget.com.cn/ttfiles/ttimages/cmsflash/database_pip.html" frameBorder=0 width=300 scrolling=no height=250 BORDERCOLOR="#000"></iframe></div>
<div class=guanggao><span id=contentAdv></span></div>
<p>　　为了得到最大的性能，一般数据库都有并发机制，不过带来的问题就是数据访问的冲突。为了解决这个问题，大多数数据库用的方法就是数据的锁定。</p>
<p>　　数据的锁定分为两种方法，第一种叫做悲观锁，第二种叫做乐观锁。什么叫悲观锁呢，悲观锁顾名思义，就是对数据的冲突采取一种悲观的态度，也就是说假设数据肯定会冲突，所以在数据开始读取的时候就把数据锁定住。而乐观锁就是认为数据一般情况下不会造成冲突，所以在数据进行提交更新的时候，才会正式对数据的冲突与否进行检测，如果发现冲突了，则让用户返回错误的信息，让用户决定如何去做。</p>
<p>　　先从悲观锁开始说。在SqlServer等其余很多数据库中，数据的锁定通常采用页级锁的方式，也就是说对一张表内的数据是一种串行化的更新插入机制，在任何时间同一张表只会插1条数据，别的想插入的数据要等到这一条数据插完以后才能依次插入。带来的后果就是性能的降低，在多用户并发访问的时候，当对一张表进行频繁操作时，会发现响应效率很低，数据库经常处于一种假死状态。而Oracle用的是行级锁，只是对想锁定的数据才进行锁定，其余的数据不相干，所以在对Oracle表中并发插数据的时候，基本上不会有任何影响。</p>
<p>　　Oracle的悲观锁需要利用一条现有的连接，分成两种方式，从SQL语句的区别来看，就是一种是for update，一种是for update nowait的形式。比如我们看一个例子。首先建立测试用的数据库表。</p>
<p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3><font face=Verdana>CREATE TABLE TEST<br>(ID,<br>NAME,<br>LOCATION,<br>VALUE,<br>CONSTRAINT test_pk PRIMARY KEY(ID))<br>AS SELECT deptno, dname, loc, 1 FROM scott.dept</font></td>
        </tr>
    </tbody>
</table>
</p>
<p>　　这里我们利用了Oracle的Sample的scott用户的表，把数据copy到我们的test表中。首先我们看一下for update锁定方式。首先我们执行如下的select for update语句。</p>
<p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>select * from test where id = 10 for update</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　通过这条检索语句锁定以后，再开另外一个sql*plus窗口进行操作，再把上面这条sql语句执行一便，你会发现sqlplus好像死在那里了，好像检索不到数据的样子，但是也不返回任何结果，就属于卡在那里的感觉。这个时候是什么原因呢，就是一开始的第一个Session中的select for update语句把数据锁定住了。由于这里锁定的机制是wait的状态(只要不表示nowait那就是wait)，所以第二个Session(也就是卡住的那个sql*plus)中当前这个检索就处于等待状态。当第一个session最后commit或者rollback之后，第二个session中的检索结果就是自动跳出来，并且也把数据锁定住。不过如果你第二个session中你的检索语句如下所示。</p>
<p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>select * from test where id = 10</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　也就是没有for update这种锁定数据的语句的话，就不会造成阻塞了。另外一种情况，就是当数据库数据被锁定的时候，也就是执行刚才for update那条sql以后，我们在另外一个session中执行for update nowait后又是什么样呢。比如如下的sql语句。 由于这条语句中是制定采用nowait方式来进行检索，所以当发现数据被别的session锁定中的时候，就会迅速返回ORA-00054错误，内容是资源正忙, 但指定以 NOWAIT 方式获取资源。所以在程序中我们可以采用nowait方式迅速判断当前数据是否被锁定中，如果锁定中的话，就要采取相应的业务措施进行处理。</p>
<p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>select * from test where id = 10 for update nowait</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　那这里另外一个问题，就是当我们锁定住数据的时候，我们对数据进行更新和删除的话会是什么样呢。比如同样，我们让第一个Session锁定住id=10的那条数据，我们在第二个session中执行如下语句</p>
<p>
<table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellSpacing=0 cellPadding=6 width="95%" align=center border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" bgColor=#f3f3f3>update test set value=2 where id = 10</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　这个时候我们发现update语句就好像select for update语句一样也停住卡在这里，当你第一个session放开锁定以后update才能正常运行。当你update运行后，数据又被你update语句锁定住了，这个时候只要你update后还没有commit，别的session照样不能对数据进行锁定更新等等。</p>
<img src ="http://www.blogjava.net/spark/aggbug/129288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2007-07-10 11:12 <a href="http://www.blogjava.net/spark/archive/2007/07/10/129288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>控制texterea长度，并显示剩余字数；附：Javascript中的trim和replace函数</title><link>http://www.blogjava.net/spark/archive/2006/11/22/82751.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Wed, 22 Nov 2006 05:54:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/11/22/82751.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/82751.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/11/22/82751.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/82751.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/82751.html</trackback:ping><description><![CDATA[
		<p>
				<font color="#0000ff">控制texterea长度，并显示剩余字数，只能在IE上运行</font>
		</p>
		<p>&lt;script&gt;<br />function checklen(obj){<br />  var lenE = obj.value.length;<br />  var lenC = 0;<br />  var CJK = obj.value.match(/[u4E00-u9FA5uF900-uFA2D]/g);<br />  if (CJK != null) lenC += CJK.length;<br />    tno.innerText = obj.maxlength - lenC - lenE ;<br />    if (tno.innerText &lt; 0) {<br />      var tmp = 0<br />      var cut = obj.value.substring(0, obj.maxlength);<br />      for (var i=0; i&lt;cut.length; i++){<br />      tmp += /[u4E00-u9FA5uF900-uFA2D]/.test(cut.charAt(i)) ? 2 : 1;<br />      if (tmp &gt; obj.maxlength) break;<br />    }<br />    obj.value = cut.substring(0, i);<br />  }<br />}<br />&lt;/script&gt;<br />&lt;body onload="tno.innerText = s1.maxlength;"&gt;<br />&lt;textarea name="s1" rows="5" cols="50" maxlength="100" onpropertychange="checklen(this)"&gt;&lt;/textarea&gt;<br />剩余&lt;span id="tno"&gt;&lt;/span&gt;个字符 </p>
		<div>附：Javascript中的trim和replace函数===============<br />//triml();<br />triml = function () {<br />  for (var i = 0; i &lt; this.length; i++) {<br />    if (this.charcodeat (i) &gt; 32) {<br />      return this.substr (i, this.length);<br />    }<br />  }<br />  return this;<br />}<br /> <br />//trimr();<br />trimr = function () {<br />  for (var i = this.length; i &gt; 0; i--) {<br />    if (this.charcodeat (i) &gt; 32) {<br />    return this.substring (0, i + 1);<br />    }<br />  }<br />  return this;<br />}<br /> <br />//trimwhite();<br />trimwhite = function() {<br />  this = this.triml ();<br />  return this.trimr ();<br />}<br /> <br />//replace();<br />function replace():string {<br />  var str:string = string(arguments[0]);<br />  var re_str:string = string(arguments[1]);<br />  var new_str:string = string(arguments[2]);<br />  if (arguments.length&lt;3||re_str=="") {<br />    return str;<br />  }<br />  while (str.indexof(re_str) != -1 &amp;&amp; str != "") {<br />    str_b = str.indexof(re_str);<br />    str_e = str_b+re_str.length-1;<br />    if (str_b != 0 &amp;&amp; str_e != str.length-1) {<br />      str = str.substr(0, str_b)+new_str+str.substr(str_e+1, str.length-1);<br />    } else if (str_b == 0) {<br />      str = new_str+str.substr(str_e+1, str.length-1);<br />    } else {<br />      str = str.substr(0, str_b)+new_str;<br />    }<br />  }<br />  return str;<br />}<br /></div>
<img src ="http://www.blogjava.net/spark/aggbug/82751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-11-22 13:54 <a href="http://www.blogjava.net/spark/archive/2006/11/22/82751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat简介 </title><link>http://www.blogjava.net/spark/archive/2006/10/17/75569.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Tue, 17 Oct 2006 03:55:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/10/17/75569.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/75569.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/10/17/75569.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/75569.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/75569.html</trackback:ping><description><![CDATA[系统结构<br /><p><strong><span style="FONT-FAMILY: 宋体"><font size="3">一、<span lang="EN-US">Tomcat背景</span></font></span></strong><span lang="EN-US" style="FONT-FAMILY: 宋体"><br /><font size="3">　　自从JSP发布之后，推出了各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后，开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器，当然同时也支持Servlet, 这样Tomcat就诞生了<span>。</span></font></span><font size="3"><span lang="EN-US" style="FONT-FAMILY: 宋体">Tomcat是jakarta项目中的一个重要的子项目，其被JavaWorld杂志的编辑选为2001年度最具创新的java产品，同时它又是sun公司官方推荐的servlet和jsp容器，因此其越来</span><span style="FONT-FAMILY: 宋体">越多的受到软件公司和开发人员的喜爱。<span lang="EN-US">servlet和jsp的最新规范都可以在tomcat的新版本中得到实现。其次，</span></span><span lang="EN-US" style="FONT-FAMILY: 宋体">Tomcat是完全免费的软件，任何人都可以从互联网上自由地下载。Tomcat与Apache的组合相当完美。</span></font></p><p><span lang="EN-US"><font size="3"><font face="Times New Roman"></font></font></span></p><p><font size="3"><strong><span style="FONT-FAMILY: 宋体">二、</span></strong><strong><span lang="EN-US"><font face="Times New Roman">Tomcat</font></span></strong><strong><span style="FONT-FAMILY: 宋体">目录</span></strong></font></p><p><font size="3"><span lang="EN-US" style="FONT-FAMILY: 宋体">tomcat<br />|---bin Tomcat：</span><span style="FONT-FAMILY: 宋体">存放启动和关闭<span lang="EN-US">tomcat脚本</span></span><span style="FONT-FAMILY: 宋体">；</span></font></p><p><font size="3"><span lang="EN-US" style="FONT-FAMILY: 宋体">|---conf Tomcat：存放</span><span style="FONT-FAMILY: 宋体">不同的配置文件（<span lang="EN-US">server.xml和web.xml）；</span></span></font><span lang="EN-US" style="FONT-FAMILY: 宋体"><br /><font size="3">|---doc：存放Tomcat文档；<br />|---lib</font></span><span lang="EN-US" style="FONT-FAMILY: 宋体"><font size="3">/japser/common</font></span><span style="FONT-FAMILY: 宋体"><font size="3">：存放</font><span lang="EN-US"><font size="3">Tomcat运行需要的库文件（JARS）；<br />|---logs：存放Tomcat执行时的LOG文件；<br />|---src：存放Tomcat的源代码；<br />|---webapps：Tomcat的主要Web发布目录（包括</font></span></span><span style="FONT-FAMILY: 宋体"><font size="3">应用程序示例</font></span><span style="FONT-FAMILY: 宋体"><font size="3">）；</font><span lang="EN-US"><br /><font size="3">|---work：</font></span></span><span style="FONT-FAMILY: 宋体"><font size="3">存放<span lang="EN-US">jsp编译后产生的class文件</span></font></span><span style="FONT-FAMILY: 宋体"><font size="3">；</font><span lang="EN-US"><br /></span></span></p><p><strong><span style="FONT-FAMILY: 宋体"><font size="3">三、<span lang="EN-US">Tomcat类加载</span></font></span></strong></p><p style="TEXT-INDENT: -21pt"><span lang="EN-US" style="FONT-FAMILY: 宋体"><span><font size="3"></font></span></span><font size="3"><span lang="EN-US"><font face="Times New Roman">Bootstrap($JAVA_HOME/jre/lib/ext/*.jar) <br />System($CLASSPATH/*.class</font></span><span style="FONT-FAMILY: 宋体">和指定的</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman">jar) <br />Common($CATALINA_HOME/common </font></span><span style="FONT-FAMILY: 宋体">下的</span><span lang="EN-US"><font face="Times New Roman">classes,lib,endores</font></span><span style="FONT-FAMILY: 宋体">三个子目录</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman">) <br />Catalina ($CATALINA_HOME/server/</font></span><span style="FONT-FAMILY: 宋体">下的</span><span lang="EN-US"><font face="Times New Roman">classes</font></span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"><font face="Times New Roman">lib</font></span><span style="FONT-FAMILY: 宋体">目录仅对</span><span lang="EN-US"><font face="Times New Roman">Tomcat</font></span><span style="FONT-FAMILY: 宋体">可见</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman">)<br />&amp;Shared($CATALINA_HOME/shared/</font></span><span style="FONT-FAMILY: 宋体">下的</span><span lang="EN-US"><font face="Times New Roman">classes</font></span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"><font face="Times New Roman">lib</font></span><span style="FONT-FAMILY: 宋体">目录以及</span><span lang="EN-US"><font face="Times New Roman">$CATALINA_HOME/lib</font></span><span style="FONT-FAMILY: 宋体">目录</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">仅对</span><span lang="EN-US"><font face="Times New Roman">Web</font></span><span style="FONT-FAMILY: 宋体">应用程序可见</span><span lang="EN-US"><font face="Times New Roman">,</font></span><span style="FONT-FAMILY: 宋体">对</span><span lang="EN-US"><font face="Times New Roman">Tomcat</font></span><span style="FONT-FAMILY: 宋体">不可见</span><span lang="EN-US"><font face="Times New Roman">WebApp($WEBAPP/Web-INF/*</font></span><span style="FONT-FAMILY: 宋体">仅对该</span><span lang="EN-US"><font face="Times New Roman">WEB</font></span><span style="FONT-FAMILY: 宋体">应用可见</span></font><span lang="EN-US"><font size="3"><font face="Times New Roman">classes/*.class lib/*.jar)<br /></font></font></span></p><p><span style="FONT-FAMILY: 宋体"><font size="3">加载类和资源的顺序为：</font></span><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">/Web-INF/classes </font></span></font></p><p><font size="3"><span lang="EN-US"><font face="Times New Roman">2</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">/Web-INF/lib/*.jar </font></span></font></p><p><font size="3"><span lang="EN-US"><font face="Times New Roman">3</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">Bootstrap </font></span></font></p><p><font size="3"><span lang="EN-US"><font face="Times New Roman">4</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">System </font></span></font></p><p><font size="3"><span lang="EN-US"><font face="Times New Roman">5</font></span><span style="FONT-FAMILY: 宋体">、</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman">$CATALINA_HOME/common/classes<br />6</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">$CATALINA_HOME/common/endores/*.jar </font></span></font></p><p><font size="3"><span lang="EN-US"><font face="Times New Roman">7</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">$CATALINA_HOME/common/lib/*.jar </font></span></font></p><p><font size="3"><span lang="EN-US"><font face="Times New Roman">8</font></span><span style="FONT-FAMILY: 宋体">、</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman">$CATALINA_HOME/shared/classes<br />9</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">$CATALINA_HOME/shared/lib/*.jar</font></span></font></p><p style="TEXT-INDENT: 18pt"><span lang="EN-US" style="FONT-FAMILY: 宋体"><font size="3"></font></span></p><p><font size="3"><strong><span style="FONT-FAMILY: 宋体">四、</span><span lang="EN-US"><font face="Times New Roman">server.xml</font></span></strong><strong><span style="FONT-FAMILY: 宋体">配置简介</span></strong><strong><span style="FONT-FAMILY: 宋体">：</span></strong></font></p><p style="TEXT-INDENT: 11.25pt"><font size="3"><span style="FONT-FAMILY: 宋体">下面讲述这个文件中的基本配置信息，更具体的配置信息请参考</span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">的文档：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3"><span><strong>server: </strong></span><br />1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">port </font></span><span style="FONT-FAMILY: 宋体">指定一个端口，这个端口<span>负责监听关闭</span></span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">的请求</span><span><font face="Times New Roman"></font></span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">2</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">shutdown </font></span><span style="FONT-FAMILY: 宋体">指定向端口发送的命令字符串</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><span><strong>service: </strong></span><br />1</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">name </font></span><span style="FONT-FAMILY: 宋体">指定</span><span lang="EN-US"><font face="Times New Roman">service</font></span><span style="FONT-FAMILY: 宋体">的名字</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><strong><span>Connector </span></strong><span>(</span></font></span><span style="FONT-FAMILY: 宋体">表示客户端和</span><span lang="EN-US"><font face="Times New Roman">service</font></span><span style="FONT-FAMILY: 宋体">之间的连接</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">port </font></span><span style="FONT-FAMILY: 宋体">指定服务器端要创建的端口号，并在这个断口监听来自客户端的请求</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />2</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">minProcessors </font></span><span style="FONT-FAMILY: 宋体">服务器启动时创建的处理请求的线程数</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />3</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">maxProcessors </font></span><span style="FONT-FAMILY: 宋体">最大可以创建的处理请求的线程数</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />4</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">enableLookups </font></span><span style="FONT-FAMILY: 宋体">如果为</span><span lang="EN-US"><font face="Times New Roman">true</font></span><span style="FONT-FAMILY: 宋体">，则可以通过调用</span><span lang="EN-US"><font face="Times New Roman">request.getRemoteHost()</font></span><span style="FONT-FAMILY: 宋体">进行</span><span lang="EN-US"><font face="Times New Roman">DNS</font></span><span style="FONT-FAMILY: 宋体">查</span></font></p><p style="TEXT-INDENT: 42.75pt"><font size="3"><span style="FONT-FAMILY: 宋体">询来得到远程客户端的实际主机名，若为</span><span lang="EN-US"><font face="Times New Roman">false</font></span><span style="FONT-FAMILY: 宋体">则不进行</span><span lang="EN-US"><font face="Times New Roman">DNS</font></span><span style="FONT-FAMILY: 宋体">查询，而是返回其</span><span lang="EN-US"><font face="Times New Roman">ip</font></span></font></p><p style="TEXT-INDENT: 42.75pt"><span style="FONT-FAMILY: 宋体"><font size="3">地址</font></span><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />5</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">redirectPort </font></span><span style="FONT-FAMILY: 宋体">指定服务器正在处理</span><span lang="EN-US"><font face="Times New Roman">http</font></span><span style="FONT-FAMILY: 宋体">请求时收到了一个</span><span lang="EN-US"><font face="Times New Roman">SSL</font></span><span style="FONT-FAMILY: 宋体">传输请求后重定向的</span></font></p><p style="TEXT-INDENT: 42.75pt"><span style="FONT-FAMILY: 宋体"><font size="3">端口号</font></span><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />6</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">acceptCount </font></span><span style="FONT-FAMILY: 宋体">指定当所有可以使用的处理请求的线程数都被使用时，可以放到处理</span></font></p><p style="TEXT-INDENT: 42.75pt"><span style="FONT-FAMILY: 宋体"><font size="3">队列中的请求数，超过这个数的请求将不予处理</font></span><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />7</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">connectionTimeout </font></span><span style="FONT-FAMILY: 宋体">指定超时的时间数</span><span lang="EN-US"><font face="Times New Roman">(</font></span><span style="FONT-FAMILY: 宋体">以毫秒为单位</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman">) <br /><strong><span>Engine </span></strong><span>(</span></font></span><span style="FONT-FAMILY: 宋体">表示指定</span><span lang="EN-US"><font face="Times New Roman">service</font></span><span style="FONT-FAMILY: 宋体">中的请求处理机，接收和处理来自</span><span lang="EN-US"><font face="Times New Roman">Connector</font></span><span style="FONT-FAMILY: 宋体">的请求</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">defaultHost </font></span><span style="FONT-FAMILY: 宋体">指定缺省的处理请求的主机名，它至少与其中的一个</span><span lang="EN-US"><font face="Times New Roman">host</font></span><span style="FONT-FAMILY: 宋体">元素的</span><span lang="EN-US"><font face="Times New Roman">name</font></span></font></p><p style="TEXT-INDENT: 42.75pt"><span style="FONT-FAMILY: 宋体"><font size="3">属性值是一样的</font></span><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><strong><span>Context </span></strong><span>(</span></font></span><span style="FONT-FAMILY: 宋体">表示一个</span><span lang="EN-US"><font face="Times New Roman">web</font></span><span style="FONT-FAMILY: 宋体">应用程序</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">docBase </font></span><span style="FONT-FAMILY: 宋体">应用程序的路径或者是</span><span lang="EN-US"><font face="Times New Roman">WAR</font></span><span style="FONT-FAMILY: 宋体">文件存放的路径</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />2</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">path </font></span><span style="FONT-FAMILY: 宋体">表示此</span><span lang="EN-US"><font face="Times New Roman">web</font></span><span style="FONT-FAMILY: 宋体">应用程序的</span><span lang="EN-US"><font face="Times New Roman">url</font></span><span style="FONT-FAMILY: 宋体">的前缀，这样请求的</span><span lang="EN-US"><font face="Times New Roman">url</font></span><span style="FONT-FAMILY: 宋体">为</span></font></p><p style="TEXT-INDENT: 42.75pt"><font size="3"><span lang="EN-US"><font face="Times New Roman">http://localhost:8080/path/**** <br />3</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">reloadable </font></span><span style="FONT-FAMILY: 宋体">这个属性非常重要，如果为</span><span lang="EN-US"><font face="Times New Roman">true</font></span><span style="FONT-FAMILY: 宋体">，则</span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">会自动检测应用程序的</span></font></p><p style="TEXT-INDENT: 42.75pt"><font size="3"><span lang="EN-US"><font face="Times New Roman">/WEB-INF/lib </font></span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"><font face="Times New Roman">/WEB-INF/classes</font></span><span style="FONT-FAMILY: 宋体">目录的变化，自动装载新的应用程序，我们可</span></font></p><p style="TEXT-INDENT: 42.75pt"><font size="3"><span style="FONT-FAMILY: 宋体">以在不重起</span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">的情况下改变应用程序</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><strong><span>host</span></strong><span> (</span></font></span><span style="FONT-FAMILY: 宋体">表示一个虚拟主机</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">name </font></span><span style="FONT-FAMILY: 宋体">指定主机名</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />2</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">appBase </font></span><span style="FONT-FAMILY: 宋体">应用程序基本目录，即存放应用程序的目录</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />3</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">unpackWARs </font></span><span style="FONT-FAMILY: 宋体">如果为</span><span lang="EN-US"><font face="Times New Roman">true</font></span><span style="FONT-FAMILY: 宋体">，则</span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">会自动将</span><span lang="EN-US"><font face="Times New Roman">WAR</font></span><span style="FONT-FAMILY: 宋体">文件解压，否则不解压，直接</span></font></p><p style="TEXT-INDENT: 42.75pt"><font size="3"><span style="FONT-FAMILY: 宋体">从</span><span lang="EN-US"><font face="Times New Roman">WAR</font></span><span style="FONT-FAMILY: 宋体">文件中运行应用程序</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><strong><span>Logger </span></strong><span>(</span></font></span><span style="FONT-FAMILY: 宋体">表示日志，调试和错误信息</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">className </font></span><span style="FONT-FAMILY: 宋体">指定</span><span lang="EN-US"><font face="Times New Roman">logger</font></span><span style="FONT-FAMILY: 宋体">使用的类名，此类必须实现</span><span lang="EN-US"><font face="Times New Roman">org.apache.catalina.Logger </font></span><span style="FONT-FAMILY: 宋体">接口</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />2</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">prefix </font></span><span style="FONT-FAMILY: 宋体">指定</span><span lang="EN-US"><font face="Times New Roman">log</font></span><span style="FONT-FAMILY: 宋体">文件的前缀</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />3</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">suffix </font></span><span style="FONT-FAMILY: 宋体">指定</span><span lang="EN-US"><font face="Times New Roman">log</font></span><span style="FONT-FAMILY: 宋体">文件的后缀</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br />4</font></span><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">timestamp </font></span><span style="FONT-FAMILY: 宋体">如果为</span><span lang="EN-US"><font face="Times New Roman">true</font></span><span style="FONT-FAMILY: 宋体">，则</span><span lang="EN-US"><font face="Times New Roman">log</font></span><span style="FONT-FAMILY: 宋体">文件名中要加入时间，如下</span></font></p><p style="TEXT-INDENT: 42.75pt"><span style="FONT-FAMILY: 宋体"><font size="3">例</font></span><font size="3"><span lang="EN-US"><font face="Times New Roman">:localhost_log.2001-10-04.txt <br /><strong><span></span><span>Realm</span></strong><span> (</span></font></span><span style="FONT-FAMILY: 宋体">表示存放用户名，密码及</span><span lang="EN-US"><font face="Times New Roman">role</font></span><span style="FONT-FAMILY: 宋体">的数据库</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">className </font></span><span style="FONT-FAMILY: 宋体">指定</span><span lang="EN-US"><font face="Times New Roman">Realm</font></span><span style="FONT-FAMILY: 宋体">使用的类名，此类必须实现</span><span lang="EN-US"><font face="Times New Roman">org.apache.catalina.Realm</font></span><span style="FONT-FAMILY: 宋体">接口</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><strong><span>Valve </span></strong><span>(</span></font></span><span style="FONT-FAMILY: 宋体">功能与</span><span lang="EN-US"><font face="Times New Roman">Logger</font></span><span style="FONT-FAMILY: 宋体">差不多，其</span><span lang="EN-US"><font face="Times New Roman">prefix</font></span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US"><font face="Times New Roman">suffix</font></span><span style="FONT-FAMILY: 宋体">属性解释和</span><span lang="EN-US"><font face="Times New Roman">Logger </font></span><span style="FONT-FAMILY: 宋体">中的一样</span><span lang="EN-US"><font face="Times New Roman">)</font></span><span style="FONT-FAMILY: 宋体">：</span></font><span lang="EN-US"><br /><font face="Times New Roman" size="3">1</font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">className </font></span><span style="FONT-FAMILY: 宋体">指定</span><span lang="EN-US"><font face="Times New Roman">Valve</font></span><span style="FONT-FAMILY: 宋体">使用的类名，如用</span><span lang="EN-US"><font face="Times New Roman">org.apache.catalina.valves.AccessLogValve</font></span></font></p><p style="TEXT-INDENT: 42.75pt"><span style="FONT-FAMILY: 宋体"><font size="3">类可以记录应用程序的访问信息</font></span><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><strong><span>directory</span></strong></font></span><span style="FONT-FAMILY: 宋体">（指定</span><span lang="EN-US"><font face="Times New Roman">log</font></span><span style="FONT-FAMILY: 宋体">文件存放的位置）：</span></font><span lang="EN-US"><br /><font face="Times New Roman"><font size="3"><span></span>1</font></font></span><font size="3"><span style="FONT-FAMILY: 宋体">、</span><span lang="EN-US"><font face="Times New Roman">pattern </font></span><span style="FONT-FAMILY: 宋体">有两个值，</span><span lang="EN-US"><font face="Times New Roman">common</font></span><span style="FONT-FAMILY: 宋体">方式记录远程主机名或</span><span lang="EN-US"><font face="Times New Roman">ip</font></span><span style="FONT-FAMILY: 宋体">地址，用户名，日期，第一行</span></font></p><p style="TEXT-INDENT: 42.75pt"><font size="3"><span style="FONT-FAMILY: 宋体">请求的字符串，</span><span lang="EN-US"><font face="Times New Roman">HTTP</font></span><span style="FONT-FAMILY: 宋体">响应代码，发送的字节数。</span><span lang="EN-US"><font face="Times New Roman">combined</font></span><span style="FONT-FAMILY: 宋体">方式比</span><span lang="EN-US"><font face="Times New Roman">common</font></span><span style="FONT-FAMILY: 宋体">方式记</span></font></p><p style="TEXT-INDENT: 42.75pt"><span style="FONT-FAMILY: 宋体"><font size="3">录的值更多</font></span></p><p><span lang="EN-US"><font size="3"><font face="Times New Roman"></font></font></span></p><p><font size="3"><strong><span style="FONT-FAMILY: 宋体">五、</span><span lang="EN-US"><font face="Times New Roman">web.xml</font></span></strong><strong><span style="FONT-FAMILY: 宋体">配置简介</span></strong><strong><span style="FONT-FAMILY: 宋体">：</span></strong></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><strong><span lang="EN-US"><font face="Times New Roman">1</font></span></strong><strong><span style="FONT-FAMILY: 宋体">、默认</span><span lang="EN-US"><font face="Times New Roman">(</font></span></strong><strong><span style="FONT-FAMILY: 宋体">欢迎</span><span lang="EN-US"><font face="Times New Roman">)</font></span></strong><strong><span style="FONT-FAMILY: 宋体">文件的设置</span></strong></font></p><p style="TEXT-INDENT: 10.5pt"><font size="3"><span style="FONT-FAMILY: 宋体"></span><font face="Times New Roman"></font><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US"><font face="Times New Roman">tomcat4confweb.xml</font></span><span style="FONT-FAMILY: 宋体">中，</span><span lang="EN-US"><font face="Times New Roman">&lt;welcome-file-list&gt;</font></span><span style="FONT-FAMILY: 宋体">与</span><span lang="EN-US"><font face="Times New Roman">IIS</font></span><span style="FONT-FAMILY: 宋体">中的默认文件意思相同。</span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><font face="Times New Roman"></font><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;welcome-file-list&gt; </font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman"> &lt;welcome-file&gt;index.html&lt;/welcome-file&gt; </font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman"> &lt;welcome-file&gt;index.htm&lt;/welcome-file&gt; </font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman"> &lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman"> &lt;/welcome-file-list&gt;</font></span></font></p><p><span lang="EN-US"><font face="Times New Roman"><font size="3"></font></font></span></p><p><font size="3"><strong><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">2</font></span></strong><strong><span style="FONT-FAMILY: 宋体">、报错文件的设置</span></strong></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;error-page&gt; </font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;error-code&gt;404&lt;/error-code&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;location&gt;/notFileFound.jsp&lt;/location&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;/error-page&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;error-page&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;exception-type&gt;java.lang.NullPointerException&lt;/exception-type&gt; </font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;location&gt;/null.jsp&lt;/location&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;/error-page&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体">如果某文件资源没有找到，服务器要报</span><span lang="EN-US"><font face="Times New Roman">404</font></span><span style="FONT-FAMILY: 宋体">错误，按上述配置则会调用</span><span lang="EN-US"><font face="Times New Roman">webappsROOTnotFileFound.jsp</font></span><span style="FONT-FAMILY: 宋体">。</span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体">如果执行的某个</span><span lang="EN-US"><font face="Times New Roman">JSP</font></span><span style="FONT-FAMILY: 宋体">文件产生</span><span lang="EN-US"><font face="Times New Roman">NullPointException </font></span><span style="FONT-FAMILY: 宋体">，则会调用</span><span lang="EN-US"><font face="Times New Roman">webappsROOTnull.jsp</font></span></font></p><p><span lang="EN-US"><font face="Times New Roman"><font size="3"></font></font></span></p><p><font size="3"><strong><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">3</font></span></strong><strong><span style="FONT-FAMILY: 宋体">、会话超时的设置</span></strong></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体">设置</span><span lang="EN-US"><font face="Times New Roman">session </font></span><span style="FONT-FAMILY: 宋体">的过期时间，单位是分钟；</span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;session-config&gt; </font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;session-timeout&gt;30&lt;/session-timeout&gt; </font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;/session-config&gt;</font></span></font></p><p><span lang="EN-US"><font face="Times New Roman"><font size="3"></font></font></span></p><p><font size="3"><strong><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">4</font></span></strong><strong><span style="FONT-FAMILY: 宋体">、过滤器的设置</span></strong></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;filter&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;filter-name&gt;FilterSource&lt;/filter-name&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;filter-class&gt;project4. FilterSource &lt;/filter-class&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;/filter&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;filter-mapping&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;filter-name&gt;FilterSource&lt;/filter-name&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;url-pattern&gt;/WwwServlet&lt;/url-pattern&gt;</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">(&lt;url-pattern&gt;/haha/*&lt;/url-pattern&gt;)</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">&lt;/filter-mapping&gt;</font></span></font></p><p><span lang="EN-US"><font size="3"><font face="Times New Roman"></font></font></span></p><p><span style="FONT-FAMILY: 宋体"><font size="3"><strong><span>过滤：</span></strong></font></span></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">1) </font></span><span style="FONT-FAMILY: 宋体">身份验证的过滤</span><span lang="EN-US"><font face="Times New Roman">Authentication Filters</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">2) </font></span><span style="FONT-FAMILY: 宋体">日志和审核的过滤</span><span lang="EN-US"><font face="Times New Roman">Logging and Auditing Filters</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">3) </font></span><span style="FONT-FAMILY: 宋体">图片转化的过滤</span><span lang="EN-US"><font face="Times New Roman">Image conversion Filters</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">4) </font></span><span style="FONT-FAMILY: 宋体">数据压缩的过滤</span><span lang="EN-US"><font face="Times New Roman">Data compression Filters</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">5) </font></span><span style="FONT-FAMILY: 宋体">加密过滤</span><span lang="EN-US"><font face="Times New Roman">Encryption Filters</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">6) Tokenizing Filters</font></span></font></p><p><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">7) </font></span><span style="FONT-FAMILY: 宋体">资源访问事件触发的过滤</span><span lang="EN-US"><font face="Times New Roman">Filters that trigger resource access events XSL/T </font></span><span style="FONT-FAMILY: 宋体">过滤</span><span lang="EN-US"><font face="Times New Roman">XSL/T filters</font></span></font></p><p style="TEXT-INDENT: -42pt"><font size="3"><span style="FONT-FAMILY: 宋体"></span><span lang="EN-US"><font face="Times New Roman">9) </font></span><span style="FONT-FAMILY: 宋体">内容类型的过滤</span><span lang="EN-US"><font face="Times New Roman">Mime-type chain Filter </font></span><span style="FONT-FAMILY: 宋体">注意监听器的顺序，如：先安全过滤，然后资源，</span></font></p><p style="TEXT-INDENT: 31.5pt"><span style="FONT-FAMILY: 宋体"><font size="3">然后内容类型等，这个顺序可以自己定。</font></span></p><p><span lang="EN-US"><font size="3"><font face="Times New Roman"></font></font></span></p><p><strong><font size="3"><span style="FONT-FAMILY: 宋体">六、管理</span><span><font face="Times New Roman"></font></span></font></strong><span lang="EN-US"><br /><strong><font face="Times New Roman"><font size="3"><span></span><span>1</span></font></font></strong></span><strong><font size="3"><span style="FONT-FAMILY: 宋体">、用户配置</span><span><font face="Times New Roman"></font></span></font></strong><span lang="EN-US"><br /><font face="Times New Roman"><font size="3"><span></span></font></font></span><font size="3"><span style="FONT-FAMILY: 宋体">在进行具体</span><span lang="EN-US"><font face="Times New Roman">Tomcat</font></span><span style="FONT-FAMILY: 宋体">管理之前，先给</span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">添加一个用户，使这个用户有权限来进行管理。</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><span></span></font></span><span style="FONT-FAMILY: 宋体">打开</span><span lang="EN-US"><font face="Times New Roman">conf</font></span><span style="FONT-FAMILY: 宋体">目录下的</span><span lang="EN-US"><font face="Times New Roman">tomcat-users.xml</font></span><span style="FONT-FAMILY: 宋体">文件，在相应的位置添加下面一行：</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><span></span>&lt;user name="user" password="user" roles="standard,manager"/&gt; <br /><span></span></font></span><span style="FONT-FAMILY: 宋体">然后重起</span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">，在浏览器中输入</span><span lang="EN-US"><font face="Times New Roman">http://localhost:8080/manager/</font></span><span style="FONT-FAMILY: 宋体">，会弹出对话框，输入上面的用户</span></font></p><p style="TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体"><font size="3">名和密码即可。</font></span><span lang="EN-US"><font face="Times New Roman"><font size="3"><br /><br /><span></span><span><strong>2</strong></span></font></font></span><strong><font size="3"><span style="FONT-FAMILY: 宋体">、应用程序列表</span><span><font face="Times New Roman"></font></span></font></strong><span lang="EN-US"><br /><font face="Times New Roman"><font size="3"><span></span></font></font></span><font size="3"><span style="FONT-FAMILY: 宋体">在浏览器中输入</span><span lang="EN-US"><font face="Times New Roman">http://localhost:8080/manager/list</font></span><span style="FONT-FAMILY: 宋体">，浏览器将会显示如下的信息：</span></font><font size="3"><span lang="EN-US"><font face="Times New Roman"><br /><span></span>OK - Listed applications for virtual host localhost <br /><span></span>/ex:running:1 <br /><span></span>/examples:running:1 <br /><span></span>/webdav:running:0 <br /><span></span>/tomcat-docs:running:0 <br /><span></span>/manager:running:0 <br /><span></span>/:running:0 <br /><span></span></font></span><span style="FONT-FAMILY: 宋体">上面显示的信息分别为：应用程序的路径、当前状态、连接这个程序的</span><span lang="EN-US"><font face="Times New Roman">session</font></span><span style="FONT-FAMILY: 宋体">数</span></font><span lang="EN-US"><br /><br /><font face="Times New Roman"><font size="3"><strong><span></span></strong><span><strong>3</strong></span></font></font></span><strong><font size="3"><span style="FONT-FAMILY: 宋体">、重新装载应用程序</span><span><font face="Times New Roman"></font></span></font></strong><span lang="EN-US"><br /><font face="Times New Roman"><font size="3"><span></span></font></font></span><font size="3"><span style="FONT-FAMILY: 宋体">在浏览器中输入</span><span lang="EN-US"><font face="Times New Roman"> http://localhost:8080/manager/reload?path=/examples</font></span><span style="FONT-FAMILY: 宋体">，浏览器显示如下：</span></font><span lang="EN-US"><font face="Times New Roman" size="3"><br /><span></span>OK - Reloaded application at context path /examples </font></span></p><p><font size="3"><span style="FONT-FAMILY: 宋体">这表示</span><span lang="EN-US"><font face="Times New Roman">example</font></span><span style="FONT-FAMILY: 宋体">应用程序装载成功，如果我们将</span><span lang="EN-US"><font face="Times New Roman">server.xml</font></span><span style="FONT-FAMILY: 宋体">的</span><span lang="EN-US"><font face="Times New Roman">Context</font></span><span style="FONT-FAMILY: 宋体">元素的</span><span lang="EN-US"><font face="Times New Roman">reloadable</font></span><span style="FONT-FAMILY: 宋体">属性设为</span><span lang="EN-US"><font face="Times New Roman">true</font></span><span style="FONT-FAMILY: 宋体">，则没必要利用这种方式重新装载应用程序，因为</span><span lang="EN-US"><font face="Times New Roman">tomcat</font></span><span style="FONT-FAMILY: 宋体">会自动装载。</span><span lang="EN-US"><font face="Times New Roman"></font></span></font></p><p style="TEXT-INDENT: 10.5pt"><span lang="EN-US"><font size="3"><font face="Times New Roman"></font></font></span></p><p><font size="3"><strong><span lang="EN-US"><font face="Times New Roman">4</font></span></strong><strong><span style="FONT-FAMILY: 宋体">、显示</span><span lang="EN-US"><font face="Times New Roman">session</font></span></strong><strong><span style="FONT-FAMILY: 宋体">信息</span><span><font face="Times New Roman"></font></span></strong></font><span lang="EN-US"><br /><font face="Times New Roman" size="3"></font></span><font size="3"><span style="FONT-FAMILY: 宋体">在浏览器中输入</span><span lang="EN-US"><font face="Times New Roman">http://localhost:8080/manager/sessions?path=/examples</font></span><span style="FONT-FAMILY: 宋体">，浏览器显示如下：</span></font><span lang="EN-US"><font face="Times New Roman" size="3"><br />OK - Session information for application at context path /examples Default maximum session inactive </font></span></p><p style="TEXT-INDENT: 10.5pt"><span lang="EN-US"><font face="Times New Roman"><font size="3">interval 30 minutes <br /><br /><strong><span>5</span></strong></font></font></span><strong><font size="3"><span style="FONT-FAMILY: 宋体">、启动和关闭应用程序</span><span><font face="Times New Roman"></font></span></font></strong><span lang="EN-US"><br /><font face="Times New Roman" size="3"></font></span><font size="3"><span style="FONT-FAMILY: 宋体">在浏览器中输入</span><span lang="EN-US"><a href="http://localhost:8080/manager/start?path=/examples和"><font face="Times New Roman">http://localhost:8080/manager/start?path=/examples</font><span style="FONT-FAMILY: 宋体">和</span></a></span></font></p><p style="TEXT-INDENT: 10.5pt"><font size="3"><span lang="EN-US"><font face="Times New Roman"><a href="http://localhost:8080/manager/stop?path=/examples">http://localhost:8080/manager/stop?path=/examples</a></font></span><span style="FONT-FAMILY: 宋体">分别启动和关闭</span><span lang="EN-US"><font face="Times New Roman">examples</font></span><span style="FONT-FAMILY: 宋体">应用程序。</span></font></p><img src ="http://www.blogjava.net/spark/aggbug/75569.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-10-17 11:55 <a href="http://www.blogjava.net/spark/archive/2006/10/17/75569.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 关于中文乱码问题的解决方案与经验</title><link>http://www.blogjava.net/spark/archive/2006/10/12/74777.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Thu, 12 Oct 2006 05:53:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/10/12/74777.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/74777.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/10/12/74777.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/74777.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/74777.html</trackback:ping><description><![CDATA[Java 关于中文乱码问题的解决方案与经验<br /><br />一、字节和unicode <br /><br />Java内核是unicode的，就连class文件也是，但是很多媒体，包括文件/流的保存方式是使用字节流的。因此Java要对这些字节流经行转化。char是unicode的，而byte是字节。Java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度，可以用来告诉你，你用的convertor。其中两个很常用的静态函数是： <br /><br />public static ByteToCharConverter getDefault(); <br />public static ByteToCharConverter getConverter(String encoding); <br /><br />如果你不指定converter，则系统会自动使用当前的encoding,gb平台上用gbk,en平台上用8859_1。 <br /><br />byte ??〉char： <br />"你"的gb码是：0xc4e3 ,unicode是0x4f60 <br />String encoding = "gb2312"; <br />byte b[] = {(byte)´\u00c4´,(byte)´\u00e3´}; <br />ByteToCharConverter converter = ByteToCharConverter.getConverter(encoding); <br />char c[] = converter.convertAll(b); <br />for (int i = 0; i &lt; c.length; i++) { <br />System.out.println(Integer.toHexString(c[i])); <br />} <br />结果是什么？0x4f60 <br />如果encoding ="8859_1"，结果又是什么？0x00c4,0x00e3 <br /><br />如果代码改为： <br /><br />byte b[] = {(byte)´\u00c4´,(byte)´\u00e3´}; <br />ByteToCharConverter converter = ByteToCharConverter. getDefault(); <br />char c[] = converter.convertAll(b); <br />for (int i = 0; i &lt; c.length; i++) { <br />System.out.println(Integer.toHexString(c[i])); <br />} <br /><br />结果将又是什么？ <br /><br />这就要根据平台的编码而定。 <br /><br />char ??〉byte： <br />String encoding = "gb2312"; <br />char c[] = {´\u4f60´}; <br />CharToByteConverter converter = CharToByteConverter.getConverter(encoding); <br />byte b[] = converter.convertAll(c); <br />for (int i = 0; i &lt; b.length; i++) { <br />System.out.println(Integer.toHexString(b[i])); <br />} <br />结果是什么？0x00c4,0x00e3 <br />如果encoding ="8859_1"，结果又是什么？0x3f <br />如果代码改为 <br />String encoding = "gb2312"; <br />char c[] = {´\u4f60´}; <br />CharToByteConverter converter = CharToByteConverter.getDefault(); <br />byte b[] = converter.convertAll(c); <br />for (int i = 0; i &lt; b.length; i++) { <br />System.out.println(Integer.toHexString(b[i])); <br />} <br /><br />结果将又是什么？还是根据平台的编码而定。 <br /><br />很多中文问题就是从这两个最简单的类派生出来的。而却有很多类不直接支持把encoding输入，这给我们带来诸多不便。很多程序难得用encoding了，直接用default的encoding，这就给我们移植带来了很多困难。 <br /><br />二、utf-8 <br /><br />utf-8是和unicode一一对应的，其实现很简单： <br /><br />7位的unicode: 0 _ _ _ _ _ _ _ <br />11位的unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />16位的unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />21位的unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br /><br />大多数情况是只使用到16位以下的unicode: <br /><br />"你"的gb码是：0xc4e3 ,unicode是0x4f60 <br />0xc4e3的二进制： <br />1100 ，0100 ，1110 ，0011 <br /><br />由于只有两位我们按照两位的编码来排，但是我们发现这行不通，因为第７位不是0因此，返回"?" <br /><br />0x4f60的二进制： <br />0100 ，1111 ，0110 ，0000 <br />我们用utf-8补齐，变成： <br />1110 ，0100 ，1011 ，1101 ，1010 ，0000 <br />e4--bd-- a0 <br />于是返回：0xe4,0xbd,0xa0。 <br /><br />三、string和byte[] <br /><br />string其实核心是char[],然而要把byte转化成string，必须经过编码。string.length()其实就是char数组的长度，如果使用不同的编码，很可能会错分，造成散字和乱码。例如： <br /><br /><br />String encoding = “”; <br />byte [] b={(byte)´\u00c4´,(byte)´\u00e3´}; <br />String str=new String(b,encoding); <br /><br />如果encoding=8859_1，会有两个字，但是encoding=gb2312只有一个字这个问题在处理分页是经常发生。 <br /><br />四、Reader,Writer / InputStream,OutputStream <br /><br />Reader和Writer核心是char，InputStream和OutputStream核心是byte。但是Reader和Writer的主要目的是要把char读/写InputStream/OutputStream。例如： <br /><br /><br />文件test.txt只有一个"你"字，0xc4,0xe3 <br />String encoding = "gb2312"; <br />InputStreamReader reader = new InputStreamReader(new FileInputStream( <br />"text.txt"), encoding); <br />char c[] = new char[10]; <br />int length = reader.read(c); <br />for (int i = 0; i &lt; length; i++) { <br />System.out.println(c[i]); <br />} <br /><br />结果是什么？是"你"。如果encoding ="8859_1"，结果是什么？"??"两个字符，表示不认识。反过来的例子自己做。 <br /><br />五、我们要对Java的编译器有所了解： <br /><br />Javac ?encoding <br /><br />我们常常没有用到encoding这个参数。其实encoding这个参数对于跨平台的操作是很重要的。如果没有指定encoding，则按照系统的默认encoding,gb平台上是gb2312，英文平台上是iso8859_1。Java的编译器实际上是调用sun.tools.Javac.main的类，对文件进行编译，这个类有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。编译器就是根据这个变量来读取Java文件的，然后把用utf-8形式编译成class文件。例子代码： <br /><br /><br />String str = "你"; <br />FileWriter writer = new FileWriter("text.txt"); <br />write.write(str); <br />writer.close(); <br /><br />如果用gb2312编译，你会找到e4 bd a0的字段 ； <br />如果用8859_1编译， 00c4 00e3的二进制： <br />0000，0000 ，1100，0100 ，0000，0000 ，1110，0011 <br />因为每个字符都大于7位，因此用11位编码： <br />1100，0001，1000，0100，1100，0011，1010，0011 <br />c1-- 84--　c3--　 a3 <br />你会找到c1 84 c3 a3 <br /><br />但是我们往往忽略掉这个参数，因此这样往往会有跨平台的问题： <br /><br />样例代码在中文平台上编译，生成zhclass <br /><br />样例代码在英文平台上编译，输出enclass <br /><br />(1) zhclass在中文平台上执行ok,但是在英文平台上不行 <br /><br />(2) enclass在英文平台上执行ok,但是在中文平台上不行 <br /><br />原因是： <br /><br />(1) 在中文平台上编译后，其实str在运行态的char[]是0x4f60,　在中文平台上运行，filewriter的缺省编码是gb2312,因此chartobyteconverter会自动用调用gb2312的converter,把str转化成byte输入到fileoutputstream中，于是0xc4,0xe3放进了文件。但是如果是在英文平台下，chartobyteconverter的缺省值是8859_1, filewriter会自动调用8859_1去转化str,但是他无法解释，因此他会输出"?" <br /><br />(2) 在英文平台上编译后，其实str在运行态的char[]是0x00c4 0x00e3, 在中文平台上运行，中文无法识别，因此会出现??；在英文平台上，0x00c4--&gt;0xc4,0x00e3-&gt;0xe3，因此0xc4,0xe3被放进了文件。 <br /><br />六、其它原因： <br /><br /><br />&lt;%@ page contentType="text/html; charset=GBK" %&gt; <br /><br />设置浏览器的显示编码，如果response的数据是utf8编码，显示将是乱码，但是乱码和上述原因还不一样。 <br /><br />七、发生编码的地方： <br /><br />1. 从数据库到Java程序 byte??〉char <br /><br />2. 从Java程序到数据库 char??〉byte <br /><br />3. 从文件到Java程序 byte??〉char <br /><br />4. 从Java程序到文件 char??〉byte <br /><br />5. 从Java程序到页面显示 char??〉byte <br /><br />6. 从页面form提交数据到Java程序byte??〉char <br /><br />7. 从流到Java程序byte??〉char <br /><br />8. 从Java程序到流char??〉byte <br /><br />可以使用配置过滤器的方法解决中文乱码的： <br /><br /><br />&lt;web-app&gt; <br />&lt;filter&gt; <br />&lt;filter-name&gt;RequestFilter&lt;/filter-name&gt; <br />&lt;filter-class&gt;net.golden.uirs.util.RequestFilter&lt;/filter-class&gt; <br />&lt;init-param&gt; <br />&lt;param-name&gt;charset&lt;/param-name&gt; <br />&lt;param-value&gt;gb2312&lt;/param-value&gt; <br />&lt;/init-param&gt; <br />&lt;/filter&gt; <br />&lt;filter-mapping&gt; <br />&lt;filter-name&gt;RequestFilter&lt;/filter-name&gt; <br />&lt;url-pattern&gt;*.Jsp&lt;/url-pattern&gt; <br />&lt;/filter-mapping&gt; <br />&lt;/web-app&gt; <br /><br /><br />public void doFilter(ServletRequest req, ServletResponse res, <br />FilterChain fChain) throws IOException, ServletException { <br />HttpServletRequest request = (HttpServletRequest) req; <br />HttpServletResponse response = (HttpServletResponse) res; <br />HttpSession session = request.getSession(); <br />String userId = (String) session.getAttribute("userid"); <br />req.setCharacterEncoding(this.filterConfig.getInitParameter("charset")); <br />// 设置字符集？ <br />实际上是设置了byte ??〉char的encoding <br />try { <br />if (userId == null || userId.equals("")) { <br />if (!request.getRequestURL().toString().matches( <br />".*/uirs/logon/logon(Controller){0,1}\\x2EJsp$")) { <br />session.invalidate(); <br />response.sendRedirect(request.getContextPath() + <br />"/uirs/logon/logon.Jsp"); <br />} <br />} <br />else { <br />// 看看是否具有信息上报系统的权限 <br />if (!net.golden.uirs.util.UirsChecker.check(userId, "信息上报系统", <br />net.golden.uirs.util.UirsChecker.ACTION_DO)) { <br />if (!request.getRequestURL().toString().matches( <br />".*/uirs/logon/logon(Controller){0,1}\\x2EJsp$")) { <br />response.sendRedirect(request.getContextPath() + <br />"/uirs/logon/logonController.Jsp"); <br />} <br />} <br />} <br />} <br />catch (Exception ex) { <br />response.sendRedirect(request.getContextPath() + <br />"/uirs/logon/logon.Jsp"); <br />} <br />fChain.doFilter(req, res); <br />}<img src ="http://www.blogjava.net/spark/aggbug/74777.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-10-12 13:53 <a href="http://www.blogjava.net/spark/archive/2006/10/12/74777.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>中文字符集与字符编码的基础知识</title><link>http://www.blogjava.net/spark/archive/2006/09/29/72748.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Fri, 29 Sep 2006 03:10:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/09/29/72748.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/72748.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/09/29/72748.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/72748.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/72748.html</trackback:ping><description><![CDATA[
		<p>
				<span style="FONT-SIZE: 12px">字符是各种文字和符号的总称，包括各国家文字、标点符号、图形符号、数字等。字符集是多个字符的集合，字符集种类较多，每个字符集包含的字符个数不同，常见字符集名称：ASCII字符集、GB2312字符集、BIG5字符集、 GB 18030字符集、Unicode字符集等。计算机要准确的处理各种字符集文字，需要进行字符编码，以便计算机能够识别和存储各种文字。<br /><br />中文文字数目大，而且还分为简体中文和繁体中文两种不同书写规则的文字，而计算机最初是按英语单字节字符设计的，因此，对中文字符进行编码，是中文信息交流的技术基础。本文将按照字符集的时间顺序讨论几种典型的字符集，选取几种代表性的中文字符集，研究历史由来、特点、技术特征。<br /><br />ASCII 字符集<br /><br />1．名称的由来<br /><br />ASCII（American Standard Code for Information Interchange，美国信息互换标准代码）是基于罗马字母表的一套电脑编码系统。<br /><br />2．特点<br /><br />它主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统，并等同于国际标准ISO 646。<br /><br />3．包含内容<br /><br />控制字符：回车键、退格、换行键等。<br /><br />可显示字符：英文大小写字符、阿拉伯数字和西文符号<br /><br />4．技术特征<br /><br />7位（bits）表示一个字符，共128字符<br /><br />5．ASCII扩展字符集<br /><br />7位编码的字符集只能支持128个字符，为了表示更多的欧洲常用字符对ASCII进行了扩展，ASCII扩展字符集使用8位（bits）表示一个字符，共256字符。<br /><br />ASCII扩展字符集比ASCII字符集扩充出来的符号包括表格符号、计算符号、希腊字母和特殊的拉丁符号。 <br /><br />GB2312 字符集<br /><br />1．名称的由来<br /><br />GB2312又称为GB2312-80字符集，全称为《信息交换用汉字编码字符集·基本集》，由原中国国家标准总局发布，1981年5月1日实施。<br /><br />2．特点<br /><br />GB2312是中国国家标准的简体中文字符集。它所收录的汉字已经覆盖99.75%的使用频率，基本满足了汉字的计算机处理需要。在中国大陆和新加坡获广泛使用。<br /><br />3．包含内容<br /><br />GB2312收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母，共 7445 个图形字符。其中包括6763个汉字，其中一级汉字3755个，二级汉字3008个；包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。 <br /><br />4．技术特征<br /><br />（1）分区表示：<br /><br />GB2312中对所收汉字进行了“分区”处理，每区含有94个汉字/符号。这种表示方式也称为区位码。<br /><br />各区包含的字符如下：01-09区为特殊符号；16-55区为一级汉字，按拼音排序；56-87区为二级汉字，按部首/笔画排序；10-15区及88-94区则未有编码。<br /><br />（2）双字节表示<br /><br />两个字节中前面的字节为第一字节，后面的字节为第二字节。习惯上称第一字节为“高字节” ，而称第二字节为“低字节”。<br /><br />“高位字节”使用了0xA1-0xF7(把01-87区的区号加上0xA0)，“低位字节”使用了0xA1-0xFE(把01-94加上0xA0)。<br /><br />5．编码举例<br /><br />以GB2312字符集的第一个汉字“啊”字为例，它的区号16，位号01，则区位码是1601，在大多数计算机程序中，高字节和低字节分别加0xA0得到程序的汉字处理编码0xB0A1。计算公式是：0xB0=0xA0+16, 0xA1=0xA0+1。<br /><br />BIG5 字符集<br /><br />1．名称的由来<br /><br />又称大五码或五大码，1984年由台湾财团法人信息工业策进会和五间软件公司宏碁 (Acer)、神通 (MiTAC)、佳佳、零壹 (Zero One)、大众 (FIC)创立，故称大五码。<br /><br />Big5码的产生，是因为当时台湾不同厂商各自推出不同的编码，如倚天码、IBM PS55、王安码等，彼此不能兼容；另一方面，台湾政府当时尚未推出官方的汉字编码，而中国大陆的GB2312编码亦未有收录繁体中文字。<br /><br />2．特点<br /><br />Big5字符集共收录13,053个中文字，该字符集在中国台湾使用。耐人寻味的是该字符集重复地收录了两个相同的字：“兀”(0xA461及0xC94A)、“嗀”(0xDCD1及0xDDFC)。<br /><br />3．字符编码方法<br /><br />Big5码使用了双字节储存方法，以两个字节来编码一个字。第一个字节称为“高位字节”，第二个字节称为“低位字节”。高位字节的编码范围0xA1-0xF9，低位字节的编码范围0x40-0x7E及0xA1-0xFE。<br /><br />各编码范围对应的字符类型如下：0xA140-0xA3BF为标点符号、希腊字母及特殊符号，另外于0xA259-0xA261，存放了双音节度量衡单位用字：兙兛兞兝兡兣嗧瓩糎；0xA440-0xC67E为常用汉字，先按笔划再按部首排序；0xC940-0xF9D5为次常用汉字，亦是先按笔划再按部首排序。<br /><br />4．Big5 的局限性<br /><br />尽管Big5码内包含一万多个字符，但是没有考虑社会上流通的人名、地名用字、方言用字、化学及生物科等用字，没有包含日文平假名及片假名字母。<br /><br />例如台湾视“着”为“著”的异体字，故没有收录“着”字。康熙字典中的一些部首用字(如“亠”、“疒”、“辵”、“癶”等)、常见的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也没有收录到Big5之中。<br /><br />GB18030 字符集<br /><br />1．名称的由来<br /><br />GB 18030的全称是GB18030-2000《信息交换用汉字编码字符集基本集的扩充》，是我国政府于2000年3月17日发布的新的汉字编码国家标准，2001年8月31日后在中国市场上发布的软件必须符合本标准<br /><br />2．特点<br /><br />GB 18030字符集标准的出台经过广泛参与和论证，来自国内外知名信息技术行业的公司，信息产业部和原国家质量技术监督局联合实施。<br /><br />GB 18030字符集标准解决汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位，收录了27484个汉字，覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。并且与Unicode 3.0版本兼容，填补Unicode扩展字符字汇“统一汉字扩展A”的内容。并且与以前的国家字符编码标准（GB2312，GB13000.1）兼容。<br /><br />3．编码方法<br /><br />GB 18030标准采用单字节、双字节和四字节三种方式对字符编码。单字节部分使用0×00至0×7F码(对应于ASCII码的相应码)。双字节部分，首字节码从0×81至0×FE，尾字节码位分别是0×40至0×7E和0×80至0×FE。四字节部分采用GB/T 11383未采用的0×30到0×39作为对双字节编码扩充的后缀，这样扩充的四字节编码，其范围为0×81308130到0×FE39FE39。其中第一、三个字节编码码位均为0×81至0×FE，第二、四个字节编码码位均为0×30至0×39。<br /><br />4．包含的内容<br /><br />双字节部分收录内容主要包括GB13000.1全部CJK汉字20902个、有关标点符号、表意文字描述符13个、增补的汉字和部首/构件80个、双字节编码的欧元符号等。　　四字节部分收录了上述双字节字符之外的，包括CJK统一汉字扩充A在内的GB 13000.1中的全部字符。<br /><br />Unicode字符集<br /><br />1．名称的由来<br /><br />Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字符集的简称，是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统，支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发，1994年正式公布，最新版本是2005年3月31日的Unicode 4.1.0。<br /><br />2．特征 <br /><br />Unicode是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码，以满足跨语言、跨平台进行文本转换、处理的要求。<br /><br />3．编码方法<br /><br />Unicode 标准始终使用十六进制数字，而且在书写时在前面加上前缀“U+”，例如字母“A”的编码为 004116 和字符“€”的编码为 20AC16。所以“A”的编码书写为“U+0041”。<br /><br />4．UTF-8 编码<br />UTF-8是Unicode的其中一个使用方式。 UTF是 Unicode Translation Format，即把Unicode转做某种格式的意思。<br /><br />UTF-8便于不同的计算机之间使用网络传输不同语言和编码的文字，使得双字节的Unicode能够在现存的处理单字节的系统上正确传输。<br /><br />UTF-8使用可变长度字节来储存 Unicode字符，例如ASCII字母继续使用1字节储存，重音文字、希腊字母或西里尔字母等使用2字节来储存，而常用的汉字就要使用3字节。辅助平面字符则使用4字节。<br /><br />5．UTF-16 和 UTF-32 编码<br />UTF-32、UTF-16 和 UTF-8 是 Unicode 标准的编码字符集的字符编码方案，UTF-16 使用一个或两个未分配的 16 位代码单元的序列对 Unicode 代码点进行编码；UTF-32 即将每一个 Unicode 代码点表示为相同值的 32 位整数。</span>
		</p>
<img src ="http://www.blogjava.net/spark/aggbug/72748.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-09-29 11:10 <a href="http://www.blogjava.net/spark/archive/2006/09/29/72748.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中的io系统总结.</title><link>http://www.blogjava.net/spark/archive/2006/09/29/72733.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Fri, 29 Sep 2006 02:17:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/09/29/72733.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/72733.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/09/29/72733.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/72733.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/72733.html</trackback:ping><description><![CDATA[
		<p>java中的io中的（input/output）stream无非就是包括基于字符的stream、基于字节的stream和把字节导向的stream转换<br />字符为导向的stream的stream。（很难理解么？）<br />以字节为导向的stream------InputStream/OutputStream<br />InputStream 和 OutputStream是两个abstact类，对于字节为导向的stream都扩展这两个鸡肋（基类^_^）;<br />--InputStream<br />ByteArrayInputStream -- 把内存中的一个缓冲区作为InputStream使用.<br /><br />construct---ByteArrayInputStream(byte[])创建一个新字节数组输入流，它从指定字节数组中读取数据。<br />---ByteArrayInputStream(byte[], int, int) 创建一个新字节数组输入流，它从指定字节数组中读取数据。<br />---mark::该字节数组未被复制。<br /><br />StringBufferInputStream -- 把一个String对象作为InputStream .<br />注释：不推荐使用 StringBufferInputStream 方法。 此类不能将字符正确的转换为字节。<br />同 JDK 1.1 版中的类似，从一个串创建一个流的最佳方法是采用 StringReader 类。 <br /><br />construct---StringBufferInputStream(String) 据指定串创建一个读取数据的输入流串。<br /><br />FileInputStream -- 把一个文件作为InputStream，实现对文件的读取操作 <br /><br />construct---FileInputStream(File) 创建一个输入文件流，从指定的 File 对象读取数据。<br />---FileInputStream(FileDescriptor) 创建一个输入文件流，从指定的文件描述器读取数据。<br />---FileInputStream(String) 创建一个输入文件流，从指定名称的文件读取数据。<br /><br />method ---- read() 从当前输入流中读取一字节数据。 <br />read(byte[]) 将当前输入流中 b.length 个字节数据读到一个字节数组中。 <br />read(byte[], int, int) 将输入流中 len 个字节数据读入一个字节数组中。<br /><br />PipedInputStream：实现了pipe的概念，主要在线程中使用. 管道输入流是指一个通讯管道的接收端。<br />一个线程通过管道输出流发送数据，而另一个线程通过管道输入流读取数据，<br />这样可实现两个线程间的通讯。<br /><br />PipedInputStream() 创建一个管道输入流，它还未与一个管道输出流连接。 <br />PipedInputStream(PipedOutputStream) 创建一个管道输入流, 它已连接到一个管道输出流。 <br /><br />SequenceInputStream：把多个InputStream合并为一个InputStream .“序列输入流”类允许应用程序把几个输入流连续地合并起来，<br />并且使它们像单个输入流一样出现。每个输入流依次被读取，直到到达该流的末尾。<br />然后“序列输入流”类关闭这个流并自动地切换到下一个输入流。 <br />SequenceInputStream(Enumeration) 创建一个新的序列输入流，并用指定的输入流的枚举值初始化它。 <br />SequenceInputStream(InputStream, InputStream) 创建一个新的序列输入流，初始化为首先 读输入流 s1, 然后读输入流 s2。<br /><br />--OutputSteam<br /><br />ByteArrayOutputStream：把信息存入内存中的一个缓冲区中.该类实现一个以字节数组形式写入数据的输出流。<br />当数据写入缓冲区时，它自动扩大。用 toByteArray() 和 toString() 能检索数据。 <br /><br />construct --- ByteArrayOutputStream() 创建一个新的字节数组输出流。<br />--- ByteArrayOutputStream() 创建一个新的字节数组输出流。 <br />--- ByteArrayOutputStream(int) 创建一个新的字节数组输出流，并带有指定大小字节的缓冲区容量。 <br />toString(String) 根据指定字符编码将缓冲区内容转换为字符串，并将字节转换为字符。 <br />write(byte[], int, int) 将指定字节数组中从偏移量 off 开始的 len 个字节写入该字节数组输出流。 <br />write(int) 将指定字节写入该字节数组输出流。 <br />writeTo(OutputStream) 用 out.write(buf, 0, count) 调用输出流的写方法将该字节数组输出流的全部内容写入指定的输出流参数。 <br /><br />FileOutputStream:文件输出流是向 File 或 FileDescriptor 输出数据的一个输出流。<br /><br />FileOutputStream(File) 创建一个文件输出流，向指定的 File 对象输出数据。 <br />FileOutputStream(FileDescriptor) 创建一个文件输出流，向指定的文件描述器输出数据。 <br />FileOutputStream(String) 创建一个文件输出流，向指定名称的文件输出数据。 <br />FileOutputStream(String, boolean) 用指定系统的文件名，创建一个输出文件。<br /><br />PipedOutputStream:管道输出流是指一个通讯管道的发送端。 一个线程通过管道输出流发送数据，<br />而另一个线程通过管道输入流读取数据，这样可实现两个线程间的通讯。<br /><br />PipedOutputStream() 创建一个管道输出流，它还未与一个管道输入流连接。 <br />PipedOutputStream(PipedInputStream) 创建一个管道输出流，它已连接到一个管道输入流。<br /><br /><br />以字符为导向的stream Reader/Writer</p>
		<p>以Unicode字符为导向的stream，表示以Unicode字符为单位从stream中读取或往stream 中写入信息。<br />Reader/Writer 为abstact类<br />以Unicode字符为导向的stream包括下面几种类型： </p>
		<p>－－ Reader</p>
		<p>1) CharArrayReader：与ByteArrayInputStream对应 <br />CharArrayReader(char[]) 用指定字符数组创建一个 CharArrayReader。<br />CharArrayReader(char[], int, int) 用指定字符数组创建一个 CharArrayReader。<br /><br />2) StringReader：与StringBufferInputStream对应 <br />StringReader(String) 创建一新的串读取者。<br />3) FileReader：与FileInputStream对应 </p>
		<p>4) PipedReader：与PipedInputStream对应 </p>
		<p>－－ Writer</p>
		<p>1) CharArrayWrite：与ByteArrayOutputStream对应 <br />2) StringWrite：无与之对应的以字节为导向的stream <br />3) FileWrite：与FileOutputStream对应 <br />4) PipedWrite：与PipedOutputStream对应 </p>
		<p>两种不现导向的stream之间的转换<br />InputStreamReader和OutputStreamReader：把一个以字节为导向的stream转换成一个以字符为导向的stream。<br />一个 InputStreamReader 类是从字节流到字符流的桥梁：它读入字节，并根据指定的编码方式，将之转换为字符流。<br />使用的编码方式可能由名称指定，或平台可接受的缺省编码方式。<br /><br />InputStreamReader 的 read() 方法之一的每次调用，可能促使从基本字节输入流中读取一个或多个字节。<br />为了达到更高效率，考虑用 BufferedReader 封装 InputStreamReader，<br />BufferedReader in = new BufferedReader(new InputStreamReader(System.in));<br /><br />InputStreamReader(InputStream) 用缺省的字符编码方式，创建一个 InputStreamReader。 <br />InputStreamReader(InputStream, String) 用已命名的字符编码方式，创建一个 InputStreamReader。<br /><br />OutputStreamWriter 将多个字符写入到一个输出流，根据指定的字符编码将多个字符转换为字节。 <br />每个 OutputStreamWriter 合并它自己的 CharToByteConverter, 因而是从字符流到字节流的桥梁。<br /><br />FilterInputStream、RandomAccessFile 见例子。<br />ObjectInputStream 、 ObjectOutputStream见另外blog。</p>
		<p>
				<br />Java IO的一般使用原则：</p>
		<p>一、按数据来源（去向）分类：<br />1、是文件： FileInputStream, FileOutputStream, FileReader, FileWriter<br />2、是byte[]：ByteArrayInputStream, ByteArrayOutputStream<br />3、是Char[]: CharArrayReader, CharArrayWriter<br />4、是String: StringBufferInputStream, StringReader, StringWriter<br />5、网络数据流：InputStream, OutputStream, Reader, Writer</p>
		<p>二、按是否格式化输出分：<br />1、要格式化输出：PrintStream, PrintWriter</p>
		<p>三、按是否要缓冲分：<br />1、要缓冲：BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter</p>
		<p>四、按数据格式分：<br />1、二进制格式（只要不能确定是纯文本的）: InputStream, OutputStream及其所有带Stream结束的子类<br />2、纯文本格式（含纯英文与汉字或其他编码方式）；Reader, Writer及其所有带Reader, Writer的子类</p>
		<p>五、按输入输出分：<br />1、输入：Reader, InputStream类型的子类<br />2、输出：Writer, OutputStream类型的子类</p>
		<p>六、特殊需要：<br />1、从Stream到Reader,Writer的转换类：InputStreamReader, OutputStreamWriter<br />2、对象输入输出：ObjectInputStream, ObjectOutputStream<br />3、进程间通信：PipeInputStream, PipeOutputStream, PipeReader, PipeWriter<br />4、合并输入：SequenceInputStream<br />5、更特殊的需要：PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader</p>
		<p>决定使用哪个类以及它的构造进程的一般准则如下（不考虑特殊需要）：<br />首先，考虑最原始的数据格式是什么： 原则四<br />第二，是输入还是输出：原则五<br />第三，是否需要转换流：原则六第1点<br />第四，数据来源（去向）是什么：原则一<br />第五，是否要缓冲：原则三 （特别注明：一定要注意的是readLine()是否有定义，有什么比read, write更特殊的输入或输出方法）<br />第六，是否要格式化输出：原则二</p>
<img src ="http://www.blogjava.net/spark/aggbug/72733.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-09-29 10:17 <a href="http://www.blogjava.net/spark/archive/2006/09/29/72733.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java程序的输入与输出</title><link>http://www.blogjava.net/spark/archive/2006/09/28/72496.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Thu, 28 Sep 2006 02:41:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/09/28/72496.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/72496.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/09/28/72496.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/72496.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/72496.html</trackback:ping><description><![CDATA[这一章我们讨论Java程序的输入与输出。Java在I/O方面提供了众多支持，使我们的工作得到大大的简化。我们将学习利用这些支持以完成各种复杂的输入、输出。<br /><br />7.1 理解java.io的类继承关系<br /><br />　　首先，让我们考察Java提供的常用输出输出流类(图7.1)。由于类的数目较多，没有列出1.1版本中新增的字符流类。在图7.2中，我们把字符流类与字节流类作了对比，在该图中可以看到字符流类的继承关系。接口和异常类也被省略了。<br />　　　　　　　　　　　　　　　　　　　　　　　　┌BufferedInputStream<br />　　　　　　　　　　　　　　　　　　　　　　　　├DataInputStream<br />　　　　　　　　　　　　　　┌FilterInputStream┼LineNumberInputStream<br />　　　　　　　　　　　　　　├FileInputStream　└PushbackInputStream<br />　　　　　　　　　　　　　　├ByteArrayInputStream<br />　　　　　┌InputStream──┼PipedInputStream<br />　　　　　│　　　　　　　　├SequenceInputStream<br />　　　　　│　　　　　　　　├StringBufferInputStream<br />　　　　　│　　　　　　　　└ObjectInputStream　┌BufferedOutputStream<br />　　　　　│　　　　　　　　 ┌FilterOutputStream┼DataOutputStream<br />　　Object┤　　　　　　　　 ├FileOutputStream　└PrintStream<br />　　　　　├OutputStream──┼ByteArrayOutputStream<br />　　　　　├File　　　　　　 ├PipedOutputStream<br />　　　　　├FileDescriptor　└ObjectOutputStream<br />　　　　　├ObjdecStreamClass<br />　　　　　├RandomAccessFile<br />　　　　　└StreamTokenizer<br />　　　　图7.1 java.io包中常用类层次图(不含字符流类)<br />　　图7.1中包含了许多的输入和输出类(这还不包括我们欢天喜地上要讲到的字符流输入输出类)。为了能正确运用它们，我们必须对它们的功能和关系有个大根式的认识。<br /><br />　　7.1.1 字节流与字符流<br /><br />　　第二章中提到了Unicode字符集和ASCII字符集。前者用16位来表示一个字符，而者用8位来表示一个字符。Unicode字符集可表示的符号显然比ASCII字符集多得多，它可以表示世界上大多数语言的符号。<br />　　在JDK1.0x版本中，只提供了字节流输入输出类。也就是说，输入输出的数据以字节为读写单位。这就给操作一些双字节字符带来了困难。比如汉字，用一个字节是不能表示，这就使Java程序的汉化成了问题。例如，用1.0x版的JDK开发一个文本编辑器，就可能出现这样的情况：用剪贴板可以把汉字贴进文本域却无法用键盘向文本域输入汉字字符。这就是标准输入流每次只接收了一个汉字的第一字节引起的。<br />　　JDK1.1版对输入输出作了改进，为字节流输入输出类增加了对应的字符流输入输出类这样，程序员就可以根据实际情况选用合适的类。<br />　　字符流I/O有其显示而易见的好处。首先它可以适用于世界上大部分语言，从而为Java程序的本地化带来方便。其次，一次读一个字符(16位)比读一个字节来得快，一般情况下可以弥补将数据按当前语言标准编码、解码的时间开销。<br />　　字节流I/O类和字符流I/O类的命名有其对应关系。字节输入流类的名字以“InputStream”结尾。而字符输入流类的名字以“Reader” 结尾。字节输出流类的名字后缀为“OutputStream”，而字符输出流类的名字后缀为“Writer”。<br />　　为了在适当的时候能把这两种流类联系起来，API中设置了两个类，充当二者的桥梁。InputStreamReader根据特定的编码规则从字节流创建相应的字符流，而Output。StreamWriter则根据编码规则从字符流读取字符，把它们转化为字节，写入字节流中。<br />　　下面列出两种流类的对应关系(图7.2)。其中，左边一栏是按继承关系排列的字符流类，右边是对应的字节流类。<br />　　Reader　　　　　　　　　　　 InputStream<br />　　　├BufferedReader　　　　　 BufferedInputStream<br />　　　│　　└LineNumberReader　 LineNumberReader<br />　　　├CharArrayReader　　　　　ByteArrayInputStream<br />　　　├InputStreamReader　　　　 (none)<br />　　　│　　└FileReader　　　　　FileInputStream<br />　　　├FilterReader　　　　　　　FilterInputStream<br />　　　│　　└PushbackReader　　　PushbackInputStream<br />　　　├PipedReader　　　　　　　 PipedInputStream<br />　　　└StringReader　　　　　　　StringBufferInputStream<br /><br />　　Write　　　　　　　　　　　　　OutputStream<br />　　├BufferedWriter　　　　　　　BufferedOutputStream<br />　　├CharArrayWriter　　　　　　　ByteArrayOutputStream<br />　　├OutputStreamWriter　　　　　(none)<br />　　│　　└FileWriter　　　　　　　FileOutputStream<br />　　├FilterWriter　　　　　　　　　FilterOutputStream<br />　　├PrintWriter　　　　　　　　　PrintStream<br />　　├PipedWriter　　　　　　　　　PipedOutputStream<br />　　└StringWriter　　　　　　　　 (none)<br />　　　　图7.2字符流类与字节流类的对应关系<br /><br />　　另外，1.1版的API中，对一些1.0x版本中已存在的类也进行了微小的修改，这主要是因为有类对字节和字符的转换可能产生错误。如以下构造函数和方法标记为过时：<br />　　Sting　　DataInputStream.readLine()<br />　　InputStream　　Runtime.getLocalizedInputStream(InputStream)<br />　　OutputStream　Runtime.getLocalizedOutputStream(OutputStream)<br />　　　　　　　　　StreamTokenizer(InputStream)<br />　　　　　　　　　String(byte ascii[],int hibyte,int offset,int count)<br />　　　　　　　　　String(byte ascii[],int hibyte)<br />　　　　void 　　　String.getBytes(int srcBegin,int srcEnd,byte dst[],int dstBegin)<br />　　另外，添加了如下构造函数和方法：<br />　　　　　　　　　StreamTokenizer(Reader)<br />　　byte[]　　　　　String.getBytes()<br />　　void　　　　　Throwable.printStackTrace(PrintWriter)<br />　　当程序员使用旧的API编程时，可以用<br />　　javac -deprecation(文件名)<br />　　来进行编译，这样编译器会给出较为详细的警告信息。编程人员可根据这些信息查找新文档，以获知新版本中的替代方法。<br />　　本章的例子都是依据1.1版本的API编写的。<br /><br />　　7.1.2 输入输出类的分类<br /><br />　　java.io包中的类各有各的分工，粗略说来可以分为以下几类：<br />　　文件I/O：有三类。对字节流类来说，包括把文件作为源进行流式输入的FileInputStream类；把文件作为目的进行流式输出的 FileOutputStream类；若你想随机存取文件，即在文件的任意位置读、数据，那么可以使用RandomAccessFile类。字符类则有 FileReader和FileWriter类。它们的功能对应于前两个字节流类。<br />　　除此之外，还有两个类是与文件访问有关的，确切地说其功能更近于文件管理。它们是File类，用以访问文件或目录；FileDescriptor则封装了操作系统用以追踪被访问文件的信息。<br />　　内存缓冲区I/O：字节流类有ByteArrayInputStream类，将字节数组转化为输入流，是从一个字符串创建输入流，与 ByteArrayInputStream异曲同工，帮也归入此类别。相应地，字符流类有CharArrayReader, CharArrayWriter,StringReader,此外还多一个StringWriter用来写字符串。<br />　　余下一些类可以不同方式存取流中的数据。字节流类中，DataInputStream和DataOutputStream因其能对流中的不同类的对象分别操作而显得与众不同；ObjectInputStream和ObjectOutputStream能把若干完整的对象按选定的格式进行读写，但要求被操作对象实现Serializable接口；BufferedInputStream和BufferedOutputStream可以对流数据进行缓冲，实现类似“预输入”、“缓输出”的功能；LineNumberInputStream跟踪输入流中的行数；PusthbackInputStream提供了一个“可推回”的流，从这个流中读了数据后，还可以将它放回流中；PrintStream类提供了许多重载的方法以简化输出。对应的字符流类可以从 7.1.1节的对应关系中查出。<br />　　除了上述类以外，Java还有种特殊的I/O类——管道I/O类。它们是专门为线程通讯预备的。管道提供了自动同步机制，可以防止线程通讯中的数据混乱。<br />　　至引相信读者已对各个I/O类的功能有所了解。这里再解释一下过滤器I/O 推广java.io包中有不少类是过滤器类，它们都是从FilterInputStream或FilterOutputStream之中派生而来(参见图 7.1)。在字符流中，也有类似的类，但并不像字节流类一样必然从某个公共的过滤器父类派生而来。<br />　　过滤器(Filter)形成的类对象从一个流中读入数据，写入另一个，就像一个流经过过滤产生另一个流一样。过滤器可以联合使用，也就是说“过滤”过的流可以再经其它过滤器“过滤”，过滤器型类的共性是：<br />　　(1)用和种流为参数的构造，且输入型过滤器用输入流，输出型过滤器用输出流；<br />　　(2)无明显的源/目的限制；<br />　　(3)流中数据的内容“多少”并未改变，只可能性质略有变化。<br />读者不妨以这几条标准去理解过滤器I/O类与其子类，并在以后的示例中加以验证。<br /><br />7.2 输入流与输出流<br /><br />　　字节输入流InputStream与字节输出流OUtputStream是两个抽象类。它们为java.io包中名目繁多的字节输入和输出流打下了基础。由于是抽象类，它们不能被实例化(也就是说，不能得到其对象)，但它们的方法可以被派生类所继承或重写。<br />　　对于字符流，相应的流类是Reader和Writer。由于它们的方法与InputStream和OutputStream对应，只是把对字节的操作改为对字符的操作，这里不再重复介绍。但为了读者能够对它们的对应关系有个基本认识，在本节末尾附上Reader类的方法列表，请读者参照。<br />　　InputStream的方示如下：<br />　　■public abstract int read() throws IOException<br />　　■public int read(byte b[]) throws IOException<br />　　■public int read(byte b[],int offset,int length) throws IOException<br />　　功能为从输入流中读数据。这一方法有几种重载形式，可以读一个字节或一组字节。当遇到文件尾时，返回-1。最后一种形式中的offset是指把结果放在b[]中从第offset个字节开始的空间，length为长度。<br />　　■public int available() throws IOException<br />　　输入流共有多少字节可读。注意此方法对InputStream的各派生类不一定都有效，有时会有返回零字节的错误结果。<br />　　■public void close() throws IOException<br />　　关闭输入流并释放资源。<br />　　■public boolean markSupperted()<br />　　返回布尔值，说明此流能否做标记。<br />　　■public synchronized void mark(int readlimit)<br />　　为当前流做标记。其参数说明在标记失效前可以读多少字节，这个值通常也就设定了流的缓冲区大小。<br />　　■public synchronized void reset() throws IOException<br />　　返回到上一次做标记处。<br />　　■public long skip (long n) throws IOEnception<br />从输入流跳过几个字节。返回值为实际跳过的字节数。<br />　　对于“mark”我们还需解释一下。输入流提供“标记”这一机制，使人们可以记录流中某些特定的位置，并能重复读部分内容。支持“mark”就必须要求当前流有一定大小的缓冲区，存放部分数据，即从标记点到当前位置的数据。当这一缓冲区装满溢出，我们就无法追踪到上一个标记处的数据了，这就称之为“标记失效”。若想用reset()返回到一个失效的标记处，将会发生输入输出异常(IOException)。<br />　　OutputStream的方法如下。各方法均可能抛出输入输出异常(throws IOException)。<br />　　■public abstract void write(int b)<br />　　■public void write(byte b[])<br />　　■public void write(byte b[],int offset,int length)<br />　　这三个重载形式都是用来向输出流写数据的。具体每个不甘落后　作用，读者可根据前文read()方法对照之。<br />　　■public void flush()<br />　　清除缓冲区，将缓冲区内尚未写出的数据全部输出。若要继承OutputStream类，这个方法必须重写，因为OutputStream中的方法未做任何实物性工作。<br />　　■public void close()<br />　　关闭输出流，释放资源。<br />　　以上提到的这些方法，在下面的章节中将有不少被运用，读者可根据实例领会它们。<br />　　附Reader类的方法列表。<br />　　构造函数：<br />　　■protected Reader()　<br />　　■protected Reader(object lock)<br />　　方法：<br />　　■public int read() throws IOException<br />　　■public int read(char cbuf[]) throws IOException<br />　　■public abstract int read(char cbuf[],int off,int len)throws IOException<br />　　■public long skip(long n) throws IOException<br />　　■public boolean ready() throws IOException //判断流是不可以读<br />　　■public boolean mark(int readAheadLimit)throws IOException<br />　　■public void reset() throws IOException<br />　　■public abstract void close() throws IOException<br /><br />7.3 文件I/O<br /><br />　　这一节中我们将结合实例讨论File，FileInputStream，FileOutputStream，FileDescriptor和RandomAccessFile类的方法与使用。<br /><br />　　7.3.1 一个文件I/O实例<br /><br />　　让我们用一个例子来演示对文件的输入输出(例7.1)。图7.3中列出了这个例子的运行结果。<br />　　例7.1 fileIODemo.java。<br />　　1:import java.io.*;<br />　　2:import java.lang.*;<br />　　3:<br />　　4: public class fileIODemo{<br />　　5: 　public static void main(String args[]){<br />　　6: 　　try{<br />　　　　　//创建输入输出流<br />　　7:　　　FileInputStream inStream = new FileInputStream("text.src");<br />　　8:　　　FileOutputStream outStream = new FileOutputStream("text.des");<br />　　　　　　//读文并写入输出流<br />　　9: 　　　　boolean eof = false;<br />　　10:　　　　while(!eof){<br />　　11:　　　　　int c = inStream.read();<br />　　12:　　　　　if(c==-1) eof = true;<br />　　13:　　　　　outStream.write((char)c);<br />　　14:　　　　}<br />　　15:　　　　inStream.close();<br />　　16:　　　　outStream.close();<br />　　17:　　　}catch(FileNotFoundException ex){<br />　　18:　　　　System.out.println("Error finding the files");<br />　　19:　　　}catch(IOException ex){<br />　　20:　　　System.out.println("IOException occured.");<br />　　21:　　}<br />　　　　//获取文件管理信息<br />　　22:　　File file = new File("text.des");<br />　　23:　　System.out.println("Parent Directory:"+file.getParent());<br />　　24:　　System.out.println("Path:"+file.getPath());<br />　　25:　　System.out.println("File Name:"+file.getName());<br />　　26:　　try{<br />　　　　　//创建RandomAccessFile对象，以便随机读写。"rw"代表可读可写<br />　　27:　　　RandomAccessFile rafile = new RandomAccessFile("text.des","rw");<br />　　　　　//指针置到文件头<br />　　28:　　　rafile.seek(0);<br />　　29:　　　boolean eof=false;<br />　　30:　　　System.out.println("The content from very head:");<br />　　　　　//读文件<br />　　31:　　　while(!eof)｛<br />　　32:　　　int c = rafile.read();<br />　　33:　　　　if(c==-1) eof = true;<br />　　34:　　　　else System.out.print((char)c);<br />　　35:　　　}<br />　　　　　//下两行把读指针置到第三字节<br />　　36:　　　rafile.seek(0);<br />　　37:　　　rafile.skipBytes(3);<br />　　38:　　　System.out.println("\nThe pointer's position:"+rafile.getFilePointer());<br />　　39:　　　System.out.println("The content from current position:");<br />　　40:　　　eof=false;<br />　　41:　　　while(!eof){<br />　　42:　　　　int c=rafile.read();<br />　　43:　　　　if(c==-1) eof=true;<br />　　44:　　　　else System.out.print((char)c);<br />　　45:　　　}<br />　　　　　//强制输出缓冲区中所有内容<br />　　46:　　　System.out.flush();<br />　　47:　　　rafile.close();<br />　　48:　　}catch(IOException ex){<br />　　49:　　　System.out.println("RandomAccessFile cause IOException!");<br />　　50:　　}<br />　　51:　}<br />　　52:}<br />　　例7.1的运行结果如下：<br />　　(略)<br />　　为了充分展示与文件I/O相关的类的作用，我们的例子中有一些冗余的东西。我们的这个程序位于C:\BookDemo\ch07路径下(见例7.1行 7)，此路径又有一个子上当text，其中有文件text.src。运行此程序，将在C:\bookDemo\ch07下创建一个新文件 text.des，text.src的内容被写信此文件。下面的段对File类的演示说明了文件的部分管理信息。然后我们又使用了 RandomAccessFile，试验了文件在指定位置的读写。<br />　　第46行的Sytem.out.flush()语句不可以被省略，读者不妨去掉它试一试。你会发现，有一部分输出信息不知道到哪儿去了。实际上，flush()的作用就是把缓冲区中的数据全部输出，我们棣输出流输出以后，某些输出流(有缓冲区的流)只是把数据写进了缓冲区而已，不会马上写到我们要求的目的地。如果不像例子中一样强制输出，部分数据可以就来不及在程序结束前输出了。<br />　　细心的读者或许要问：为什么第一次用ReadomAccessFile读文件时，输出语句后面没有flush()呢？岂非自相矛盾吗？原来， System.out是PrintStream类的对象(关于PrintStream后有缓冲区中的内容清除出去。因此许多地方就不必加flush() 了。PrintStream的这个特点，在创建其对象时是可以去掉(disable)的。<br />　　这个程序中用到了IOException和FileNotFoundException两个异常。后者是从前者派生出来的，因此，如果去年程序中的所有try、catch，而在main()方法开头加上throws IOException，哪样可以。但这样不好区分各种不同的异常情况，即使找不到我们需要的text.src文件，也不会有任何信息显示。这无疑是一种不良的编程风格。因此我们提倡对各个异常分别处理，这样对出错情况可以很地掌握。<br /><br />　　7.3.2 文件输入输出的类库支持<br /><br />　　下面我们逐一介绍例7.1中用到的各个类。<br />　　1.File类<br />　　File类的构造函数有三个。分别根据文件名、文件路径与文件名、文件对象(目录)与文件名创建实例。即：<br />　　■public File(String path)<br />　　■public File(String path,String name)<br />　　■public File(File dir,String name)<br />　　除了例子中用到的以外，还有许多方法，下面仅列出较常用的：<br />　　■public boolean exists()判断文件是否存在<br />　　■public boolean canRead()判断文件是否可读<br />　　■public long length()返回文件长度<br />　　■public boolean mkdir()创建目录<br />　　■public boolean renameTo(File dest)文件改名<br />其中，后三个方法可能抛出I/O异常。<br />　　2.FileInputStream类<br />　　它是文件输入流类<br />　　构造函数有三个：<br />　　■public FileInputStream(String fileName) throws FileNotFoundException<br />　　■public FileInputStream(File file) throws FileNotFoundException<br />　　■public FileInputStream(int fd) throws FileNotFoundException<br />　　三个构造函数分别根据文件名、文件对象、文件描述符创建一个文件输入流。例子中用的是第一种。<br />　　方法：<br />　　read()、skip()、available() 、close()分别重写了抽象类InputStream的同名方法，功能如前所述。此外还有：<br />　　■public final int getFD()<br />　　返回相应的文件描述符。<br />　　■protedted void finalize() throws IOException<br />　　关闭输入流，并收集无用内存空间。<br />　　现在我们必须介绍一下文件描述符类FileDescriptor。这个类用于访问操作系统维护的文件描述符(也称句柄)。但这个类产不能访问很多信息。它只提供了两个方法，即valid()，以判断文件描述符是否有效；sync()，用以同步系统缓冲区。<br />　　3.FileOutputStream类<br />　　文件输出流。三个构造函数，其参数、返回值及异常均与FileInputStream的相对应。write()、close()方法重写了 OutputStream的同名方法。getFD()与finalize()功能与InputStream的类似。<br />　　4.ReadomAccessFile类<br />　　该类用于随机访问文件。<br />　　构造函数有三种：<br />　　■public RandomAccessFile(String Filename,String mode) throws IOException<br />　　■public RandomAccessFile(int FD) throws IOException<br />　　■public RandomAccessFile(File file,String mode)throws IOException<br />　　由上可见，我们可以用文件名加读写方式、文件描述符、File对象加读写方式来创建其对象。其中读写方式用“r”表示只读，“rw”表示可读写，等等。用过Ｃ语言的读者对此应当不会陌生。<br />　　此类的成员方法很多。除了重写InputStream的read()方法之外，还可以读、写一个布尔值、一个字节、一个整数......等对象。这些方法都不可重写，并且抛出Ｉ／Ｏ异常(IOException)。讯方法名为“read”加类型名(类型名的第一字母大写)，写方法名为“write”加类型名。如<br />　　readInt()读一个整型数<br />　　writeDouble()写一个双精度浮点数<br />等。另外还有文件指针的操作，如skipBytes(int n)等。<br />　　有了以上这些类的支持，处理文件输入输出和维护文件就容易多了。<br /><br />7.4 内存缓冲区<br /><br />　　内存缓冲区I/O，对字节流来说指的是ByteArrayInputStream和ByteArrayOutputStream类的运用。此外， StringBufferInputStream与ByteArrayInputStream用法相似将一并介绍。对字符流不另举例，它们使用与字节流类类似。<br /><br />　　7.4.1 程序示例<br /><br />　　同上一节一样，我们还是先看一个例子(例7.2)<br />　　例7.2 ByteArrayIODemo.java<br />　　1:import java.io.*;<br />　　2:<br />　　3: public class ByteArrayIODemo{<br />　　4: 　public static void main(String args[]) throws IOException{<br />　　 　　　String s ="This a test";<br />　　5: 　　byte buffer[]=s.getBytes();<br />　　6: 　　ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();<br />　　7：　　for(int i=0;i&lt;buffer.length;++i)<br />　　8: 　　　byteArrayOut.write(buffer[i]);<br />　　//由字节数组创建字节输入流<br />　　9: 　　ByteArrayInputStream inStream = new<br />　　　　　　　ByteArrayInputStream(byteArrayOut.toByteArray());<br />　　//读写<br />　　10:　　boolean eof=false;<br />　　11:　　while(!eof){<br />　　12:　　　int c=inStream.read();<br />　　13:　　　if(c==-1) eof=true;<br />　　14:　　　　else System.out.print((char)c);<br />　　15:　　}<br />　　16:　　System.out.println("\nThe'writeTo' method can produce same results.");<br />　　//用ByteArrayOutputStream的writeTo()方法写<br />　　17:　　byteArrayOut.writeTo(System.out);<br />　　18:　　byteArrayOut.close();<br />　　//available()与reset()的使用<br />　　19:　　System.out.println("\nThe buf of inStream has the length(before<br />　　　　seset):"+inStream.available());<br />　　20:　　inStream.reset();<br />　　21:　　System.out.println("\nThe buf of inStream has the length:"+inStream.available());<br />　　22:　　inStream.close();<br />　　23:　}<br />　　24:}<br />　　该程序的运行结果：(略)<br />　　这个例子看来相对简单些。我们先把字节数组的内容写进一个字节数组输出流对象。然后，用一个字节数组输入流对象读数据，再用System.out输出。程序显示了writeTo()方法的作用。另外，我们还在reset()前、后用了两疚available()方法，请注意两方法先后产生的不同结果。这个例子主要用来演示字节数组I/O的部分方法。<br /><br />　　7.4.2缓冲区I/O的类库支持<br /><br />　　看过了例子，我们接下来介绍有关的类。<br />　　1.ByteArrayInputStream类<br />　　这个类用于从一个<br />　　字节数组取得输入数据。<br />　　它有两个构造函数：<br />　　■public ByteArrayInputStream(byte Buf[])<br />　　由字节数组创建相应的输入流。<br />　　■public ByteArrayInputStream(byte buf[],int offset,int length)<br />　　由字节数组中起点为offset长为length的一段创建输入流。<br />　　成员变量：<br />　　protected byte buf[]数据缓冲区<br />　　protected int pos 缓冲区中当前位置<br />　　protected int count缓冲区中字节数目<br />　　该类的成员方法都是同步(synchronized)的。<br />　　■public synchronized int read()<br />　　读一个字节。<br />　　■public synchronized int read(byte b[],int offset,intrlength)<br />　　读取多个字节，返值一般为读到的字节数。但读到末尾时返回-1。<br />　　■public synchronized long skip(long n)<br />　　跳过n个字节。若返回值不等于n，可能是遇到末尾。<br />　　■public synchronized int available()<br />　　求得缓冲区内字节数目。<br />　　■public synchronized void reset()<br />　　该指针重新设置到输入流的开始处。注意，这个reset()与InputStream中的功能不同。它并不作用于标记。<br />　　2.ByteArrayOutputStream类<br />　　这个类用于把数据写进字节数组(缓冲区)。<br />　　构造函数：<br />　　■public ByteArrayOutputStream()<br />　　■public ByteArrayOntput Stream(int size)<br />　　其中size指定缓冲区的初始大小(它是可以动态增长的)。<br />　　成员变量：<br />　　protected byte buf[]缓冲区<br />　　protected int count缓冲区大小<br />　　方法：<br />　　■public synchronized void write(int b)<br />　　写一个字节。<br />　　■public synchronized void write(byte b[],int offset,int length)<br />　　把数组b中由offset开始长为length的一部分写入缓冲区。<br />　　■public synchronized void writeTo(OutputStream out)throws IOException<br />　　把缓冲区内容写到另一输出流out。<br />　　■public synchronized void reset()<br />　　指针定到缓冲区开始。当然，以后再写入也就是从缓冲区的开始位置重写了，原有的内容就都清掉了。<br />　　■public syschronized byte[] toByteArray()<br />　　将缓冲区内容作为一个字节数组返回。<br />　　■public int size()<br />　　当前缓冲区大小。<br />　　■public string toString()<br />　　■public string toString(int hibyte)<br />　　把缓冲区内容转化为字符串。其中hibyte指把字符(通常是８位的ASCII字符)转为16位的Unicode值时，高八的值。<br />　　3.StringBufferInputStream类<br />　　它的构造函数以一个字符串为参数，原型为：<br />　　■public StringBufferInputStream(String s)<br />　　其余成员变量及方法均与ByteArrayInputStream的同名且基本功能相同，此不赘述。<br />　　这三个类的共性是内存中开辟了一段空间来做I/O缓冲区，故称缓冲区I/O类。<br /><br />7.5 过滤器I/O<br /><br />　　这一节涉及的类较多，但我们可以结合几个例子逐一介绍。<br />　　在第一节中，我们已经谈了一些过滤器类的特性。过滤器是可以“连接”的，即一个数据流经过过滤后，其结果可以再次过滤。我们可以使用这样一串过滤器中的任一个方法来完成某种特殊的操作。关于这一点在第二个例子中有更明白的阐述。<br /><br />　　7.5.1 例1:各类数据的I/O<br /><br />　　第一个例子(例7.3)演示了对各类数据的输入输出。<br />　　例7.3FilterIODemo1.java。<br />　　1: import java.io.*;<br />　　2: public class FilterIODemo1{<br />　　3: 　public static void main(String args[]) throws IOException{<br />　　 　　　//串接过滤器<br />　　4: 　　BufferedOutputStream bufOut=<br />　　5:　　　 new BufferedOutputStream(new FileOutputStream("text.txt"));<br />　　6: 　　DataOutputStream dataOut = new DataOutputStream(bufOut);<br />　　　 　　//用DataOutputStream类写各种数据<br />　　7: 　　dataOut.writeBoolean(true);<br />　　8: 　　dataOut.writeChar('a');<br />　　9: 　　dataOut.writeInt(1);<br />　　10:　　dataOut.writeDouble(3.3);<br />　　11:　　bufOut.close();<br />　　12:　　dataOut.close();<br />　　13:　　BufferedInputStream bufIn=<br />　　14:　　　new BufferedInputStream(new FileInputStream("text.txt"));<br />　　15:　　DataInputStream dataIn= new DataInputStream(bufIn);<br />　　　　//用DataInputStream类读各种数据<br />　　16:　　System.out.println(dataIn.readBoolean());<br />　　17:　　System.out.println(dataIn.readChar());<br />　　18:　　System.out.println(dataIn.readInt());<br />　　19:　　System.out.println(dataIn.readDouble());<br />　　20:　　bufIn.close();<br />　　21:　　dataIn.close();<br />　　22:　}<br />　　23:}<br />　　例7.3的运行结果如下：(略)<br />　　上述例子演示了DataInputStream、DataOutpurStream、BufferedInputStream和 BufferedOutputStream的使用。该程序中只有一个方法main()。<br />　　在方法的开头，我们实例化了BufferedOutputStream类，得到对象bufOut。注意，我们的数据输出的最终目的地是文件 “Text.txt”。为了能够利用BufferedOutputStream的缓输出(把输出内容先存入缓冲，然后大块输出)功能，我们在文件输出应对上加一个过滤器，形成：<br />　　数据→过滤器对象bufOut→文件输出流<br />这样，我们用dataOut来写数据，就可以直接把各种类型的数据写入文件text.txt。<br />　　程序的后半部分几乎是第一个程序的翻版。我们在输入流上也加了过滤器，就可以用过滤器的方法来操作输入流了。<br />　　由于BufferedOutputStream和BufferedInputStream没有提供新的方法，这个例子也许会使读者产生一种错觉，好像只有最外层(最接近“数据”)的过滤器才能操纵输入。事实并非如此，我们将在下一个例子中说明这一点。<br />　　我们要解释的问题是，如果我们读数据时，选用的读方法与写时不一致会怎么样呢？读者可以自行实验一下。如果我们把<br />　　dataIn.readBoolean()换作dataIn.readChar()<br />读出的结果就不正确了(注意读到的并不是字符‘t’)，各种类型的数据存储的格式是不同的。虽然我们得到了图7.4所示的结果，但如果你用type命令看一下 text.txt，将会看到不同的输出。因此，不要把程序的输出和数据的内部在存储混为一谈。当使用dataI/O时，应当对你要读的数据的类型心中有数。DataInputStream并不能从一堆数据中析取你所需要的那个整数。<br /><br />　　7.5.2 过滤器类家庭<br /><br />　　下面我们介绍例1中出现的过滤器类。首先介绍一下它们的父类FilterInputStream和FilterOutputStream。<br />　　1.FilterInputStream类<br />　　这是一个抽象类。它是所有过滤器输入类的父类，提供了从一个输入流创建另一个输入流的方法。<br />　　构造函数：<br />　　■public FilterInputStream(InputStream in)<br />　　人一个输入流构造过滤器输入流。<br />　　方法：<br />　　重写了InputStream的同名方法，未提供新的方法。<br />　　2.FilterOutputStream类<br />　　与FilterOutputStream相对应，提供从一个输出流创建另一个输出流的方法。<br />　　构造函数：<br />　　■public Filer OutputStream(OutputStream out)<br />　　由输出流创始创建一个过滤器输出流。<br />　　方法：<br />　　重写了OutputStream的同名方法。<br />　　 3.BufferedInputStream类<br />　　从这个类开始，我们来介绍例7.3中用到的过滤器子类。BufferedInputStream类提供了一种“预输入”功能，它把输入数据在其缓冲区内暂存，在适当的时候把较大块的数据提交出去。<br />　　构造函数：<br />　　■public BufferedInputStream(InputStream in)<br />　　■public BufferedInputStream(InputSteam in,int size)<br />　　其中size指缓冲区大小。<br />　　方法：<br />　　重写了父类的方法。其中skip()、available()、mark()、reset()均为同步(synchonized)方法。<br />　　4. BufferedOutputStream类<br />　　提供“缓输出”功能，把输出数据暂存后，在适当时候大批送出。<br />　　构造函数：<br />　　■public BufferedOutputStream(OutputStream out)<br />　　■public BufferedOutputStream(OutputStream out,int size)<br />　　方法：<br />　　■public synchronized void write(int b) throws IOException<br />　　■public synchronized void write(byte b[],int offset,int length) throws IOException<br />　　■public synchronized void flush() throws IOException<br />以上方法重写了父类的同名方法。<br />　　在BufferedI/O类中，还有一些protect型的成员变量，是关于缓冲区和标记的，这里就不一一列出了。<br />　　5. DataInput接口和DataOutput接口<br />　　要介绍Data I/O类，就必须介绍Data I/O接口。<br />　　Data I/O类的目的是从流中析取或向流中写入指定的数据对象。一个流可以是纯字符流，也可以包含许多类型的数据。DataInput接口和 DataOutput接口就提供了从流中析取和写入数据的方法。用于读的方法除了个别之外都是无参的，写的方法则往往以被　写的数据类型为参数。方法的名字也很好记，即为“read”或“write”后接类型名，如readInt()，readUnsignedByte()，writeInt()， writeUnsignedByte()等。这引起方法均可能抛出Ｉ／Ｏ异常。一般说来，读时遇文件尾时抛出EOFException(是 IOException的子类)，读写时发生其它错误抛出IOException。<br />除了上面所说的名字很有规律的方法外，Data I/O接口中还有几个方法：<br />　　■public abstract void readFully(byte buffer[])<br />　　读全部数据到buffer[]数组。读时系统处于阻塞状态。<br />　　■public abstract void readFully(byte buffer[],int offset,int length)<br />　　把数据读到数组buffer[]中从Offset开始长为length的地方。<br />　　■public abstract int skipBytes(int n)<br />　　跳过规定字节数。返值为实际跳过的字节数。<br />　　■public abstract String readLine()<br />　　读取一行数据。<br />　　此外，还有我们早已熟悉的write()方法的三种重载形式。<br />　　6. DataInputStream类<br />　　介绍过两个数据I/O的接口后，介绍数据I/O流类就简单多了。DataInputStream类实现了DataInput接口，因面也就实现了这个接口的所有成员方法。此外，还有两个read()方法：<br />　　■public final int read(byte b[])<br />　　■public final int read(byte b[],int offset,int length)<br />　　重写了FilterInputStream的同名方法。<br />　　DataInputStream只有一个构造函数。像所有过滤器输入流类一样，这个构造函数的参数是InputStream的一个对象。<br />　　7.DataOutputStream类<br />　　这个类的成员方法我们都很熟悉了。除了实现DataOutput接口的方法之外，再就是一个flush()方法。write()与flush()重写了FilterOutputStream类的同名方法。<br />　　现在我们可以回过头来再看一下例7.3，印证一下刚才讲过的内容。这个例子的重点之一是演示过滤器的“连接”，另一个是介绍相应的类。<br /><br />　　7.5.3 例2:行号与“可推回”的流<br /><br />　　在下面的例子(例7.4)中，我们将进一步理解过滤器的连接问题。前面例子基本上用的都是字节流类，这个例子使用字符流类。<br />　　例7.4 FilterIODemo2.java。<br />　　1:import java.io.*;<br /><br />　　3:public class FilterIODemo2{<br />　　4:　public static void main(String args[]) throws IOException{<br />　　5:　　String s="this is a multi-line string.\n It is \nused to demo filterIO.\n";<br />　　6:　　char array[]=new char[s.length()];<br />　　7:　　for(int i=0;i&lt;s.length();++i)<br />　　8:　　array[i]=s.charAt(i);<br />　　　　//创建字符流，串接过滤器<br />　　9:　　CharArrayReader charReader = new CharArrayReader(array);<br />　　10:　　PushbackReader pushReader = new PushbackReader(charReader);<br />　　11:　　LineNumberReader lineReader = new LineNumberReader(pushReader);<br />　　12:　　String line;<br />　　　　//读字符流，加行号输出<br />　　13:　　while((line = lineReader.readLine())!=null){<br />　　14:　　　System.out.println(lineReader.getLineNumber()+":"+line);<br />　　15:　　}<br />　　　　//指针置到开头<br />　　16:　　try{ pushReader.reset();}catch(IOException e){}<br />　　　　//读字符流，每读到一个'\n'就把它推回<br />　　17:　　boolean eof = false;<br />　　18:　　boolean met = false;<br />　　19:　　while(!eof){<br />　　20:　　　int c=pushReader.read();<br />　　21:　　　if(c==-1) eof=true;<br />　　22:　　　else if(((char)c=='\n')&amp;&amp;!met){met =true;pushReader.unread(c);}<br />　　23:　　　else met =false;<br />　　24:　　　if(c!=-1) System.out.print((char)c);<br />　　25:　　}<br />　　26:　　System.out.flush();<br />　　27:　　pushReader.close();<br />　　28:　　charReader.close();<br />　　29:　　lineReader.close();<br />　　30:　}<br />　　31:}<br />　　该程序的运行结果如下：(略)<br />　　这个例子的功能是：给一个字符串加上行号后输出；把每个换行符都“重复”一次，即每次换行时加一个空行。该例子使用的是字符流I/O，演示了几个类的使用：CharArrayReader，PushbackReader，LineNumberReader。此外，我们还可以复习一下前面提到的几个流类。<br />　　PushbackReader，顾名思义是是可以把数据“推回”输入流的流类。我们用它来实现对换行符的重复——只要读完后把“推回去”，下次就可再读一遍了。LineNumberReader可以追踪输入的行数，用它来实现加行号输出。<br />　　现在来讲解一下程序。第５行中，在main()方法的开始，定义了一个字符串s。其中，有三个换行符‘\n’。然后创建一个字节数组Array[]，并在接下来的for循环(第7、8行)中为它赋值。以此为参数创建了一个内存缓冲区输入流的对象。这就是我们一串过滤器的源点。注意array并不是一个输入流，相应的CaarArrayReader也不是一个过滤器。<br />　　现在考虑选用过滤器。可根据我们想要的功能来选择。既然我们要行号，那么显然最好是一行一行读数据。BufferedReader的readLine ()方法正是我们需要。(readLine()方法本来是DataInputStream类的方法，但在1.1版中过时了。详细情况在第一节中已有说明。这里用DataInputStream也是可以的但编译时会警告信息。)加行号我们可以一行一行地读，也可以自己高于个变量来累计行数。当然也可以利用一个现成的类和现在的方法——选择LineNumbdrReader类及其getLineNumber()方法。由于LineNumbdrReader本身是BuffredReader类的子类，可以直接用它来逐行读数据，不必再引入BufferedReader类。为了重复写回画换行符可选用 PushbackInputStream类和它的unread()方法。<br />　　下面的任务是把它们串起来，如例子所示，可将它些过滤器一个“输出”作为下一个的“输入”。第一个while循环(第13到15行)中做的事很简单；读一行信息，取得其行号，然后一些输出。<br />　　第二个while循环(第19行到25行)的工作是重写操作符。我们用pushReader来读数据。布尔量eof来标识输入是否结束，met用来标识当瓣换行符是否被推回过。当输入没有结束时，每读到一个‘\n’ 时，就不会再“推回”了，保证换行符只被重复一次。<br />　　正如前面所提到过的，一串过滤器中的任一个都可以操作数据，无论该过滤器是最先的或最末的或是中间的任何一个。<br />　　由于我们是用print()方法来输出字符的，程序结束时可能还有一部分数据在缓冲区中，没被写到屏幕上。因此我们加了一个flush()方法强制显示到屏幕上。<br />　　将用过的流都关闭(第27到29行)是一种好的编辑风格。虽然Java的“垃圾收集”系统可以回收废弃不用的资源，仍应自觉地打扫“战场”，把能回收的资源主动回收。<br /><br />　　7.5.4 类库支持<br /><br />　　下面详细介绍一下例7.4中新出现的类。有一点需要解释，就是字符流I/O类与字节流I/O类的继承关系并不是一一对应的。比如，字节流I/O类中的 PrintStream是FilterOutputStream的子类，而对应的字符流类PrintWriter却是Writer类的子类。因此，严格地说PrintWriter并非过滤器类。但是，为了能够分六别类地研究这些类，我们不苛求这个差别，而是按照字节流I/O类的继承关系，对应地把相应字符流I/O类也看作过滤器类。<br />　　1.PushbackReader类<br />　　构造函数两个：<br />　　■public PushbackReader(Reader in,int size)<br />　　创建缓冲区大小为size的一个PushbackReader对象。<br />　　■public PushbackReader(Reader in)<br />　　创建缓冲区大小为一个字符的一个PushbackReader对象。<br />　　方法：<br />　　■public int read()<br />　　■public int read(char cbuf[],int offset,int length)<br />　　读数据。<br />　　■public void unread(int ch)<br />　　回退一个字符。当缓冲区满或发生其它输入输出的异常情况时，抛出I/O异常。<br />　　■public int avaliable()<br />　　返回缓冲区内字节个数。<br />　　■public boolean markSupported()<br />　　确认输入流是否支持标记功能。<br />read()、unread()、available()均可能抛出IOException。<br />　　2.LineNumberReader类<br />　　构造函数两个，与PushbackReader类似。<br />　　下面列出方法的原型，其中我们已经熟悉的，在此就不给出解释了。<br />　　■public int read() throws IOException<br />　　■public int read(char cbuf[],int offset,int length) throws IOException<br />　　■public void setLineNumber(int lineNumber)<br />　　设置行号。<br />　　■public int getLineNumber()<br />　　读行号。<br />　　■public long skip(long n) throws IOException<br />　　■public int available()throws IOException<br />　　■public void mark(int readAheadLimit)throws IOException<br />　　在当前位置作标记。从此读取readAheadLimit个字符后标记变为无效。<br />　　■public void reset()throws IOException<br />　　返回到上一标记。<br />　　3.PrintStream类和PrintWriter类<br />　　PrintStream类是过滤器类中一个不可忽视的成员，最基本的标准输出就要借助于它——我们常用的System.out变量就是 PrintStream实例。与之对应的字符流类是PrintWriter类。<br />　　PrintStream有两个构造函数(在新版ＡＰＩ中已标记为过时)：<br />　　■public PrintStream(OutputStream out)<br />　　■public PrintStream(OutputStream out,boolean autoFlush)<br />其中，autoFlush置为true时，每当输出遇到换行符，缓冲区的内容就被强制全部输出，如同调用了一次flush()。但要注意，如果没遇到换行符，还是会有数据“憋”在缓冲区里。<br />　　方法(已熟悉的就不解释)：<br />　　■public void write(int b)<br />　　■public void write(byte b,int offset,int length)<br />　　■public void flush()<br />　　■public void close()<br />　　■public void print(Object obj)<br />　　这个方法功能是非常强大的，它可以输出任何对象，而不必另加说明。此外print()方法有许多重载形式，即有多种参数。它们是字符串 (String)、字符数组(char[])、字符(char)、整数(int)、长整数(long)、浮点数(float)、双精度浮点数 (double)、布尔值(boolean)。其中，输出多个数单位的print()方法(也就是指参数为String和char[]的)是同步 (synchronized)方法。<br />　　■public void println()输出一个换行符。<br />　　■public synchronized void println(Object obj)<br />　　println()方法有9个重载形式，几乎就是print()方法的翻版。唯一的区别在于println()方法都是同步的。<br />　　■public boolean checkError()<br />　　检查输出过程中有什么错误，如有，返回true值。只要输出流中出现一次错误，则出错后的任意对checkError()的调用均会返回真值。<br />　　下面介绍PrintWriter类。<br />　　如同第二节中所说，PrintWriter是JDK1.1版增加了与字节流I/O相对应的字符流I/O。但是，为了保持兼容性，原先的类几乎没有改动。再加之调试的需要，PrintStream类被保留，并且System类中的成员变量out、err仍作为它的对象。然而，PrintWriter用于大多数输出比PrintStream更为合适。因此1.1版的API中建议新开发的代码使用PrintWriter类，并将 PrintStream类的两个构造函数标记为过时。这样，虽然使用System.out输出不会产生问题，在程序中创建新的PrintStream对象时却会产生编译时的警告。<br />　　PrintWriter类与PrintStream类的方法是对应的。有一个不同之外需提请读者注意，就是当前者的自动清空缓冲区的功能被使能时(构造函数中autoFlush置为true)，仅当println()方法被调用时才自动清缓冲区，而不是像PrintStream一样遇到一个换行符就清缓冲。<br />　　到此为止，我们已介绍了各种类型的过滤器I/O类。适用于字节流和字符的各种对应过滤器类，其方法也是对应的。因此，对没有介绍的类读者可以从其对应类推理其功能。<br /><br />7.6 管道I/O<br /><br />　　管道I/O是专门用于线程通信的。对于字节流Java提供了两个类，PipedInputStream类被线程用来写字节数据。两个管道I/O流对象可以连接起来，这样一个线程写的数据就可以被另一个线程来读。对于字符流也有两个类，分别叫做PipedReader和PipedWriter。我们只详细介绍字节流的管道I/O类。<br /><br />　　7.6.1 PipedInputStream类<br /><br />　　这个类有两个构造函数。一个无参，用它建立起输入流后，需将它与一个管道输出流相连接。另一个以管道输出流(PipedOutputStream)对象为参数，创建一个与该输出流对象相连接的输入流。<br />　　PipedInputStream类的所有方法均可能抛出IOException。<br />　　■public void connect (PipedOutputStream src)<br />　　将输入流连接到某管道输出流。<br />　　■public synchronized int read()<br />　　■public synchronized int read(byte b[],int offset,int length)<br />　　读数据。<br />　　■public void close()<br />　　关闭流。<br /><br />　　7.6.2 PipedOutputStream类<br /><br />　　与PipedInputStream类完全对应，它有两个构造函数，其中一个以PipedInputStream对象为参数，另一个无参。成员方法也是包括connect()，close()，另外还有两种形式的write()方法，这里就不细述了。<br /><br />　　7.6.3 程序示例<br /><br />　　下面用一个示例(例7.5)具体演示管道Ｉ／Ｏ的使用。<br />　　例7.5 PipeIODemo.java<br />　　1: import java.lang.*;<br />　　2: import java.io.PipedInputStream;<br />　　3: import java.io.PipedOutputStream;<br />　　4: import java.io.IOException;<br />　　5:<br /><br />　　6: public class PipeIODemo{<br />　　7: 　public static void main(String args[]){<br />　　 　　//这里的Reader和Writer不是字符流输入输出的基本类，而是下文自定义的<br />　　8: 　　Reader thread1=new Reader("1");<br />　　9: 　　Writer thread2=new Writer("2");<br />　　　　//联接管道<br />　　10:　　try{<br />　　11:　　　thread2.pipeOut.connect(thread1.pipeIn);<br />　　12:　　}catch(IOException ex){<br />　　13:　　　System.out.println("IOException occured when connecting two stream");<br />　　14:　　}<br />　　　　//启动线程<br />　　15:　　thread1.start();<br />　　16:　　thread2.start();<br />　　　　//循环，等线程均结束后程序中止<br />　　17:　　do{<br />　　18:　　}while(thread1.isAlive()||thread2.isAlive());<br />　　19:　　System.out.println("All over!");<br />　　20:　}<br />　　21:}<br />　　//自定义读者类<br />　　22:class Reader extends Thread{<br />　　23:　public PipedInputStream pipeIn;<br />　　24:　String threadName;<br />　　25:　public Reader(String name){<br />　　26:　　super();<br />　　27:　　threadName = name;<br />　　28:　　pipeIn = new PipedInputStream();<br />　　29:　}<br />　　30:　public void run(){<br />　　31:　　try{<br />　　32:　　　boolean over = false;<br />　　33:　　　while(!over){<br />　　34:　　　　int ch=pipeIn.read();<br />　　35:　　　　try{<br />　　36:　　　　　Thread.sleep(200);<br />　　37:　　　　}catch(InterruptedException ex){<br />　　38:　　　　　System.out.println("Sleep is interrupted!");<br />　　39:　　　}<br />　　40:　　　if(ch=='.') over = true;<br />　　41:　　　　else System.out.println("Thread "+threadName+" read "+(char)ch);<br />　　42:　　　}<br />　　43:<br />　　44:　　}catch(IOException ex){<br />　　45:　　　System.out.println("IOException occured when try to read data");<br />　　46:　　}<br />　　47:　}<br />　　48:}<br />　　//自定义写者类<br />　　49:class Writer extends Thread{<br />　　50:　public PipedOutputStream pipeOut;<br />　　51:　String threadName;<br />　　　//待写内容<br />　　52:　String content = "orange apple";<br />　　53:　public Writer(String name){<br />　　54:　　super();<br />　　55:　　threadName=name;<br />　　56:　　pipeOut = new PipedOutputStream();<br />　　57:　}<br />　　58:　public void run(){<br />　　59:　　try{<br />　　　　　//将字符串内容逐字输出<br />　　60:　　　for(int i=0;i&lt;content.length();++i){<br />　　61:　　　　pipeOut.write(content.charAt(i));<br />　　62:　　　　try{<br />　　63:　　　　　Thread.sleep(200);<br />　　64:　　　　}catch(InterruptedException ex){<br />　　65:　　　　　System.out.println("Sleep is interrupted!");<br />　　66:　　　　}<br />　　67:　　　　System.out.println("Thread "+threadName+" wrote "+content.charAt(i));<br />　　68:　　　}<br />　　69:　　　　pipeOut.write('.');<br />　　70:　　　}catch(IOException ex){<br />　　71:　　　System.out.println("IOException occured when try to write data");<br />　　72:　　}<br />　　73:　}<br />　　74:}<br />　　该程序的运行结果如下：(略)<br />　　这个例子功能很简单。两个线程，一个是读者，一个是写者，读者取写者所写的内容。双方约定以‘.’为结束符。<br />　　这个例子演示了管道I/O一般过程，首先是创建管理I/O流类对象。这个工作是在Reader和Writer类的构造函数中做的(第28、56行)。因此当我们创建了thread1和thread2两个线程时，pipeIn和pipeOut就被创建了。然后我们把它们连接起来，再启动两个线程工作，最后打印“All Over!” 表示运行结束。<br />　　可以看出，读线程与写线程实际上是不必关心对方的情况的。它们的工作就是读或写，每处理一个字符输出一条信息表明自己做过的工作。我们在pipeIn 的输出信息中加了一大段空格，这样的目的是使两个线程的输出能容易分辨。另外，让两个线程处理一个字符就睡眠(sleep) 一会儿并不是必须的，这样只是为了增加线程交替执行的机会。如果去年这一段，可能执行数次者不出现thread1、thread2交替输出信息的现象，容易被误解为两个线程必须一个死亡才执行另一个。另外，作为结束符的“.” 并没有显示出来。<br />　　这个例子实现的是单向通信。实际上，为每个线程都分别创建输入流对象和输出流对象，再分别连接起来，就可以实现双向通信。读者有兴趣不妨一试。<br /><br />7.7 java.io包中的其它类<br /><br />　　7.7.1 SequenceInputStream类<br /><br />　　这个类的功能是合并多个输入流。其构造函数有两个，一个以枚举(Enumeration)对象为参数，一个以两个InputStream对象为参数。方法则有两个read()方法，分别读一个字符、读数据入字节数组中的一段。再就是一个close()方法。例7.6利用它来实现了两上文件的并接。其中还使用了ByteArrayOutputStream，用意是将两个文件并接的结果先在内存缓冲区中暂存一下。这个例子允许目的的文件是两个源文件之一。<br />　　例7.6 FileCat.java<br />　　import java.lang.System;<br />　　import java.io.*;<br /><br />　　public class FileCat{<br />　　　public static void main(String args[]){<br />　　　　SequenceInputStream seqIn;<br />　　　　if(args.length!=3){System.out.println("Usage:java FileCat filesrc filesrc filedst");}<br />　　　　else{<br />　　　　　try{<br />　　　　　　FileInputStream f1=new FileInputStream(args[0]);<br />　　　　　　FileInputStream f2=new FileInputStream(args[1]);<br />　　　　　　seqIn=new SequenceInputStream(f1,f2);<br />　　　　　　ByteArrayOutputStream byteArrayOut=new ByteArrayOutputStream();<br />　　　　　　boolean eof=false;<br />　　　　　　int byteCount=0;<br />　　　　　　while(!eof){<br />　　　　　　　int c=seqIn.read();<br />　　　　　　　if(c==-1)eof=true;<br />　　　　　　　else{<br />　　　　　　　　//将读到的数据写入字节数组输出流<br />　　　　　　　　byteArrayOut.write((char)c);<br />　　　　　　　　++byteCount;<br />　　　　　　　}<br />　　　　　　}<br />　　　　　　FileOutputStream outStream=new FileOutputStream(args[2]);<br />　　　　　　//将数据写入文件<br />　　　　　　byteArrayOut.writeTo(outStream);<br />　　　　　　System.out.println(byteCount+" bytes were read.");<br />　　　　　　seqIn.close();<br />　　　　　　outStream.close();<br />　　　　　　byteArrayOut.close();<br />　　　　　　f1.close();<br />　　　　　　f2.close();<br />　　　　　}catch(FileNotFoundException ex){<br />　　　　　　System.out.println("Cannot open source files.Please check if they"+<br />　　　　　　　　"exists and allows freading.");<br />　　　　　}catch(IOException ex){<br />　　　　　　System.out.println("IOexception occured!");<br />　　　　　}<br />　　　　}<br />　　　}<br />　　}<br /><br />　　7.7.2 Streamtokenizer类<br /><br />　　这个类是用来构造词法分析器的。缺省情况下，它可以识别数值、字母以及字符串。它的构造函数只有一个，以输入流(inputStream)对象为参数。本节我们给出一个例子(例7.7)，并介绍例子中出现的该类的部分方法。<br />　　例7.7 TokenIODemo.java。<br />　　1:import java.io.IOException ;<br />　　2:import java.lang.System;<br />　　3:import java.io.InputStreamReader ;<br />　　4:import java.io.StreamTokenizer;<br />　　5:import java.io.FileInputStream ;<br />　　6:<br />　　7:public class TokenIODemo{<br />　　8:　public static void main(String args[]) throws IOException{<br />　　　　//从文件创建输入流<br />　　9:　　FileInputStream fileIn = new FileInputStream ("hello.c");<br />　　　　//从字节流创建字符流<br />　　10:　　InputStreamReader inReader = new InputStreamReader (fileIn);<br />　　11:　　StreamTokenizer tokenStream = new StreamTokenizer (inReader);<br />　　　　//设置注释风格<br />　　12:　　tokenStream.slashStarComments(true);<br />　　13:　　tokenStream.slashSlashComments (true);<br />　　　　//识别行结束符;如果参数为假，将行结束符视作空白符<br />　　14:　　tokenStream.eolIsSignificant (true);<br />　　　　//设置引号的符号表示<br />　　15:　　tokenStream.quoteChar ('"');<br />　　　　//将ASCII码为0-32的字符设为空白符<br />　　16:　　tokenStream.whitespaceChars (0,32);<br />　　17:　　boolean eof = false;<br />　　18:　　do{<br />　　19:　　　int token = tokenStream.nextToken ();<br />　　20:　　　switch(token){<br />　　　　　　//文件结束符<br />　　21:　　　case tokenStream.TT_EOF :<br />　　22:　　　　System.out.print(" EOF ");<br />　　23:　　　　eof=true;<br />　　24:　　　　break;<br />　　　　　　//行结束符<br />　　25:　　　case tokenStream.TT_EOL :<br />　　26:　　　　System.out.print (" EOL ");<br />　　27:　　　　break;<br />　　　　　　//单词<br />　　28:　　　case tokenStream.TT_WORD :<br />　　29:　　　　System.out.print (" Word "+tokenStream.sval );<br />　　30:　　　　break;<br />　　　　　　//数字<br />　　31:　　　case tokenStream.TT_NUMBER :<br />　　32:　　　　System.out.print(" Number "+tokenStream.nval );<br />　　33:　　　　break;<br />　　34:　　　default:<br />　　35:　　　　System.out.print(" "+(char)token);<br />　　36:　　　}<br />　　37:　　}while(!eof);<br />　　38:　　System.out.flush();<br />　　39:　}<br />　　40:}<br />　　下面是该例的运行结果：<br />　　E:\&gt;java TokenIODemo<br />　　# Word include &lt; Word stdio.h &gt; EOL EOL Word main ( ) { EOL Word print ( " ,<br />Number 1234.0 ) ; EOL EOL } EOL EOF<br />　　E:\&gt;<br />　　其中，hello.c程序的源代码如下：<br />　　#include &lt;stdio.h&gt;<br />　　//To say "hello world"<br />　　main(){<br />　　　print("hello world %d\n",1234);<br />　　　/* It is a test for TokenIODemo*/<br />　　}<br />　　例子中我们用到了这样一些方法：<br />　　■public void whitespaceChars(int low,int hi)<br />　　把给定范围的字符设为空格(不可见)字符。类似的方法还有wordChars()(设为单词字符)，ordinaryChars()(设置为除了单词字符、数据字符等有实际含义字符之外的其它字符)。<br />　　■public void slachStarComments(boolean flag)<br />　　■public void slachSlashComments(boolean flag)<br />　　flag为真，则可训别相应风格的注释。前者(slashStar)指Ｃ风格的注释(/*...*/)。后者指C++风格的注释“//”。<br />　　■public int nextToken()<br />　　从输入流取得下一个词法分析单位。<br />　　■public void eolIsSingnificant(boolean flag)<br />　　如果参数为真，识别行结束符；否则，将行结束符视作空白符。<br />　　例子中还用到了一些常量和变量。TT_EOF、TT_EOL、TT_NUMBER、TT_WORD分别表示文件结束符、行结束符、数值和单词。public String sval是指字符串值；public double nval指双精度值。这些常量、变量的使用在例子中已有明确的演示，这里就不多说了。<br /><br />　　7.7.3 FilenameFilter接口<br /><br />　　这个接口不太常用，只提供了一个方法：<br />　　■public abstract boolean accept(File dir,String fileName)<br />　　功能是确定某一文件列表是否包含了指定的文件。<br /><br />　　7.7.4 Serializable接口<br /><br />　　实现这一接口的类可以被“串行化”，即它们的对象可以被转化为某种形式，该形式可以被输入输出，而保存对象的结构。也就是说，只有实现了这一接口，类的对象才能被完整地输入输出和存储。<br />　　该接口不含任何方法和变量，它只充当一个标记。编程时只要在类定义时中上：<br />　　... implements Serializable<br />即可使该类的对象具有“串行性” 。<br /><br />本章小结<br /><br />　　在这一章中，我们比较全面地介绍了java.io包中的类和接口，并给出了示例。读者通过这一章学习，应掌握java的输入输出类，并将种I/O手段灵活运用于自编的程序之中。<br /><br /><img src ="http://www.blogjava.net/spark/aggbug/72496.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-09-28 10:41 <a href="http://www.blogjava.net/spark/archive/2006/09/28/72496.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA全方位学习</title><link>http://www.blogjava.net/spark/archive/2006/09/28/72493.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Thu, 28 Sep 2006 02:33:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/09/28/72493.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/72493.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/09/28/72493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/72493.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/72493.html</trackback:ping><description><![CDATA[
		<p>列出java语言的所有重点</p>
		<br />
		<p>java 2全方位学习 J2ME无线java应用开发  JAVA手机程序设计入门与应用 <br />1、对于一般PC平台来说，Java的程序分成两大类，一个是在PC的操作系统上通过JVM直接运行的Java Application，另一种是通过浏览器中附带的JVM运行的Java Applet。<br />2、&lt;applet code="要运行的class文件名称" width="显示的宽度" height="显示的高度"&gt;&lt;/applet&gt;。<br />3、javac,java,appletviewer。<br />4、java是用unicode作为字符集的，所以我们在Java程序中使用中文或是英文甚至是其他的语言作为class名称、变量名称都可以。<br />5、JFC-java foundation classes,GUI-graphical uesr interface。<br />6、java -jar Java2D.jar。<br />7、PDA-个人数据处理。jpda-Java Platform Debugger Architecture。</p>
		<p>第4章 程序基本单元<br />8、关键字与保留字的区别。标志符的魔力。Literal的含义。变量的意义，变量命名的原则。<br />9、基本数据类型：整型，浮点，其他类型。<br />10、为什么数值范围正负值分开，无理数或是无穷小数的表示问题。其核心是精度问题。浮点数不存在0这个数值，所以会产生误差。<br />11、其他数据类型：boolean,char,常用转义字符，特殊字符的表示方法。<br />12、Java两种变量的模式：成员变量（member variable），局部变量（local variable）。成员变量初始值在声明时就指定了。而局部变量则不会，要求用户自己设定初始值。<br />13、类型转换分为自动类型转换（promotion）和强制类型转换（casting）两种。其中每种又分为放大（widening）和缩小（narrowing）两种。放大转换属于自动类型转换，缩小转换属于强制类型转换。<br />14、数据类型的后面加上一个英文字母，是由于Java对于literal默认的数据类型有关，基本上Java对整数的lieral默认为int型，而对于浮点数的literal默认为double型。<br />15、Java里有个特殊的类，可以像一般的基本数据类型一样使用，它就是String-字符串。</p>
		<p>第5章 Java的表达式<br />16、5%2与5%-2与-5%2与-5%-2的区别。<br />17、比较运算符的结果只有两种，true和flase。instanceof?<br />18、逻辑与和一般与的差别。在需要改变变量的值时，用一般与。通常使用逻辑运算符，因为运算速度会快一些。<br />19、逻辑运算的优先级在比较运算符之下。<br />20、赋值运算符是所有运算符中最低的。赋值运算符从右边运算到左边。而算术运算符是从左边运算到右边。并且赋值运算符的左边只能有一个变量存在。<br />21、位运算符（bitwise）。 &amp;,|,^,~（complement）。位运算符只能用于整型数据类型中。位移运算（shift）的用处。位移运算比较难。要理解位移运算的用途。了解减次运算的含义。      <br />22、运算符的优先级和结合性。</p>
		<p>第6章 Java的语句<br />23、语句有很多种，粗略的把它们分为四类：第一类是一般的语句，第二类是声明语句，第三类是条件流程控制语句，第四类是循环控制语句。<br />24、对象的声明与变量的声明是不同的。对象在声明后，必须进行实例化，而变量声明是不需要的。<br />25、?:运算符的使用。<br />26、Switch的参数只能是(&lt;byte、short、int或char变量&gt;)的其中一种。  <br />27、for(&lt;控制循环变量初始值设置&gt;;&lt;循环结束判断条件语句&gt;;&lt;控制循环变量值改变方法&gt;){&lt;代码&gt;s}。千万不使用浮点数作为控制变量。由于浮点数误差问题。<br />28、while(&lt;循环结束判断条件语句&gt;){&lt;代码&gt;s}。<br />29、do{&lt;代码&gt;s} while(&lt;循环结束判断条件语句&gt;)。<br />30、高级循环控制－嵌套循环。以及break和continue的使用。<br />31、标记&lt;token&gt;的使用。以冒号： 作为结束。运用适当的break、continue和token可以增强程序的弹性。但不要乱用token。<br />32、必须了解注释语句、if语句、switch语句、循环语句、break、continue和标记的使用与限制。<br />                                    <br />第7章 Java面向对象程序设计<br />33、对象是符合某种类定义所产生出来的实例（instance）。类是抽象的，而对象是实在的。属性（attribute）是用来形容一个实例对象的，其实就是变量。方法（method）是对象自己的行为或者是使用它们的方法，其实就是函数。属性和方法称为对象的成员。类可以说是蓝图（blueprint），类中会定义许多产生该类对象时，所必须具备的一些属性与方法。<br />34、继承（inheritance）和多态（polymorphism）是类的另外两个重要的特性。继承最主要的目的是为了"扩展"原类的功能、加强或改进原类所没有定义的属性及方法。被继承的类为父类，继承的类为子类。采用UML（Unified Modeling Language）的表达方式来设计类，可以画出类关系图，其中最重要的部件是类图标和继承图标。多态的概念比较难理解，需要加强理解，其中还有覆盖（override）的概念。<br />35、为了增强程序的可读性和易用性。全世界的java程序师都遵守以下的规则：（1）Package（包），作为Package名称的英文单词全部要小写；（2）类，每个英文单词的第一个字母大写；（3）接口，规则与类一样；（4）属性，每个英文单词的第一个字母小写，其他单词的第一个英文字母大写；（5）方法，规则和属性一样，不过后面有小括号；（7）常量，英文单词全部大写，而且每两个英文单词之间用下划线隔开。<br />36、Animal和Zoo两个类只需要对Zoo.java进行编译即可。这是因为在Zoo.java中所有用到的类如果还没有进行过编译的话，在编译Zoo.java的过程中它们都会被自动编译。<br />37、构造函数（constuctor），除了可以在Java编译时为我们自动产生之外，还可以自行编写所需要的构造函数。构造函数也是一个方法。<br />38、在一个类中，有多个构造函数使用相同的名称，但是参数类型与个数却各不相同，我们把这样的一个行为称为构造函数重载（overloading）。<br />39、原则上重载有两个规则一定要遵守：一、方法名称一定要一样。否则的话，就是两个不同的方法，不能称为重载。二、调用的参数类型一定要不一样。因为编译器要通过参数类型来判断调用的是哪一个方法。<br />40、面向对象程序设计中一个非常重要的概念，我们称为信息的隐藏（information hidding），专用的技术术语为封装（encapsulatio）。封装的目的有两个：一、保护类中的数据，不让这些数据被错误的使用或破坏；二、隐藏不需要让别人知道的细节，以防别人误用。封装还有一些其他的重要的特点：隐藏类的具体细节；强制用户通过单一接口访问数据；程序更加容易维护。<br />41、属性访问方法的命名规则：设置属性值的方法以set作为开头；获取属性值的方法以get作为开头；Boolean数据类型值的获取用isXXX形式来命名。<br />42、类的多态的，指类在不同情况下，可以看作是不同的类。<br />43、类成员和实例成员。前面介绍的属性和方法，属于对象等级的，称为实例成员。类成员必须使用限定词static。类成员的调用方法为&lt;类名称&gt;.&lt;类成员名称&gt;，也可以为&lt;对象名称&gt;.&lt;类成员名称&gt;。但是类方法中不能使用实例成员。<br />44、子类产生对象时，会往上通知它的父类，它的父类又会通知父类的父类，持续这个操作直到最上层的java.lang.Object类。通知上层父类最主要的目的时，对于那些继承自父类的属性或其他的设置做初始化的操作。从而达到 程序代码的重复使用，这也是继承的目的。Java在编译时自动帮我们加上通知父类的程序代码，是加在构造函数里面。super();这行的意思必须明白。super是关键字。<br />45、调用super函数必须注意两点：一、super调用必须在构造函数的第1行。二、如果子类中有好几个不同的构造函数，二父类又没有不需要参数的构造函数，那么就必须在子类中的每个构造函数的第一行加上适当的super调用。<br />46、构造函数调用构造函数用this这个关键字。<br />47、super和this在使用上有一些要注意的地方：一、super和this只能使用在构造函数程序代码中的第一行；二、super和this同时只能使用一种；三、super和this的调用只能使用在构造函数中；四、如果构造函数中没有使用super或this，那么Java会自动帮你加上super()调用。<br />48、屏蔽(shadow)－属性（继承关系）、覆盖(override)－方法（继承关系）、重载(overload)－方法（同一个类下函数同名，但参数不同）。使用属性的几种方法必须了解，super、this、强制类型转换的使用。</p>
		<p>第8章 深入Java面向对象程序设计<br />49、什么是包(package)？包很像我们计算机中的目录或是文件夹。目录分隔符，dos用\，unix用/。目录机制应用于Java面向对象的程序当中就是所谓的包。<br />50、package语句中，原本的目录分隔符改用句点[.]来代替。package &lt;package名称&gt;;必须注意：package语句一定只能写在程序代码的第一行。package的UML图示。除了每一个类的Java文件中的第一行设置package外，程序代码中用到其他类的地方也一并加上它的package的名称。package的设置与使用。<br />51、import语句，必须写在package语句之后，所有类声明之前。import语句的通配符(*)。使用通配符只是将该package下的类import进来，不会把子目录下的其他目录中的类import进来。<br />52、classpath的设置。classpath是Java程序在编译与运行时会使用到的一个【环境变量】，它的主要用途是告诉编译器去哪里找到编译或运行时所需要的类。windows默认情况下classpath为【.】。设置classpath的两种方法：一、直接设置；二、javac加上-classpath这个参数。<br />53、访问权限的限定词的使用。protected与default的使用。成员限定词有四个，而类声明限定词只有两个。<br />54、final限定词的使用－用于常量。final和static的使用。<br />55、抽象类的使用。关键字是abstract。能让继承的子类一定覆盖某个特殊的方法，这种机制就是【抽象(abstract)】。在一个类中，我们可以指定某个方法为抽象的，而一个抽象的方法不需要编写方法的内容，也就是说当方法声明完后，就直接以分号【；】来结束，不用加上左右大括号。只要有任何一个抽象方法，那么这个类就必须成为一个抽象类，所以我们必须把类的声明加上abstract这个关键字。抽象类不能生成对象实例。abstract只能用在类和方法上。属性和变量上没有意义。<br />56、接口－一种标准、一些规范。在java中，接口是由一些常量和抽象方法所组成的。关键字是【interface】，使用的格式如下：&lt;限定词&gt;interface&lt;接口名称&gt;[extends&lt;接口名称&gt;s]。解决abstract不能解决的问题。接口中方法的语法声明跟抽象方法的语法声明是一样的，就是是只有方法的声明，而没有方法本身，简单的说就是声明完后直接以分号结束整个语句，而不用再加上大括号。接口中的方法也都全部是抽象方法，只是不需要额外加上abstract这个关键字。extends &lt;类名&gt;，implements &lt;接口名&gt;。简单的说，接口就是一个完全抽象的类。Java用多重接口的方法来完成类的多重继承机制。implements&lt;接口1&gt;,&lt;接口2&gt;......。java中存在一种特殊的接口，它只有接口的声明，而内部是空的，也就是说完全没有任何的常量和方法的声明。这种特殊大额接口称为【标记接口(marker interface)】。</p>
		<p>第9章 Object类的常用方法介绍<br />57、对象之间的比较，第一种观点，对象相等是指对象为同一个。包括使用的内存。直接用==。第二种观点，是两个对象的内容是否相等。用equals方法。<br />58、理解hash code的含义。<br />59、引用(reference)与复制(clone)的区别。clone方法的使用。<br />60、将对象转为字符的方法【toString】。<br />61、在设计的类的时候，最好也一并的把这几个Object的方法覆盖。</p>
		<p>第10章 深入内存<br />62、变量内存的使用，变量声明后，编译器就分配了内存。<br />63、对象内存的使用，对象声明后，编译器只是在内存中产生一个对象的引用(reference)，它所存放的并不是一个真正的对象实例 ，因为对象的实例我们还没生成。所以当一个对象被声明后，在内存中这个对象引用的初始值会是【null】。我们用new这个关键字，配合调用类的构造函数，来生成对象实例。但，此时对象引用与对象实例并没有产生关联。需要使用复制语句使它们关联。每个对象引用占用4个字节的内存空间。对象的引用所存放的是撒对象实例真正在内存中的地址。对象引用实际占用的内存大小，跟系统（JVM）实现的方法有关，不同的系统大小不一定相同。<br />64、什么是数组，数组是存放量大、性质相同且需要做相同处理的数据。数组可以用在基本数据类型的变量上，当然也可以用在对象上。数组与对象有点相似，分成两个阶段——数组引用的声明和数组实例的生成。数组声明格式如下:int a[];和int []a;数组声明完后，在内存中表现的方法也跟对象一样，也是个引用，而且初始值也是null。生成数组实例同样要用到new关键字，在这之后要用赋值语句进行关联处理。也可以同时创建和初始化数组，如 int a[]={1,2,3,4}。<br />65、数组的索引(index)，是[]里面的数字，它表示这个数组中的第几笔数据。数组的使用比较简单，就是在数组变量的名称后，加上要访问的索引。索引从0开始到数组的大小减1。<br />66、数组的length属性获得数组的大小。必须注意数组的大小是不能改变的。使用上比较有弹性。<br />67、数组的复制。数组不是继承自java.lang.Object类的对象，所以没有clone这个用来复制对象实例的方法。可以利用循环赋值来实现。java中提供了【System.arraycopy】方法。使用这个方法时需要5个参数，依次是源数组、来源数组数据起始位置、目的数组、目的数组数据起始位置、复制数据的个数。使用上比较有弹性。arraycopy方法只适用于基本数据类型的数组。相比而言，第二种方法使用JNI的方法，所以速度上会比较快。arraycopy的三种异常，NULLPointerException，ArrayIndexOutOfBoudsException，ArrayStroeException。<br />68、Java 本机接口（Java Native Interface (JNI)）是一个本机编程接口，它是 Java 软件开发工具箱（Java Software Development Kit (SDK)）的一部分。JNI 允许 Java 代码使用以其它语言（譬如 C 和 C++）编写的代码和代码库。Invocation API（JNI 的一部分）可以用来将 Java 虚拟机（JVM）嵌入到本机应用程序中，从而允许程序员从本机代码内部调用 Java 代码。 <br />预备知识 <br />所有示例都是使用 Java、C 和 C++ 代码编写的，并可以移植到 Windows 和基于 UNIX 的平台上。要完全理解这些示例，您必须有一些 Java 语言编程经验。此外，您还需要一些 C 或 C++ 编程经验。严格来说，JNI 解决方案可以分成 Java 编程任务和 C/C++ 编程任务，由不同的程序员完成每项任务。然而，要完全理解 JNI 是如何在两种编程环境中工作的，您必须能够理解 Java 和 C/C++ 代码。 <br />系统需求 <br />浏览器：Netscape 4.x 或更高版本, 或者 Internet Explorer 4.x 或更高版本 ，支持 JavaScript 。 要运行本教程中的示例，您需要下列工具与组件： Java 编译器：随 SDK 一起提供的 javac.exe。 Java 虚拟机（JVM）：随 SDK 一起提供的 java.exe。 本机方法 C 文件生成器：随 SDK 一起提供的 javah.exe。 定义 JNI 的库文件和本机头文件。jni.h C 头文件、jvm.lib 和 jvm.dll 或 jvm.so 文件，这些文件都是随 SDK 一起提供的。 能够创建共享库的 C 和 C++ 编译器。最常见的两个 C 编译器是用于 Windows 的 Visual C++ 和用于基于 UNIX 系统的 cc。<br />68、多维数组在内存中的样子。必须理解。不规则数组的生成。 不规则数组是Java语言的一个重要特点，其他的程序语言像C或是Basic，都只能声明规则的多维数组，而且维数有上限。java没有这个限制。<br />69、以上讨论基本数据类型的数组，现在来看对象数组。防止NullPointerException异常的产生。<br />70、变量的访问范围【scope】，有点像类之间属性及方法访问的限制，这些限制是由于访问权限的限定词、package和继承这几种关系组合起来的。变量访问范围大致分为四个等级：第一、类级(static)；第二、对象实例级；第三、方法级；第四、局域级。怎么样区分这几个级别，必须注意。必须理解这四个等级。访问范围和视野的关系刚好相反。内存存在的时间。<br />71、参数的传递。以前的程序语言概念参数的传递有两种方法，一是【传值(call by value)】，另一个是【传址(call by reference)】。但java里面只有传值这种方式。基本数据类型参数值传递与类对象型参数值传递是不同的。<br />72、内存回收(garbage collection)。负责运行这个机制的就是【garbage collector】。对象声明包括两部分：对象引用和对象实例。如果一个对象实例不被任何对象引用指到的话，但启动GC时，就会把对象实例回收回去，并把内存释放调。取消对象引用，只要将它指定为【null】即可。GC是不定时的启动，也可以手动调用它，方法是【System.gc()】，它会调用【Runtime.getRuntime.gc()】，这两个方法都可以使用。finalize方法同样也是Object类常用的一个方法，与GC有关。它是在对象被回收前，GC所调用的方法。回收顺序与对象实例的生成顺序有关。既是我们手动调用System.gc()，GC也不见得一定运行，GC正确的启动时间无法得知。                                                                                                                                <br />第11章 Application与Applet<br />73、Application的输出，System类的out属性是PrintStream对象，有prinlin方法和print方法，也可以用err属性是PrintStream对象，有prinlin方法和print方法，但有区别，out属性可以重定向(redirected)，err属性只能输出到默认的设备上。Application默认的就是所打开的命令行窗口，Applet默认的就是Java Console。 可以用&gt;来实现重定向。println和print方法都是属于重载的方法，除了可以接受八种基本数据类型和String类型作为参数外，还可以接受一般的对象作为参数，编译器会自动调用这个对象的【toString】方法，char数组也可以作为这两个方法的参数。<br />74、Application的输入，分为两种，一是参数输入（命令行参数），Wrapper类的使用。基本数据类型与Wrapper类的对应关系。Wrapper类种有相应的parseXXX方法来实现字符串转换为基本数据类型。二是标准输入，System类的in属性是InputStream对象，有read方法来读取输入，读进来是byte对类型，需要转化为其他类数据型。通常使用InputStreamReader类，然后连接到BufferedReader类，用BufferedReader类提供的读取字符串的方法【readLine】。<br />75、系统参数的获取用【System.getProperties】方法。必须注意系统参数与命令行参数的区别。<br />76、System类的使用。setXXX(setOut、setErr、setIn)，setProperties和SetProperty的区别。System.exit(n)，虚拟机会调用Runtime.getRutime.exit(n)方法。currentTimeMills。<br />77、Runtime类的使用。可以通过exec这个方法来运行一个外部程序。<br />78、Appplication必须有一个main的方法，符合四个条件。而一个Applet一定要继承java.applet.Applet类。main方法是Application运行的起始点，而Applet运行的起始点在init方法上。Applet中，System.out或System.err方法来输出，但System.in方法不能用。Applet有自己的输入方式，类似于命令行参数的方式。在HTML文件中，加上参数语法，&lt;param name=&lt;参数名称&gt; value=&lt;参数值&gt;&gt;。然后在java程序中，应用java.applet.Applet类的【getParam】方法。<br />79、Applet基本方法的使用。init、start、stop、destroy、paint。destroy和finalize方法的区别在于使用地点不同。paint方法的使用。paint方法中有个属性是Graphics对象，注意Graphics类的【drawString】方法的使用。<br />80、java的安全性，是指Applet满足java指定的重重安全规范。四点限制措施。 <br />81、Application和Applet的结合。Java Web Start是取代Applet的机制。</p>
		<p>第12章 异常处理<br />82、异常是指程序在运行的过程中，由于编写程序的倏忽，外在环境的因素，或是电脑系统本身的问题，都可能导致程序运行时产生错误，造成死机或是计算的结果不正确，这些突发的状况称为异常。 异常处理是指当程序出现异常时，能够作出一些应变的处理。<br />83、java.lang.Throwable类。Exception类（可以控制）和Error类（无法控制）。<br />84、RuntimeException常见的有以下几种：ArithmeticException、ArrayIndexOutOfBoundsException、ArrayStoreException、ClassCastException、IllegalArgumentException、NativeArraySizeException、NullPointerException、SecurityException。由于自己编程引起的。<br />85、CheckedException常见的有以下几种：ClassNotFoundExecption、FileNotFoundException、InterrupedException、IOException、SQLException。一些外部因素引起的。<br />86、Error有OutOfMemoryError、StackOverflowError、UnknowError、AWTError、ThreadDeath。系统级且非常严重的错误。错误原因是内存不足或者是运行时挂起。<br />87、捕捉和处理异常。主要是针对CheckedException类的异常。try、catch、finally三个关键字的使用。处理异常包括以下两个步骤：一、把异常的名称及一些相关的信息显示出来，二、用最安全的方法恢复程序的运行。显示异常信息用到，toString、getLocalizedMessage、getMessage、printStackTrace方法。其中printStackTrace方法有三种不同的重载。弹性(flexibility)。 finally关键字的使用注意以下三点：一、没有异常产生－》进finally区块－》方法中剩下未运行的程序代码。二、有异常产生－》捕捉到－》进catch区块－》finally区块－》方法中剩下未运行的程序代码；三、有异常产生－》没有捕捉到－》进finally区块－》方法中剩下未运行的程序代码。                    <br />88、注意异常捕捉的顺序。越上层的类，越放在下面。<br />89、throws关键字的使用，在方法声明上抛出异常。throw关键字，在方法内部抛出异常。必须注意抛出RuntimeException和CheckedException两种异常在使用上的差别。<br />90、定义自己的Exception。<br />91、抛出异常方法覆盖的问题。注意两点：一、不可抛出原有方法抛出异常类的父类或上层类；二、抛出的异常类数目不能笔原有的方法抛出的还多。主要是因为编译时抛出的异常类无法自动转化为父类中所声明的异常类。</p>
		<p>第13章 容器(Container)与布局(Layout)<br />92、什么是AWT(Abstract Windowing Toolkit)，什么是GUI(Graphical User Interface)图形用户接口。AWT包的结构图。<br />93、Container包括Frame和Panel。Frame是先构造，然后setSize，然后再setVisible。理解Deprecation。Frame的常用方法。记住【Ctrl】＋【C】来停止程序的方法。Panel不能独立出现在画面上，必须放在某个Container中才行，例如Frame或浏览器里面。Applet本身就是一个panel。add方法的使用。<br />94、什么是Layout。【setLayout(&lt;xxxLayout&gt;)】方法。有五个基本的Layout类。Frame默认的布局是BorderLayout类。Panel默认的布局是FlowLayout。另外还有CardLayout、GridLayout、GridBagLayout。也可以设计自己的Layout类。<br />95、pack和setSize方法的区别。                                                      <br />96、如果不使用Layout，可以使用【setSize】和【setLocation】方法来代替。最好使用Layout类。                                                                                       <br />第14章 事件处理<br />97、什么是事件【event】。事件就是别人给予它的一些操作。明白事件处理结构：事件本身、事件产生的来源、谁来处理事件。<br />98、什么是委托处理模式【Delegation Model】。事件处理的机制。<br />99、AWT Event类的结构图。分为两类：Low－level和senmantic。<br />100、【Listener】这个接口(interface)与【Adapter】类的相对应。<br />101、一个对象可以委托好几个类来处理相同的事件，一个处理事件的类也可以同时处理不同对象所产生的事件。这种情况称为【multiplexer】。<br />102、WindowEvent、MouseEvent、KeyEvent类事件处理的接口，类和方法。以及其他常用的Low－level Event类，分别是ContainterEvent和FocusEvent。                            <br />103、Swing是Java所设计的另外一组更丰富、功能更多的GUI空间。理解Swing和AWT的区别。</p>
<img src ="http://www.blogjava.net/spark/aggbug/72493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-09-28 10:33 <a href="http://www.blogjava.net/spark/archive/2006/09/28/72493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java初学者备忘录</title><link>http://www.blogjava.net/spark/archive/2006/09/28/72492.html</link><dc:creator>空空</dc:creator><author>空空</author><pubDate>Thu, 28 Sep 2006 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/spark/archive/2006/09/28/72492.html</guid><wfw:comment>http://www.blogjava.net/spark/comments/72492.html</wfw:comment><comments>http://www.blogjava.net/spark/archive/2006/09/28/72492.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/spark/comments/commentRss/72492.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/spark/services/trackbacks/72492.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" width="96%" border="0">
				<tbody>
						<tr>
								<td>
										<p> 一.异常 <br /><br />　　Java对异常的处理同Delphi一样,不是刻意的去避免它的发生,而是等它发生后去补救. <br /><br />　　Delphi的异常处理简单来说就是一下语句 <br /><br />Try <br />Except//异常发生后就转入此处执行 <br />Finally//不管异常发不发生，都转入此处运行 <br />End <br /><br />　　与此相类似，Java的异常处理的基本形式如下 <br /><br />try{ <br />}catch(ExceptionType1 e){ <br />file&amp;://对/异常情况1的处理 <br />}catch(ExceptionType2 e){ <br />file&amp;://对/异常情况2的处理 <br />throw(e)//抛出异常,和Delphi中的raise是一回事 <br />} <br /><br />　　要补充的是,对大多数的异常,假如你要在正常运行的程序中而不是捕捉异常的程序中明确的抛出,Java的编译器需要你事先对你要抛出的异常作声明，否则不允许编译通过.这个任务是由throws来完成的. <br /><br />　　二.Java的输入输出流 <br /><br />　　2.1 输出 <br /><br />System.out.print　 file&amp;://这/里out是一个静态方法哦 <br />System.out.println <br />System.err.print　 file&amp;://err/和out一样也是标准输出,至于有什么不同,我目前还不清楚 <br />System.err.println <br /><br />　　2.2 输入 <br /><br />System.in.read() <br /><br />　　2.3 文件的操作 <br /><br />　　只需要几个带注释的例子就可以了。 <br /><br />　　第一个是一个显示文件基本信息的程序 <br /><br />import java.io.*;//调入和io相关的类 <br />class fileinfo{ <br />file&amp;://注/意,main函数一定是静态方法 <br /><br />　public static void main(String args[])throws IOException{ <br />　　File fileToCheck;//使用文件对象创建实例 <br />　　if (args.length&gt;0){ <br />　　　for (int i=0;i<br />　　　　fileToCheck=new File(args[i]);//为文件对象分配空间 <br />　　　　info(fileToCheck);//这里引用的info一定要是静态方法成员 <br />　　　} <br />　　} <br />　　else{ <br />　　　System.out.println("no file given"); <br />　　} <br />　} <br /><br />　public static void info(File f)throws IOException{ <br />　　System.out.println("Name:"+f.getName()); <br />　　System.out.println("Path:"+f.getPath()); <br />　　if (f.exists()){ <br />　　　System.out.println("File exists."); <br />　　　System.out.print((f.canRead()?" and is Readable":""));//判断函数，如果满足条件，输出前者，否则输出后者 <br />　　　System.out.print((f.canWrite()?"and is Writable":"")); <br />　　　System.out.print("."); <br />　　　System.out.println("File is"+f.length()+"bytes."); <br />　　} <br />　　else{ <br />　　　System.out.println("File does not exist."); <br />　　} <br />　} <br />} <br /><br /><br />　　第二个例子是一个存储电话信息的小程序,用户输入姓名和电话号码,程序将其存入phone.numbers文件中，通过FileOutputStream来实现 <br /><br />import java.io.*; <br /><br />class phones{ <br />　static FileOutputStream fos; <br />　public static final int lineLength=81; <br />　public static void main(String args[])throws IOException{ <br />　　byte[] phone=new byte[lineLength]; <br />　　byte[] name=new byte[lineLength]; <br />　　int i; <br />　　fos=new FileOutputStream("phone.numbers"); <br />　　while(true){ <br />　　　System.err.println("Enter a name(enter ‘done‘ to quit)"); <br />　　　readLine(name); <br />　　　if ("done".equalsIgnoreCase(new String(name,0,0,4))){ <br />　　　　break; <br />　　　} <br />　　　System.err.println("Enter the phone number"); <br />　　　readLine(phone); <br />　　　for (i=0;phone[i]!=0;i++){ <br />　　　　fos.write(phone[i]); <br />　　　} <br />　　　fos.write(‘,‘); <br />　　　for (i=0;name[i]!=0;i++){ <br />　　　　fos.write(name[i]); <br />　　　} <br />　　　fos.write(‘n‘); <br />　 } <br />　 fos.close(); <br />　} <br /><br />　private static void readLine(byte line[])throws IOException{ <br />　　int i=0,b=0; <br />　　while((i&lt;(lineLength-1))&amp;&amp;((b=System.in.read())!=‘n‘)){ <br />　　　line[i++]=(byte)b; <br />　　} <br />　　line[i]=(byte)(0); <br />　} <br />} <br />2.4 流 <br /><br />　　无非是两种 <br /><br />　　输出流,让我们来写的 <br /><br />　　输入流,给我们来读的 <br /><br />　　java.io包中有很多种类的输入输出流：<br /><br />　　1.FileInputStream和FileOutputStream 节点流 <br /><br />　　2.BufferedInputStream和BufferedOutputStream 过滤流 <br /><br />　　3.DataInputStream和DataOutputStream 增强的过滤流 <br /><br />　　4.PipedInputStream和PipledOutputStream 用于线程的流 <br /><br />　　掌握了流的概念,就可以开始Sockets的学习了.关于Socket的作用,昨天我已经讲了. <br /><br />　　现在,我们将创建一个简单的通讯程序,以获得对Socket的实质性的认识.该程序包括两个部分,客户机(RemoteFileClient)和服务器(RemoteFileServer).客户机向服务器发出请求,要求读取服务器上的文件信息.服务器将响应请求,将相应的文件信息传给客户机,将相应的文件信息传给客户机. <br /><br />　　首先我们创建RemoteFileClient类： <br /><br />import java.io.*;//java.io 包提供对流进行读写的工具,也是与 TCP 套接字通信的唯一途径 <br />import java.net.*;//java.net 包提供套接字工具。 <br /><br />public class RemoteFileClient { <br />　　protected String hostIp; <br />　　protected int hostPort; <br />　　protected BufferedReader socketReader;//负责读数据的对象 <br />　　protected PrintWriter socketWriter;//负责写数据的对象 <br /><br />　　file&amp;://类/的构造器有两个参数：远程主机的 IP 地址(hostIp)和端口号(hostPort)各一个.构造器将它们赋给实例变量 <br /><br />　　public RemoteFileClient(String aHostIp, int aHostPort) { <br />　　　　hostIp = aHostIp; <br />　　　　hostPort = aHostPort; <br />　　} <br />　　public static void main(String[] args) { <br />　　} <br />file&amp;://连/接到远程服务器 <br />　　public void setUpConnection() { <br />　　} <br />file&amp;://向/远程服务器请求文件信息 <br />　　public String getFile(String fileNameToGet) { <br />　　} <br />file&amp;://从/远程服务器上断开 <br />　　public void tearDownConnection() { <br />　　} <br />} <br /><br /><br />　　首先来实现main() <br /><br />public static void main(String[] args) { <br />　　RemoteFileClient remoteFileClient = new RemoteFileClient("127.0.0.1", 3000);//为了方便调试，我们把本地服务器当作远程服务器 <br />　　remoteFileClient.setUpConnection();//连接。不能直接使用setUpConnection，因为它是非静态变量，需要创建实例后，对实例进行引用，可以看我第一天的日记，上面写的非常详细 <br />　　String fileContents = <br />　　　　remoteFileClient.getFile("RemoteFile.txt");//读取 <br /><br />　　remoteFileClient.tearDownConnection();//断开 <br /><br />　　System.out.println(fileContents);//输出读取内容 <br />} <br /><br /><br />　　步骤非常清楚.那么我们分别看连接,读取,断开是怎么实现的 <br /><br />　　1.连接 <br /><br />public void setUpConnection() { <br />　　try { <br />　　　　Socket client = new Socket(hostIp, hostPort);//创建Socket对象 <br /><br /><br />　　　　 OutputStream outToServerStream=client.getOutputStream(); <br />　　　　 InputStream　inFromServerStream=client.getInputStream(); <br />　　　　 socketReader = new BufferedReader(new InputStreamReader(inFromServerStream)); <br />file&amp;://把/Socket的InputStream包装进BufferedReader 以使我们能够读取流的行 <br /><br />　　　　 socketWriter = new PrintWriter(outToServerStream); <br />file&amp;://把/Socket的OutputStream包装进PrintWriter 以使我们能够发送文件请求到服务器 <br /><br />　　} catch (UnknownHostException e) { <br />　　　　System.out.println("Error setting up socket connection: unknown host at " + hostIp + ":" + hostPort); <br />file&amp;://对/Socket对象创建错误的异常处理 <br />　　} catch (IOException e) { <br />　　　　System.out.println("Error setting up socket connection: " + e); <br />file&amp;://对/IO错误的异常处理 <br />　　} <br />} <br /><br />　　2.读取 <br /><br />public String getFile(String fileNameToGet) { <br />　　StringBuffer fileLines = new StringBuffer();//StringBuffer对象也是String对象，但是比它更灵活，这里是用来存放读取内容的 <br /><br />　　try { <br />　　　　socketWriter.println(fileNameToGet); <br />　　　　socketWriter.flush();//文件存放地址输出到socketWriter中,然后清空缓冲区,让这个地址送到服务器中去 <br /><br /><br />　　　　String line = null; <br />　　　　while ((line = socketReader.readLine()) != null) <br />　　　　　　fileLines.append(line + "n"); <br />file&amp;://既/然已经发送到服务器去了,那我们都要等待响应,这里的程序就是等待服务器把我们所需要的文件内容传过来 <br />　　} catch (IOException e) { <br />　　　　System.out.println("Error reading from file&amp;: " + fileNameToGet); <br />　　} <br /><br />　　return fileLines.toString();//别忘了把buffer中的内容转成String再返回 <br />} <br /><br />　　3.断开 <br /><br />public void tearDownConnection() { <br />　　try { <br />　　　　socketWriter.close(); <br />　　　　socketReader.close(); <br />　　} catch (IOException e) { <br />　　　　System.out.println("Error tearing down socket connection: " + e); <br />　　} <br />} <br /><br />　　tearDownConnection() 方法只别关闭我们在 Socket 的 InputStream 和 OutputStream 上创建的 BufferedReader 和 PrintWriter。这样做会关闭我们从 Socket 获取的底层流，所以我们必须捕捉可能的 IOException <br /><br />　　好,现在可以总结一下客户机程序的创建步骤了 <br /><br />　　1.用要连接的机器的IP端口号实例化Socket（如有问题则抛出 Exception）。 <br /><br />　　2.获取 Socket 上的流以进行读写. <br /><br />　　3.把流包装进 BufferedReader/PrintWriter 的实例. <br /><br />　　4.对 Socket 进行读写.具体说来,就是在Writer上传送文件地址信息给服务器,在Reader上读取服务器传来的文件信息 <br />5.关闭打开的流。 <br /><br />　　下面是RemoteFileClient 的代码清单 <br /><br />import java.io.*; <br />import java.net.*; <br /><br />public class RemoteFileClient { <br />　　protected BufferedReader socketReader; <br />　　protected PrintWriter socketWriter; <br />　　protected String hostIp; <br />　　protected int hostPort; <br /><br />　　public RemoteFileClient(String aHostIp, int aHostPort) { <br />　　　　hostIp = aHostIp; <br />　　　　hostPort = aHostPort; <br />　　} <br />　　public String getFile(String fileNameToGet) { <br />　　　　StringBuffer fileLines = new StringBuffer(); <br /><br />　　　　try { <br />　　　　　　socketWriter.println(fileNameToGet); <br />　　　　　　socketWriter.flush(); <br /><br />　　　　　　String line = null; <br />　　　　　　while ((line = socketReader.readLine()) != null) <br />　　　　　　　　fileLines.append(line + "n"); <br />　　　　} catch (IOException e) { <br />　　　　　　System.out.println("Error reading from file&amp;: " + fileNameToGet); <br />　　　　} <br /><br />　　　　return fileLines.toString(); <br />　　} <br />　　public static void main(String[] args) { <br />　　　　RemoteFileClient remoteFileClient = new RemoteFileClient("127.0.0.1", 3000); <br />　　　　remoteFileClient.setUpConnection(); <br />　　　　String fileContents = remoteFileClient.getFile("RemoteFile.txt"); <br />　　　　remoteFileClient.tearDownConnection(); <br /><br />　　　　System.out.println(fileContents); <br />　　} <br />　　public void setUpConnection() { <br />　　　　try { <br />　　　　　　Socket client = new Socket(hostIp, hostPort); <br /><br />　　　　　　OutputStream outToServerStream=client.getOutputStream(); <br />　　　　　　InputStream　inFromServerStream=client.getInputStream(); <br />　　　　　　socketReader = new BufferedReader(new InputStreamReader(inFromServerStream)); <br />　　　　　　socketWriter = new PrintWriter(outToServerStream); <br /><br />　　　　} catch (UnknownHostException e) { <br />　　　　　　System.out.println("Error setting up socket connection: unknown host at " + hostIp + ":" + hostPort); <br />　　　　} catch (IOException e) { <br />　　　　　　System.out.println("Error setting up socket connection: " + e); <br />　　　　} <br />　　} <br />　　public void tearDownConnection() { <br />　　　　try { <br />　　　　　　socketWriter.close(); <br />　　　　　　socketReader.close(); <br />　　　　} catch (IOException e) { <br />　　　　　　System.out.println("Error tearing down socket connection: " + e); <br />　　　　} <br />　　} <br />} <br /><br />　　好了,现在来看服务器端的程序怎么写. <br /><br />　　创建RemoteClientServer类： <br /><br />import java.io.*; <br />import java.net.*; <br /><br />public class RemoteFileServer { <br />　　protected int listenPort = 3000; <br />　　public static void main(String[] args) { <br />　　} <br />　　public void acceptConnections() { <br />　　} <br />　　public void handleConnection(Socket incomingConnection) { <br />　　} <br />} <br /><br />　　跟客户机中一样，首先导入 java.net 的 java.io。接着,给我们的类一个实例变量以保存端口,我们从该端口侦听进入的连接。缺省情况下，端口是 3000。 <br /><br />acceptConnections()将允许客户机连接到服务器 <br />handleConnection()负责与客户机 Socket 交互以将您所请求的文件的内容发送到客户机。 <br /><br />　　首先看main() <br /><br />public static void main(String[] args) { <br />　　RemoteFileServer server = new RemoteFileServer(); <br />　　server.acceptConnections(); <br />} <br /><br />　　非常简单,因为主函数无非是让服务器进入监听状态,所以直接调用acceptConnection().需要注意的是,必须先创建RemoteFileServer()的实例,而不是直接调用. <br /><br />　　那么服务器是怎样通过acceptConnection()来监听客户机的连接呢？并且如果兼听到了，又怎样处理呢？我们来看 <br /><br />public void acceptConnections() { <br />　　try { <br />　　　　ServerSocket server = new ServerSocket(listenPort);//同客户机的Socket对应,在服务器端,我们需要ServerSocket对象,参数是兼听的端口号 <br />　　　　Socket incomingConnection = null;//创建一个客户端的Socket变量,以接收从客户端监听到的Socket <br />　　　　while (true) { <br />　　　　　　incomingConnection = server.accept();//调用该 ServerSocket 的 accept() 来告诉它开始侦听, <br />　　　　　　handleConnection(incomingConnection); <br />　　　　} <br />file&amp;://不/断监听直到来了一个连接请求,然后交由handleConnection处理 <br />　　} catch (BindException e) { <br />　　　　System.out.println("Unable to bind to port " + listenPort); <br />　　} catch (IOException e) { <br />　　　　System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort); <br />　　} <br />} <br /><br />　　无论何时如果创建了一个无法绑定到指定端口（可能是因为别的什么控制了该端口）的 ServerSocket，Java 代码都将抛出一个错误。所以这里我们必须捕捉可能的 BindException。同时，与在客户机端上时一样，我们必须捕捉 IOException，当我们试图在 ServerSocket 上接受连接时，它就会被抛出。可以通过用毫秒数调用 setSoTimeout() 来为 accept() 调用设置超时，以避免实际长时间的等待。调用 setSoTimeout() 将使 accept() 经过指定占用时间后抛出 IOException <br /><br />　　最关键的处理在handleConnection()中，这时已经连接到了客户端的Socket，要从该Socket中读取客户端的请求并且响应。 <br /><br />public void handleConnection(Socket incomingConnection) { <br />　　try { <br />　　　　OutputStream outputToSocket = incomingConnection.getOutputStream(); <br />　　　　InputStream inputFromSocket = incomingConnection.getInputStream(); <br /><br />file&amp;://首/先获取同Socket相关联的流outputToSocket和InputStream <br />file&amp;://其/中outputToSocket是要返回给客户端Socket的流 <br />file&amp;://InputStream/是客户端发来的请求,在这里就是文件路径,即"RemoteFile.txt" <br /><br />　　　　BufferedReader streamReader = <br />　　　　　　new BufferedReader(new InputStreamReader(inputFromSocket)); <br /><br />file&amp;://首/先要将InputStream转换到BufferedReader中 <br /><br />　　　　FileReader fileReader = new FileReader(new File(streamReader.readLine())); <br />file&amp;://从/BufferedReader中读出文件路径,建立新对象FileReader <br /><br />　　　　BufferedReader bufferedFileReader = new BufferedReader(fileReader); <br /><br />file&amp;://再/次建立BufferedReader对象，这一次它读取得是文件里面的内容 <br /><br />　　　　PrintWriter streamWriter = <br />　　　　　　new PrintWriter(OutputStream); <br /><br />file&amp;://把/Socket的outputToSocket流包装进PrintWriter 以使我们能够发送文件信息到客户端 <br /><br />　　　　String line = null; <br />　　　　while ((line = bufferedFileReader.readLine()) != null) { <br />　　　　　　streamWriter.println(line); <br />　　　　} <br />file&amp;://从/bufferedFileReader中读出文件信息，再经由streamWriter输出到客户端 <br /><br />　　　　fileReader.close(); <br />　　　　streamWriter.close();//注意Socket的两个流关闭的顺序 <br />　　　　streamReader.close(); <br />file&amp;://完/成之后关闭所有流 <br /><br />　　} catch (Exception e) { <br />　　　　System.out.println("Error handling a client: " + e); <br />　　} <br />} <br /><br /><br />　　请注意完成所有操作之后关闭流的顺序，streamWriter的关闭在streamReader的关闭之前。这不是偶然的,假如将关闭次序颠倒过来,客户端将不会获取到任何文件信息,你可以调试一下看看.这是为什么呢?原因是如果你在关闭 streamWriter 之前关闭 streamReader，则你可以以往 streamWriter中写任何东西，但没有任何数据可以通过通道（通道被关闭了）.但奇怪的是,我不是已经在之前的streamWriter.println()中输出了吗?难道非要等到所有的流关闭之后输出到客户端的信息的东西才能到达?我试着将 <br /><br />streamWriter.close(); <br />streamReader.close(); <br /><br />　　屏蔽掉，看是否依然能够实现正常的通信,结果发现不行,程序死机.可能是因为通道没有闭合导致的.那么至少可以说明,只有将通道按某种顺序正常关闭,才能完成通讯数据的传输,否则客户端收不到信息. <br /><br />　　最后依然是总结一下创建服务器端程序的步骤 <br /><br />　　1.用一个你想让它侦听传入客户机连接的端口(比如程序中的3000)来实例化一个 ServerSocket（如有问题则抛出 Exception）。 <br /><br />　　2.循环调用ServerSocket的accept()以监听连接 <br /><br />　　3.获取客户端的Socket流以进行读写操作 <br /><br />　　4.包装流 <br /><br />　　5.对客户端的Socket进行读写 <br /><br />　　6.关闭打开的流(切记,永远不要在关闭 Writer 之前关闭 Reader),完成通信 <br /><br />　　下面是 <br /><br />RemoteFileServer 的代码清单 <br /><br />import java.io.*; <br />import java.net.*; <br /><br />public class RemoteFileServer { <br />　　int listenPort; <br />　　public RemoteFileServer(int aListenPort) { <br />　　　　listenPort = aListenPort; <br />　　} <br />　　public void acceptConnections() { <br />　　　　try { <br />　　　　　　ServerSocket server = new ServerSocket(listenPort); <br />　　　　　　Socket incomingConnection = null; <br />　　　　　　while (true) { <br />　　　　　　　　incomingConnection = server.accept(); <br />　　　　　　　　handleConnection(incomingConnection); <br />　　　　　　} <br />　　　　} catch (BindException e) { <br />　　　　　　System.out.println("Unable to bind to port " + listenPort); <br />　　　　} catch (IOException e) { <br />　　　　　　System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort); <br />　　　　} <br />　　} <br />　　public void handleConnection(Socket incomingConnection) { <br />　　　　try { <br />　　　　　　OutputStream outputToSocket = incomingConnection.getOutputStream(); <br />　　　　　　InputStream inputFromSocket = incomingConnection.getInputStream(); <br /><br />　　　　　　BufferedReader streamReader = new BufferedReader(new InputStreamReader(inputFromSocket)); <br /><br />　　　　　　FileReader fileReader = new FileReader(new File(streamReader.readLine())); <br /><br />　　　　　　BufferedReader bufferedFileReader = new BufferedReader(fileReader); <br />　　　　　　PrintWriter streamWriter = new PrintWriter(outputToSocket); <br />　　　　　　String line = null; <br />　　　　　　while ((line = bufferedFileReader.readLine()) != null) { <br />　　　　　　　　streamWriter.println(line); <br />　　　　　　} <br /><br />　　　　　　fileReader.close(); <br />　　　　　　streamWriter.close(); <br />　　　　　　streamReader.close(); <br />　　　　} catch (Exception e) { <br />　　　　　　System.out.println("Error handling a client: " + e); <br />　　　　} <br />　　} <br />　　public static void main(String[] args) { <br />　　　　RemoteFileServer server = new RemoteFileServer(3000); <br />　　　　server.acceptConnections(); <br />　　} <br />}</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/spark/aggbug/72492.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/spark/" target="_blank">空空</a> 2006-09-28 10:32 <a href="http://www.blogjava.net/spark/archive/2006/09/28/72492.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>