??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品乱码久久久久久下载,亚洲无线一二三四区,亚洲日韩乱码中文无码蜜桃臀网站 http://m.tkk7.com/spark/category/15766.html智慧是第一生?/description>zh-cnThu, 21 Jan 2010 01:14:18 GMTThu, 21 Jan 2010 01:14:18 GMT60ftp实现上传下蝲Q解决了(jin)~码问题?/title><link>http://m.tkk7.com/spark/archive/2010/01/19/310032.html</link><dc:creator>I空</dc:creator><author>I空</author><pubDate>Tue, 19 Jan 2010 01:16:00 GMT</pubDate><guid>http://m.tkk7.com/spark/archive/2010/01/19/310032.html</guid><wfw:comment>http://m.tkk7.com/spark/comments/310032.html</wfw:comment><comments>http://m.tkk7.com/spark/archive/2010/01/19/310032.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/spark/comments/commentRss/310032.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/spark/services/trackbacks/310032.html</trackback:ping><description><![CDATA[     摘要:     很多人都到ftp的上传下载文件的实现Q很Ҏ(gu)到一些问题,最难解决的是ؕ码的问题Q?在网上搜索了(jin)挺多Q也没h能讲得清楚详l的Q这里把自己实现的程序脓(chung)出来Q供大家参考?以后到q些问题Q可以自己多看看java的APIQ还是很有帮助的?    另外在实现ftp上传下蝲的时候,q要多考虑一下上传下载失败或...  <a href='http://m.tkk7.com/spark/archive/2010/01/19/310032.html'>阅读全文</a><img src ="http://m.tkk7.com/spark/aggbug/310032.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/spark/" target="_blank">I空</a> 2010-01-19 09:16 <a href="http://m.tkk7.com/spark/archive/2010/01/19/310032.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 实现ftp上传下蝲(?http://m.tkk7.com/spark/archive/2009/09/22/295975.htmlI空I空Tue, 22 Sep 2009 03:02:00 GMThttp://m.tkk7.com/spark/archive/2009/09/22/295975.htmlhttp://m.tkk7.com/spark/comments/295975.htmlhttp://m.tkk7.com/spark/archive/2009/09/22/295975.html#Feedback1http://m.tkk7.com/spark/comments/commentRss/295975.htmlhttp://m.tkk7.com/spark/services/trackbacks/295975.html

package com.why.ftp;     
    
import java.io.DataInputStream;     
import java.io.File;     
import java.io.FileInputStream;     
import java.io.FileOutputStream;     
import java.io.IOException;     
import java.io.OutputStream;     
import java.util.ArrayList;     
import java.util.List;     
import java.util.StringTokenizer;     
import sun.net.TelnetInputStream;     
import sun.net.TelnetOutputStream;     
import sun.net.ftp.FtpClient;     
    
/**   
 * ftp上传Q下?nbsp;  
 * @author why 2009-07-30   
 *   
 */    
public class FtpUtil {     
    
    private String ip = "";     
    
    private String username = "";     
    
    private String password = "";     
    
    private int port = -1;     
    
    private String path = "";     
    
    FtpClient ftpClient = null;     
    
    OutputStream os = null;     
    
    FileInputStream is = null;     
    
    public FtpUtil(String serverIP, String username, String password) {     
        this.ip = serverIP;     
        this.username = username;     
        this.password = password;     
    }     
         
    public FtpUtil(String serverIP, int port, String username, String password) {     
        this.ip = serverIP;     
        this.username = username;     
        this.password = password;     
        this.port = port;     
    }     
    
    /**   
     * q接ftp服务?nbsp;  
     *    
     * @throws IOException   
     */    
    public boolean connectServer(){     
        ftpClient = new FtpClient();     
        try {     
            if(this.port != -1){     
                    ftpClient.openServer(this.ip,this.port);     
            }else{     
                ftpClient.openServer(this.ip);     
            }     
            ftpClient.login(this.username, this.password);     
            if (this.path.length() != 0){     
                ftpClient.cd(this.path);// path是ftp服务下主目录的子目录                
            }     
            ftpClient.binary();// ?q制上传、下?nbsp;    
            System.out.println("已登录到\"" + ftpClient.pwd() + "\"目录");     
            return true;     
        }catch (IOException e){     
            e.printStackTrace();     
            return false;     
        }     
    }     
         
    /**   
     * 断开与ftp服务器连?nbsp;  
     *    
     * @throws IOException   
     */    
    public boolean closeServer(){     
        try{     
            if (is != null) {     
                is.close();     
            }     
            if (os != null) {     
                os.close();     
            }     
            if (ftpClient != null) {     
                ftpClient.closeServer();     
            }     
            System.out.println("已从服务器断开");     
            return true;     
        }catch(IOException e){     
            e.printStackTrace();     
            return false;     
        }     
    }     
         
    /**   
     * (g)查文件夹在当前目录下是否存在   
     * @param dir   
     * @return   
     */    
     private boolean isDirExist(String dir){     
         String pwd = "";     
         try {     
             pwd = ftpClient.pwd();     
             ftpClient.cd(dir);     
             ftpClient.cd(pwd);     
         }catch(Exception e){     
             return false;     
         }     
         return true;      
     }     
         
    /**   
     * 在当前目录下创徏文g?nbsp;  
     * @param dir   
     * @return   
     * @throws Exception   
     */    
     private boolean createDir(String dir){     
         try{     
            ftpClient.ascii();     
            StringTokenizer s = new StringTokenizer(dir, "/"); //sign     
            s.countTokens();     
            String pathName = ftpClient.pwd();     
            while(s.hasMoreElements()){     
                pathName = pathName + "/" + (String) s.nextElement();     
                try {     
                    ftpClient.sendServer("MKD " + pathName + "\r\n");     
                } catch (Exception e) {     
                    e = null;     
                    return false;     
                }     
                ftpClient.readServerResponse();     
            }     
            ftpClient.binary();     
            return true;     
        }catch (IOException e1){     
            e1.printStackTrace();     
            return false;     
        }     
     }     
          
     /**   
      * ftp上传   
      * 如果服务器段已存在名为filename的文件夹Q该文g夹中与要上传的文件夹中同名的文g被替换   
      *    
      * @param filename 要上传的文gQ或文g夹)(j)?nbsp;  
      * @return   
      * @throws Exception   
      */    
    public boolean upload(String filename){     
        String newname = "";     
        if(filename.indexOf("/") > -1){     
            newname = filename.substring(filename.lastIndexOf("/") + 1);     
        }else{     
            newname = filename;     
        }     
        return upload(filename, newname);     
    }     
          
     /**   
      * ftp上传   
      * 如果服务器段已存在名为newName的文件夹Q该文g夹中与要上传的文件夹中同名的文g被替换   
      *    
      * @param fileName 要上传的文gQ或文g夹)(j)?nbsp;  
      * @param newName 服务器段要生成的文gQ或文g夹)(j)?nbsp;  
      * @return   
      */    
     public boolean upload(String fileName, String newName){     
         try{     
             String savefilename = new String(fileName.getBytes("ISO-8859-1"), "GBK");      
             File file_in = new File(savefilename);//打开本地待长传的文g     
             if(!file_in.exists()){     
                 throw new Exception("此文件或文g夹[" + file_in.getName() + "]有误或不存在!");     
             }     
             if(file_in.isDirectory()){     
                 upload(file_in.getPath(),newName,ftpClient.pwd());     
             }else{     
                 uploadFile(file_in.getPath(),newName);     
             }     
                  
             if(is != null){     
                 is.close();     
             }     
             if(os != null){     
                 os.close();     
             }     
             return true;     
         }catch(Exception e){      
                e.printStackTrace();      
                System.err.println("Exception e in Ftp upload(): " + e.toString());      
                return false;     
         }finally{     
             try{     
                 if(is != null){     
                     is.close();     
                 }     
                 if(os != null){      
                     os.close();      
                 }     
             }catch(IOException e){     
                 e.printStackTrace();     
            }      
         }     
     }     
          
     /**   
      * 真正用于上传的方?nbsp;  
      * @param fileName   
      * @param newName   
      * @param path   
      * @throws Exception   
      */    
     private void upload(String fileName, String newName,String path) throws Exception{     
             String savefilename = new String(fileName.getBytes("ISO-8859-1"), "GBK");      
             File file_in = new File(savefilename);//打开本地待长传的文g     
             if(!file_in.exists()){     
                 throw new Exception("此文件或文g夹[" + file_in.getName() + "]有误或不存在!");     
             }     
             if(file_in.isDirectory()){     
                 if(!isDirExist(newName)){     
                     createDir(newName);     
                 }     
                 ftpClient.cd(newName);     
                 File sourceFile[] = file_in.listFiles();     
                 for(int i = 0; i < sourceFile.length; i++){     
                     if(!sourceFile[i].exists()){     
                         continue;     
                     }     
                     if(sourceFile[i].isDirectory()){     
                         this.upload(sourceFile[i].getPath(),sourceFile[i].getName(),path+"/"+newName);     
                     }else{     
                         this.uploadFile(sourceFile[i].getPath(),sourceFile[i].getName());     
                      }     
                    }     
             }else{     
                 uploadFile(file_in.getPath(),newName);     
             }     
             ftpClient.cd(path);     
     }     
    
    /**   
     *  upload 上传文g   
     *    
     * @param filename 要上传的文g?nbsp;  
     * @param newname 上传后的新文件名   
     * @return -1 文g不存?>=0 成功上传Q返回文件的大小   
     * @throws Exception   
     */    
    public long uploadFile(String filename, String newname) throws Exception{     
        long result = 0;     
        TelnetOutputStream os = null;     
        FileInputStream is = null;     
        try {     
            java.io.File file_in = new java.io.File(filename);     
            if(!file_in.exists())     
                return -1;     
            os = ftpClient.put(newname);     
            result = file_in.length();     
            is = new FileInputStream(file_in);     
            byte[] bytes = new byte[1024];     
            int c;     
            while((c = is.read(bytes)) != -1){     
                os.write(bytes, 0, c);     
            }     
        }finally{     
            if(is != null){     
                is.close();     
            }     
            if(os != null){     
                os.close();     
            }     
        }     
        return result;     
    }     
    
    /**   
     * 从ftp下蝲文g到本?nbsp;  
     *    
     * @param filename 服务器上的文件名   
     * @param newfilename 本地生成的文件名   
     * @return   
     * @throws Exception   
     */    
    public long downloadFile(String filename, String newfilename){     
        long result = 0;     
        TelnetInputStream is = null;     
        FileOutputStream os = null;     
        try{     
            is = ftpClient.get(filename);     
            java.io.File outfile = new java.io.File(newfilename);     
            os = new FileOutputStream(outfile);     
            byte[] bytes = new byte[1024];     
            int c;     
            while ((c = is.read(bytes)) != -1) {     
                os.write(bytes, 0, c);     
                result = result + c;     
            }     
        }catch (IOException e){     
            e.printStackTrace();     
        }finally{     
            try {     
                if(is != null){     
                        is.close();     
                }     
                if(os != null){     
                    os.close();     
                }     
            } catch (IOException e) {     
                e.printStackTrace();     
            }     
        }     
        return result;     
    }     
    
    /**   
     * 取得相对于当前连接目录的某个目录下所有文件列?nbsp;  
     *    
     * @param path   
     * @return   
     */    
    public List getFileList(String path){     
        List list = new ArrayList();     
        DataInputStream dis;     
        try {     
            dis = new DataInputStream(ftpClient.nameList(this.path + path));     
            String filename = "";     
            while((filename = dis.readLine()) != null){     
                list.add(filename);     
            }     
        } catch (IOException e) {     
            e.printStackTrace();     
        }     
        return list;     
    }     
    
         
    
    public static void main(String[] args){     
        FtpUtil ftp = new FtpUtil("133.224.202.2","tstbill","tstbill");     
        ftp.connectServer();     
        boolean result = ftp.upload("C:/test_why", "test_why/test");     
        System.out.println(result?"上传成功Q?:"上传p|Q?);     
        List list = ftp.getFileList("test_why/test");     
        for(int i=0;i<list.size();i++){     
            String name = list.get(i).toString();     
            System.out.println(name);     
        }     
        ftp.closeServer();     
        /**   
        FTPq程命o(h)列表   
        USER    PORT    RETR    ALLO    DELE    SITE    XMKD    CDUP    FEAT   
        PASS    PASV    STOR    REST    CWD     STAT    RMD     XCUP    OPTS   
        ACCT    TYPE    APPE    RNFR    XCWD    HELP    XRMD    STOU    AUTH   
        REIN    STRU    SMNT    RNTO    LIST    NOOP    PWD     SIZE    PBSZ   
        QUIT    MODE    SYST    ABOR    NLST    MKD     XPWD    MDTM    PROT   
        在服务器上执行命?如果用sendServer来执行远E命?不能执行本地FTP命o(h))的话Q所有FTP命o(h)都要加上\r\n   
        ftpclient.sendServer("XMKD /test/bb\r\n"); //执行服务器上的FTP命o(h)   
        ftpclient.readServerResponse一定要在sendServer后调?nbsp;  
        nameList("/test")获取指目录下的文件列?nbsp;  
        XMKD建立目录Q当目录存在的情况下再次创徏目录时报?nbsp;  
        XRMD删除目录   
        DELE删除文g   
         */    
    }     
    
}  


下面是FtpClientcȝ一些介l:(x)

sun.net.ftp.FtpClient.Q该cd主要提供?jin)用于徏立FTPq接的类。利用这些类的方法,~程人员可以q程d到FTP服务器,列D该服务器上的目录Q设|传输协议,以及(qing)传送文件。FtpClientcL盖了(jin)几乎所有FTP的功能,FtpClient的实例变量保存了(jin)有关建立"代理"的各U信息。下面给Z(jin)q些实例变量Q?/p>

  public static boolean useFtpProxy
  q个变量用于表明FTP传输q程中是否用了(jin)一个代理,因此Q它实际上是一个标讎ͼ此标记若为TRUEQ表明用了(jin)一个代理主机?/p>

  public static String ftpProxyHost
  此变量只有在变量useFtpProxy为TRUE时才有效Q用于保存代理主机名?/p>

  public static int ftpProxyPort
  此变量只有在变量useFtpProxy为TRUE时才有效Q用于保存代理主机的端口地址?/p>

  FtpClient有三U不同Ş式的构造函敎ͼ如下所C:(x)

  1、public FtpClient(String hostname,int port)
   此构造函数利用给出的L名和端口号徏立一条FTPq接?/p>

  2、public FtpClient(String hostname)
  此构造函数利用给出的L名徏立一条FTPq接Q用默认端口号?/p>

  3、FtpClient()
  此构造函数将创徏一FtpClientc,但不建立FTPq接。这ӞFTPq接可以用openServerҎ(gu)建立?/p>

  一旦徏立了(jin)cFtpClientQ就可以用这个类的方法来打开与FTP服务器的q接。类ftpClient提供?jin)如下两个可用于打开与FTP服务器之间的q接的方法?/p>

  public void openServer(String hostname)
  q个Ҏ(gu)用于建立一条与指定L上的FTP服务器的q接Q用默认端口号?/p>

  public void openServer(String host,int port)
  q个Ҏ(gu)用于建立一条与指定L、指定端口上的FTP服务器的q接?/p>

  打开q接之后Q接下来的工作是注册到FTP服务器。这旉要利用下面的Ҏ(gu)?/p>

  public void login(String usernameQString password)
  此方法利用参数username和passwordd到FTP服务器。用过Intemet的用户应该知道,匿名FTP服务器的d用户名ؓ(f)anonymousQ密码一般用自己的电(sh)子邮件地址?/p>

  下面是FtpClientcL提供的一些控制命令?/p>

  public void cd(String remoteDirectory)Q该命o(h)用于把远E系l上的目录切换到参数remoteDirectory所指定的目录?br />   public void cdUp()Q该命o(h)用于把远E系l上的目录切换到上一U目录?br />   public String pwd()Q该命o(h)可显CE系l上的目录状态?br />   public void binary()Q该命o(h)可把传输格式讄Zq制格式?br />   public void ascii()Q该命o(h)可把传输协议讄为ASCII码格式?br />   public void rename(String stringQString string1)Q该命o(h)可对q程pȝ上的目录或者文件进行重命名操作?/p>

  除了(jin)上述Ҏ(gu)外,cFtpClientq提供了(jin)可用于传递ƈ(g)索目录清单和文g的若q方法。这些方法返回的是可供读或写的输入、输出流。下面是其中一些主要的Ҏ(gu)?/p>

  public TelnetInputStream list()
  q回与远E机器上当前目录相对应的输入?/p>

  public TelnetInputStream get(String filename)
  获取q程机器上的文gfilenameQ借助TelnetInputStream把该文g传送到本地?/p>

  public TelnetOutputStream put(String filename)
  以写方式打开一输出,通过q一输出把文gfilename传送到q程计算?/p>

I空 2009-09-22 11:02 发表评论
]]>
javax.naming.NameNotFoundException: Name jdbc is not bound in this Contexthttp://m.tkk7.com/spark/archive/2009/09/08/294339.htmlI空I空Tue, 08 Sep 2009 09:47:00 GMThttp://m.tkk7.com/spark/archive/2009/09/08/294339.htmlhttp://m.tkk7.com/spark/comments/294339.htmlhttp://m.tkk7.com/spark/archive/2009/09/08/294339.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/294339.htmlhttp://m.tkk7.com/spark/services/trackbacks/294339.html 启动的时候报错(在项目目录下Q在tomcat中配|context指向目目录没问题Q打包发布到
tomcat报错了(jin)Q,抛的异常是:(x)
javax.naming.NameNotFoundException: Name jdbc is not bound in this Context

在web.xml中添加配|如下:(x)
<resource-ref>
  <description>DB Connection</description>
  <res-ref-name>jdbc/test</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
 </resource-ref>


I空 2009-09-08 17:47 发表评论
]]>
java web应用E序转exehttp://m.tkk7.com/spark/archive/2009/05/21/274556.htmlI空I空Thu, 21 May 2009 14:28:00 GMThttp://m.tkk7.com/spark/archive/2009/05/21/274556.htmlhttp://m.tkk7.com/spark/comments/274556.htmlhttp://m.tkk7.com/spark/archive/2009/05/21/274556.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/274556.htmlhttp://m.tkk7.com/spark/services/trackbacks/274556.html  最q做?jin)一个小的web应用Q客户那辚w不常用java环境Q让他们安装、配|java、tomcat环境对他们来说太难ؓ(f)他们?jin)?br /> 所以花?jin)点旉研究了(jin)下exe文g的制作,java web应用制作成exe文gQƈ打包?jin)jre环境Q最后生成启动服务器的快h式?br /> 打开IE的快h式,感觉q样成?jin)傻瓜型的?jin)Q^!^ ׃上网找资料花?jin)不时_(d)想着方便那些有类似需要的朋友Q就
在此ȝ一下,希望能帮助到别h吧?br />
  在一个没有java环境的系l中(此处只应用于windows)Q要执行web应用Q需要jdk、tomcatQ服务器Q,我是机器上装的jdk目录?br /> tomcat目录拯C个目录,q有数据库客L(fng)Q这里用的hsqlQ就不详l说?jin)。这里主要注意的问题主要是环境变量的设|,
在tomcat\bin目录中我们需要设|java_home和CATALINA_HOMEQ设|方法如下:(x)
打开tomcat\bin\startup.bat,对其中if exist "%CATALINA_HOME%\bin\catalina.bat" goto okHomeq样的语句都UdC面代码的后面Q?br /> set CURRENT_DIR=%cd%                                                          注释Q取得当前目录tomcat\bin
set CATALINA_HOME=%CURRENT_DIR%                                                                 
cd ..                                                                                                注释Q到上一U目录tomcat                                                  
set CATALINA_HOME=%cd%                                                    
cd ..                                                                                               注释Q到上一U目录delply
set JAVA_HOME=%cd%\jdk                                                       注释Q设|JAVA_HOME
set JRE_HOME=%cd%\jdk\jre                                                      注释Q设|JRE_HOME
其实q里的关键就是不使用以前的判断,直接讄CATALINA_HOME、JAVA_HOME{到你打包的目录
注意我的目录l构如下Q大家可Ҏ(gu)需要适当调整上面的代码:(x)
deploy
------->tomcat
------->jdk

    再一点就是NSIS的用,可以使用它提供的VNISEdit~译环境中的 新徏脚本Q向D行配|,其中要注意的问题?br /> 1. 选择目录的时候,讄的是目录下的内容Q不包括目录Q?br /> 2. 通过向导配置的快h式有炚w题,需要手工改动编码,主要是下面的内容Q?br /> Section "yourapp" SEC01
  SetOutPath "$INSTDIR"                     (q里是你的根目录Q我q里是deploy)
  SetOverwrite ifnewer
  File /r "..\deploy\*.*"                          (注意q里的格?
SectionEnd

Section -AdditionalIcons
  SetOutPath "$INSTDIR\tomcat\bin"                   (q里是你快捷方式的v始位|,卛_h式指向的那个文g的目录,前面讄的是根目录,q里需要重新设|,如果在前面设|的话,你的根目录就变成?jin)你的快h式指向的那个文g的目录了(jin)Q一定要注意q里的问?
  CreateDirectory "$SMPROGRAMS\IBS"
  CreateShortCut "$desktop\StartServer.lnk" "$INSTDIR\tomcat\bin\startup.bat" "" "$INSTDIR\tomcat\start-server.ico"              Q我q里是把tomcat里的startup.bat建立?jin)桌面快h式,后面是我讄的图标)(j)
  CreateShortCut "$desktop\StartIBS.lnk" "http://localhost:9000/appname" "" "$INSTDIR\tomcat\app_ie.ico"  Q这里是我徏立的桌面快捷方式Q点d打开的是我制定的|址Q?br />   CreateShortCut "$SMPROGRAMS\IBS\Uninstall.lnk" "$INSTDIR\uninst.exe"
SectionEnd

ȝ上面的内容,是我们在打包java webpȝӞ主要是把tomcat、jdk攑ֈ一个目录下Q用NSIS工具其压羃卛_Q需要注意的是两点Q一是tomcat?br /> 对CATALINA_HOME、java_home的设|,二就是nsis脚本中的目录讄、快h式的讄?jin)。?/p>

I空 2009-05-21 22:28 发表评论
]]>
JAVA新手学习(fn)指南[转]http://m.tkk7.com/spark/archive/2009/02/10/254094.htmlI空I空Tue, 10 Feb 2009 07:35:00 GMThttp://m.tkk7.com/spark/archive/2009/02/10/254094.htmlhttp://m.tkk7.com/spark/comments/254094.htmlhttp://m.tkk7.com/spark/archive/2009/02/10/254094.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/254094.htmlhttp://m.tkk7.com/spark/services/trackbacks/254094.html每个人的学习(fn)Ҏ(gu)是不同的Q一个h的方法不见得适合另一个hQ我只能是谈自己的学?fn)方法。因为我学习(fn)Java是完全自学的Q从来没有问q别人,所以学?fn)的q程基本上完全是自己摸烦(ch)出来的。我也不知道q种Ҏ(gu)是否是比较好的方法,只能l大家提供一点参考了(jin)?

学习(fn)Java的第一步是安装好JDKQ写一个Hello WorldQ 其实JDK的学?fn)没有那么简单,关于JDK有两个问题是很容易一直困?JavaE序员的地方Q一个是CLASSPATH的问题,其实从原理上来说Q是要搞清楚JRE的ClassLoader是如何加载Class的;另一个问题是package和import问题Q如何来Lcȝ路径问题。把q两个问题摸索清楚了(jin)Q就扫除?jin)学习(fn)Java和用JDK的最大障。推荐看一下王的《Java深度历险》,对这两个问题q行?jin)深入的探讨?

W二步是学习(fn)Java的语法。Java的语法是cC++的,基本上主的~程语言不是cCQ就是类C++的,没有什么新东西Q所以语法的学习(fn)Q大概就是半天的旉_?jin)。唯一需要注意的是有几个不容易搞清楚的关键字的用法,publicQprotectedQprivateQstaticQ什么时候用Qؓ(f)什么要用,怎么用,q可能需要有人来指点一下,我当初是完全自己琢磨出来的,׃(jin)很久的时间。不q后来我看到《Thinking in Java》这本书上面是讲?jin)这些概늚?

W三步是学习(fn)Java的面向对象的~程语言的特性的地方。比如承,构造器Q抽象类Q接口,Ҏ(gu)的多态,重蝲Q覆盖,Java的异常处理机制。对于一个没有面向对象语a背景的h来说Q我觉得q个q程需要花很长很长旉Q因为学?fn)Java之前没有C++的经验,只有C的经验,我是大概׃(jin)一个月左右吧,才彻底把q些概念都搞清楚Q把书上面的例子反复的揣摩,修改Q尝试,把那几章内容反复的看q来Q看q去Q看?jin)不?遍,才彻底领(zhn)了(jin)。不q我惛_果有 C++l验的话Q应该一两天旉_?jin)。那么在q个q程中,可以多看看《Thinking in Java》这本书Q对面向对象的讲解非帔R彻。可惜的是我学习(fn)的时候,q没有看到这本书Q所以自p?jin)大量的旉Q通过自己的尝试和揣摩来学?x)的?

W四步就是开始熟(zhn)Java的类库。Java的基cd其实是JDK安装目录下面jre\lib\rt.jarq个包。学?fn)基cd是学习(fn)rt.jar。基cd里面的类非常非常多。据说有3000多个Q我没有l计q。但是真正对于我们来说最核心(j)的只?个,分别?
java.lang.*;
java.io.*;
java.util.*;
java.sql.*;

q四个包的学?fn),每个包的学?fn)都可以写成一本厚厚的教材Q而O'reilly也确实是q样做的。我觉得如果旉比较紧,是不可能通过d本书来学?fn)。我觉得比较好的学习(fn)Ҏ(gu)是这L(fng)Q?
首先要通读整个package的框Ӟ?jin)解整个package的classQinterfaceQexception的构成,最好是能够扑ֈ介绍整个包框架的文章。这些专门介l包的书c的前几章应该就是这些M的框架内容介l?

对包整体框架的把握ƈ不是要熟(zhn)每个类的用法,C它有哪些属性,Ҏ(gu)。想CC住的。而是要知道包有哪些方面的cL成的Q这些类的用途是什么,最核心(j)的几个类分别是完成什么功能的。我在给人培训的时候一般是一ơ课讲一个包Q所以不可能详细的介l每个类的用法,但是我反复强调,我给你们讲这些包的不是要告诉你们cȝҎ(gu)是怎么调用的,也不要求你们CcȝҎ(gu)调用Q而是要你们了(jin)解,Javal我们提供了(jin)哪些c,每个cL用在什么场合,当我遇到问题的时候,我知道哪个类Q或者哪几个cȝl合可以解决我的问题QThat'allQ,当我们具体写E序的时候,只要你知道该用哪个类来完成你的工作就_?jin)。编码的时候,具体的方法调用,是边写代码,Ҏ(gu)DocumentationQ所有的东西都在Documentation里面Q不要求你一定记住,实际你也C?000多个cȝd近10万个Ҏ(gu)调用。所以对每个包的M框架的把握就变得极ؓ(f)重要?

W五步,通过上面的学?fn),如果学的比较扎实的话Q就打好?jin)Java的基?jin),剩下要做的工作是扫清Documentation里面除了(jin)上面4个包之外的其他一些比较有用处的类。相信进展到q一步,Java的自学能力已l被培养出来?jin),可以C(jin)直接学习(fn)Documentation的水q了(jin)。除?jin)要?GUI~程之外QJDK里面其他?x)有用处的包是这些?x)
java.text.*;
java.net.*;
javax.naming.*;
q些包里面真正用的比较多的类其实很少Q只有几个,所以不需要花很多旉?

W六步,Java Web ~程
Web~程的核?j)是HTTP协议QHTTP协议和Java无关Q如果不熟?zhn)HTTP协议的话Q虽然也可以学好Servlet/JSP~程Q但是达不到举一反三Q一通百通的境界。所以HTTP协议的学?fn)是必备的。如果熟(zhn)了(jin)HTTP协议的话Q又有了(jin)Java~程的良好的基础Q学?Servlet/JSP直易如反掌,我学?fn)Servlet/JSPq?jin)不C周的旉Q然后就开始用JSP来做目?jin)?

在Servlet/JSP的学?fn)中Q重头仍然是Servlet Documentation。Servlet API最常用的类很少Q花比较?yu)的旉可以掌握?jin)。把q些c都看一遍,多写几个例子试试。Servlet/JSP~程本质是在反复调用这些类来通过HTTP协议在Web Server 和Brower之间交谈。另外对JSPQ还需要熟(zhn)几个常用JSP的标讎ͼ具体的写法记不住的话Q(f)时查是?jin)?

此外Java Web~程学习(fn)的重点要攑֜Web Application的设计模式上Q如何进行业务逻辑的分析,q且q行合理的设计,按照 MVC设计模式的要求,q用Servlet和JSP分别完成不同的逻辑层,掌握如何在Servlet和JSP之间q行程的控制和数据的共享,以及(qing) Web Application应该如何配置和部|Ӏ?

W七步,J2EE~程
以上的学?fn)过E如果是比较利的话Q进行到q一步,隑ֺ又陡然提高。因Z面的知识内容都是只涉?qing)一个方面,而像EJBQJMSQJTA{核?j)的J2EE规范往往是几UJava技术的l合q用的结Ӟ所以掌握v来难度比较大?

首先一定要学习(fn)好JNDIQJNDI是App Server定位服务器资源(EJBlgQDatasouceQJMSQ查找方法,如果对JNDI 不熟(zhn)的话,EJBQJMSq些东西几乎学不下去。JNDI其实是javax.naming.*q个包,q用h很简单。难点在于服务器资源文g的配|。对于服务器资源文g的配|,需要看看专门的文档规范?jin),比如web.xml的写法,ejb-jar.xml的写法等{。针Ҏ(gu)U不同的 App ServerQ还有自q服务资源配置文gQ也是需要熟(zhn)的?

然后可以学习(fn)JTAQ主要是要理解JTA对于事务的控制的Ҏ(gu)Q以?qing)该在什么场合用JTA。这里可以简单的举个例子Q我们知道一般情况可以对于一个数据库q接q行事务控制(conn.setAutoCommit(false),....,conn.commit())Q做Z个原子操作,但是假设我的业务需求是要把对两个不同数据库的操作做Z个原子操作,你能做的到吗Q这时候只能用JTA?jin)。假设操作过E是先往A数据库插一条记录,然后删除B 数据库另一个记录,我们自己写代码是控制不了(jin)把整个操作做Z个原子操作的。用JTA的话Q由App Server来完成控制?

在学?fn)EJB之前要学?fn)对象序列化和RMIQRMI是EJB的基。接着学习(fn)JMS和EJBQ对于EJB来说Q最关键是要理解EJB是如何通过RMI来实现对q端对象的调用的Q以?qing)在什么情况下要用到EJB?

在学?fn)完EJBQJMSq些东西之后Q你可能?x)意识到要急不可待学习(fn)两个领域的知识,一个是UMLQ另一个是Design Pattern?Java企业软g的设计非帔R视框?Framework)的设计,一个好的Y件框架是软g开发成功的必要条g。在q个时候,应该开始把学习(fn)的重Ҏ(gu)在设计模式和框架的学?fn)上Q通过学习(fn)和实际的~程l验来掌握EJB的设计模式和J2EE的核?j)模式?

J2EE规范里面Q除?jin)EJBQJMSQJTAQServlet/JSPQJDBC之外q有很多很多的企业技术,q里不一一q行介绍?jin)?

另外q有一个最新领域Web Services。Web Services也完全没有Q何新东西Q它像是一U黏合剂Q可以把不同的服务统一h提供一个统一的调用接口,作ؓ(f)使用者来_(d)我只要获得服务提供者给我的WSDLQ对服务的描qͼ(j)Q就够了(jin)Q我完全不知道服务器提供者提供的服务I竟是EJB lgQ还?NetlgQ还是什么CORBAlgQ还是其他的什么实玎ͼ我也不需要知道。Web Services最伟大的地方就在于通过l一的服务提供方式和调用方式Q实C(jin)整个Internet服务的共享,是一个非o(h)人激动的技术领域。Web Services好像目前q没有什么很好的书籍Q但是可以通过在网l上面查资料的方式来学习(fn)?/span>

I空 2009-02-10 15:35 发表评论
]]>
Oracle中的数据锁定机制全面解析http://m.tkk7.com/spark/archive/2007/07/10/129288.htmlI空I空Tue, 10 Jul 2007 03:12:00 GMThttp://m.tkk7.com/spark/archive/2007/07/10/129288.htmlhttp://m.tkk7.com/spark/comments/129288.htmlhttp://m.tkk7.com/spark/archive/2007/07/10/129288.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/129288.htmlhttp://m.tkk7.com/spark/services/trackbacks/129288.html

  Z(jin)得到最大的性能Q一般数据库都有q发机制Q不q带来的问题是数据讉K的冲H。ؓ(f)?jin)解册个问题,大多数数据库用的?gu)是数据的锁定?/p>

  数据的锁定分ZU方法,W一U叫做?zhn)观锁Q第二种叫做乐观锁。什么叫(zhn)观锁呢Q?zhn)观锁֐思义Q就是对数据的冲H采取一U?zhn)观的态度Q也是说假设数据肯定会(x)冲突Q所以在数据开始读取的时候就把数据锁定住。而乐观锁是认ؓ(f)数据一般情况下不会(x)造成冲突Q所以在数据q行提交更新的时候,才会(x)正式Ҏ(gu)据的冲突与否q行(g),如果发现冲突?jin),则让用户q回错误的信息,让用户决定如何去做?/p>

  先从(zhn)观锁开始说。在SqlServer{其余很多数据库中,数据的锁定通常采用锁的方式Q也是说对一张表内的数据是一U串行化的更新插入机Ӟ在Q何时间同一张表只会(x)?条数据,别的x入的数据要等到这一条数据插完以后才能依ơ插入。带来的后果是性能的降低,在多用户q发讉K的时候,当对一张表q行频繁操作Ӟ?x)发现响应效率很低,数据库经常处于一U假ȝ态。而Oracle用的是行U锁Q只是对想锁定的数据才进行锁定,其余的数据不相干Q所以在对Oracle表中q发插数据的时候,基本上不?x)有M影响?/p>

  Oracle的?zhn)观锁需要利用一条现有的q接Q分成两U方式,从SQL语句的区别来看,是一U是for updateQ一U是for update nowait的Ş式。比如我们看一个例子。首先徏立测试用的数据库表?/p>

CREATE TABLE TEST
(ID,
NAME,
LOCATION,
VALUE,
CONSTRAINT test_pk PRIMARY KEY(ID))
AS SELECT deptno, dname, loc, 1 FROM scott.dept

  q里我们利用?jin)Oracle的Sample的scott用户的表Q把数据copy到我们的test表中。首先我们看一下for update锁定方式。首先我们执行如下的select for update语句?/p>

select * from test where id = 10 for update

  通过q条(g)索语句锁定以后,再开另外一个sql*plusH口q行操作Q再把上面这条sql语句执行一便,你会(x)发现sqlplus好像d那里?jin),好像(g)索不到数据的样子Q但是也不返回Q何结果,属于卡在那里的感觉。这个时候是什么原因呢Q就是一开始的W一个Session中的select for update语句把数据锁定住?jin)。由于这里锁定的机制是wait的状?只要不表Cnowait那就是wait)Q所以第二个Session(也就是卡住的那个sql*plus)中当前这个检索就处于{待状态。当W一个session最后commit或者rollback之后Q第二个session中的(g)索结果就是自动蟩出来Qƈ且也把数据锁定住。不q如果你W二个session中你的检索语句如下所C?/p>

select * from test where id = 10

  也就是没有for updateq种锁定数据的语句的话,׃?x)造成d?jin)。另外一U情况,是当数据库数据被锁定的时候,也就是执行刚才for update那条sql以后Q我们在另外一个session中执行for update nowait后又是什么样呢。比如如下的sql语句?׃q条语句中是制定采用nowait方式来进行检索,所以当发现数据被别的session锁定中的时候,׃(x)q速返回ORA-00054错误Q内Ҏ(gu)资源正忙, 但指定以 NOWAIT 方式获取资源。所以在E序中我们可以采用nowait方式q速判断当前数据是否被锁定中,如果锁定中的话,p采取相应的业务措施进行处理?/p>

select * from test where id = 10 for update nowait

  那这里另外一个问题,是当我们锁定住数据的时候,我们Ҏ(gu)据进行更新和删除的话?x)是什么样呢。比如同P我们让第一个Session锁定住id=10的那条数据,我们在第二个session中执行如下语?/p>

update test set value=2 where id = 10

  q个时候我们发现update语句好像select for update语句一样也停住卡在q里Q当你第一个session攑ּ锁定以后update才能正常q行。当你updateq行后,数据又被你update语句锁定住了(jin)Q这个时候只要你update后还没有commitQ别的session照样不能Ҏ(gu)据进行锁定更新等{?/p>

I空 2007-07-10 11:12 发表评论
]]>
控制texterea长度Qƈ昄剩余字数Q附QJavascript中的trim和replace函数http://m.tkk7.com/spark/archive/2006/11/22/82751.htmlI空I空Wed, 22 Nov 2006 05:54:00 GMThttp://m.tkk7.com/spark/archive/2006/11/22/82751.htmlhttp://m.tkk7.com/spark/comments/82751.htmlhttp://m.tkk7.com/spark/archive/2006/11/22/82751.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/82751.htmlhttp://m.tkk7.com/spark/services/trackbacks/82751.html 控制texterea长度Qƈ昄剩余字数Q只能在IE上运?/font>

<script>
function checklen(obj){
  var lenE = obj.value.length;
  var lenC = 0;
  var CJK = obj.value.match(/[u4E00-u9FA5uF900-uFA2D]/g);
  if (CJK != null) lenC += CJK.length;
    tno.innerText = obj.maxlength - lenC - lenE ;
    if (tno.innerText < 0) {
      var tmp = 0
      var cut = obj.value.substring(0, obj.maxlength);
      for (var i=0; i<cut.length; i++){
      tmp += /[u4E00-u9FA5uF900-uFA2D]/.test(cut.charAt(i)) ? 2 : 1;
      if (tmp > obj.maxlength) break;
    }
    obj.value = cut.substring(0, i);
  }
}
</script>
<body onload="tno.innerText = s1.maxlength;">
<textarea name="s1" rows="5" cols="50" maxlength="100" onpropertychange="checklen(this)"></textarea>
剩余<span id="tno"></span>个字W?

附:(x)Javascript中的trim和replace函数===============
//triml();
triml = function () {
  for (var i = 0; i < this.length; i++) {
    if (this.charcodeat (i) > 32) {
      return this.substr (i, this.length);
    }
  }
  return this;
}
 
//trimr();
trimr = function () {
  for (var i = this.length; i > 0; i--) {
    if (this.charcodeat (i) > 32) {
    return this.substring (0, i + 1);
    }
  }
  return this;
}
 
//trimwhite();
trimwhite = function() {
  this = this.triml ();
  return this.trimr ();
}
 
//replace();
function replace():string {
  var str:string = string(arguments[0]);
  var re_str:string = string(arguments[1]);
  var new_str:string = string(arguments[2]);
  if (arguments.length<3||re_str=="") {
    return str;
  }
  while (str.indexof(re_str) != -1 && str != "") {
    str_b = str.indexof(re_str);
    str_e = str_b+re_str.length-1;
    if (str_b != 0 && str_e != str.length-1) {
      str = str.substr(0, str_b)+new_str+str.substr(str_e+1, str.length-1);
    } else if (str_b == 0) {
      str = new_str+str.substr(str_e+1, str.length-1);
    } else {
      str = str.substr(0, str_b)+new_str;
    }
  }
  return str;
}


I空 2006-11-22 13:54 发表评论
]]>
Tomcat?http://m.tkk7.com/spark/archive/2006/10/17/75569.htmlI空I空Tue, 17 Oct 2006 03:55:00 GMThttp://m.tkk7.com/spark/archive/2006/10/17/75569.htmlhttp://m.tkk7.com/spark/comments/75569.htmlhttp://m.tkk7.com/spark/archive/2006/10/17/75569.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/75569.htmlhttp://m.tkk7.com/spark/services/trackbacks/75569.html

一?span lang="EN-US">Tomcat背景
  自从JSP发布之后Q推Z(jin)各式各样的JSP引擎。Apache Group在完成GNUJSP1.0的开发以后,开始考虑在SUN的JSWDK基础上开发一个可以直接提供Web服务的JSP服务器,当然同时也支持Servlet, q样Tomcatp生了(jin)?/span>
Tomcat是jakarta目中的一个重要的子项目,其被JavaWorld杂志的编辑选ؓ(f)2001q度最具创新的java产品Q同时它又是sun公司官方推荐的servlet和jsp容器Q因此其来多的受到Y件公司和开发h员的喜爱?span lang="EN-US">servlet和jsp的最新规范都可以在tomcat的新版本中得到实现。其ơ,Tomcat是完全免费的软gQQ何h都可以从互联|上自由C载。Tomcat与Apache的组合相当完?/span>

二?/span>Tomcat目录

tomcat
|---bin TomcatQ?/span>存放启动和关?span lang="EN-US">tomcat脚本
Q?/span>

|---conf TomcatQ存?/span>不同的配|文Ӟserver.xml和web.xmlQ;
|---docQ存放Tomcat文档Q?br />|---lib
/japser/commonQ存?/font>Tomcatq行需要的库文ӞJARSQ;
|---logsQ存放Tomcat执行时的LOG文gQ?br />|---srcQ存放Tomcat的源代码Q?br />|---webappsQTomcat的主要Web发布目录Q包?/font>
应用E序CZQ;
|---workQ?/font>
存放jsp~译后生的class文gQ?/font>

三?span lang="EN-US">Tomcatcd?/span>

Bootstrap($JAVA_HOME/jre/lib/ext/*.jar)
System($CLASSPATH/*.class
和指定的
jar)
Common($CATALINA_HOME/common
下的classes,lib,endores三个子目?/span>
)
Catalina ($CATALINA_HOME/server/
下的classes?/span>lib目录仅对Tomcat可见
)
&Shared($CATALINA_HOME/shared/
下的classes?/span>lib目录以及(qing)$CATALINA_HOME/lib目录)仅对Web应用E序可见,?/span>Tomcat不可?/span>WebApp($WEBAPP/Web-INF/*仅对?/span>WEB应用可见
classes/*.class lib/*.jar)

加蝲cd资源的顺序ؓ(f)Q?/font>
1
?/span>/Web-INF/classes

2?/span>/Web-INF/lib/*.jar

3?/span>Bootstrap

4?/span>System

5?/span>$CATALINA_HOME/common/classes
6
?/span>$CATALINA_HOME/common/endores/*.jar

7?/span>$CATALINA_HOME/common/lib/*.jar

8?/span>$CATALINA_HOME/shared/classes
9
?/span>$CATALINA_HOME/shared/lib/*.jar

四?/span>server.xml配置?/span>Q?/span>

下面讲述q个文g中的基本配置信息Q更具体的配|信息请参?/span>tomcat的文档:(x)
server:
1
?/span>port 指定一个端口,q个端口负责监听关闭tomcat的请?/span>
2
?/span>shutdown 指定向端口发送的命o(h)字符?/span>
service:
1
?/span>name 指定service的名?/span>

Connector (
表示客户端和service之间的连?/span>)Q?/span>

1
?/span>port 指定服务器端要创建的端口Pq在q个断口监听来自客户端的h
2
?/span>minProcessors 服务器启动时创徏的处理请求的U程?/span>

3
?/span>maxProcessors 最大可以创建的处理h的线E数

4
?/span>enableLookups 如果?/span>trueQ则可以通过调用request.getRemoteHost()q行DNS?/span>

询来得到q程客户端的实际L名,若ؓ(f)false则不q行DNS查询Q而是q回?/span>ip

地址
5
?/span>redirectPort 指定服务器正在处?/span>httph时收C(jin)一?/span>SSL传输h后重定向?/span>

端口?/font>
6
?/span>acceptCount 指定当所有可以用的处理h的线E数都被使用Ӟ可以攑ֈ处理

队列中的h敎ͼ过q个数的h不予处?/font>
7
?/span>connectionTimeout 指定时的时间数(以毫Uؓ(f)单位
)
Engine (
表示指定service中的h处理机,接收和处理来?/span>Connector的请?/span>)Q?/span>

1
?/span>defaultHost 指定~省的处理请求的L名,它至与其中的一?/span>host元素?/span>name

属性值是一L(fng)
Context (
表示一?/span>web应用E序)Q?/span>

1
?/span>docBase 应用E序的\径或者是WAR文g存放的\?/span>
2
?/span>path 表示?/span>web应用E序?/span>url的前~Q这栯求的url?/span>

http://localhost:8080/path/****
3
?/span>reloadable q个属性非帔R要,如果?/span>trueQ则tomcat?x)自动检应用程序的

/WEB-INF/lib ?/span>/WEB-INF/classes目录的变化,自动装蝲新的应用E序Q我们可

以在不重?/span>tomcat的情况下改变应用E序
host (
表示一个虚拟主?/span>)Q?/span>

1
?/span>name 指定L?/span>
2
?/span>appBase 应用E序基本目录Q即存放应用E序的目?/span>

3
?/span>unpackWARs 如果?/span>trueQ则tomcat?x)自动?/span>WAR文g解压Q否则不解压Q直?/span>

?/span>WAR文g中运行应用程?/span>
Logger (
表示日志Q调试和错误信息)Q?/span>

1
?/span>className 指定logger使用的类名,此类必须实现org.apache.catalina.Logger 接口
2
?/span>prefix 指定log文g的前~

3
?/span>suffix 指定log文g的后~

4
?/span>timestamp 如果?/span>trueQ则log文g名中要加入时_(d)如下

?/font>:localhost_log.2001-10-04.txt
Realm (
表示存放用户名,密码?/span>role的数据库)Q?/span>

1
?/span>className 指定Realm使用的类名,此类必须实现org.apache.catalina.Realm接口
Valve (
功能?/span>Logger差不多,?/span>prefix?/span>suffix属性解释和Logger 中的一?/span>)Q?/span>

1
?/span>className 指定Valve使用的类名,如用org.apache.catalina.valves.AccessLogValve

cd以记录应用程序的讉K信息
directory
Q指?/span>log文g存放的位|)(j)Q?/span>

1
?/span>pattern 有两个|common方式记录q程L名或ip地址Q用户名Q日期,W一?/span>

h的字W串Q?/span>HTTP响应代码Q发送的字节数?/span>combined方式?/span>common方式?/span>

录的值更?/font>

五?/span>web.xml配置?/span>Q?/span>

?/span>1、默?/span>(Ƣ迎)文g的设|?/span>

?/span>?/span>tomcat4confweb.xml中,<welcome-file-list>?/span>IIS中的默认文g意思相同?/span>

?/span>?/span><welcome-file-list>

?/span> <welcome-file>index.html</welcome-file>

?/span> <welcome-file>index.htm</welcome-file>

?/span> <welcome-file>index.jsp</welcome-file>

 </welcome-file-list>

?/span>2、报错文件的讄

<error-page>

?/span><error-code>404</error-code>

?/span><location>/notFileFound.jsp</location>

</error-page>

<error-page>

?/span><exception-type>java.lang.NullPointerException</exception-type>

?/span><location>/null.jsp</location>

</error-page>

如果某文件资源没有找刎ͼ服务器要?/span>404错误Q按上述配置则会(x)调用webappsROOTnotFileFound.jsp?/span>

如果执行的某?/span>JSP文g产生NullPointException Q则?x)调?/span>webappsROOTnull.jsp

?/span>3、会(x)话超时的讄

讄session 的过期时_(d)单位是分钟;

<session-config>

?/span><session-timeout>30</session-timeout>

</session-config>

?/span>4、过滤器的设|?/span>

<filter>

?/span><filter-name>FilterSource</filter-name>

?/span><filter-class>project4. FilterSource </filter-class>

</filter>

<filter-mapping>

?/span><filter-name>FilterSource</filter-name>

?/span><url-pattern>/WwwServlet</url-pattern>

?/span>(<url-pattern>/haha/*</url-pattern>)

</filter-mapping>

qo(h)Q?/span>

1) w䆾验证的过?/span>Authentication Filters

2) 日志和审核的qo(h)Logging and Auditing Filters

3) 囄转化的过?/span>Image conversion Filters

4) 数据压羃的过?/span>Data compression Filters

5) 加密qo(h)Encryption Filters

6) Tokenizing Filters

7) 资源讉K事g触发的过?/span>Filters that trigger resource access events XSL/T qo(h)XSL/T filters

9) 内容cd的过?/span>Mime-type chain Filter 注意监听器的序Q如Q先安全qo(h)Q然后资源,

然后内容cd{,q个序可以自己定?/font>

六、管?/span>
1
、用户配|?/span>
在进行具?/span>Tomcat理之前Q先l?/span>tomcatd一个用P使这个用h权限来进行管理?/span>
打开conf目录下的tomcat-users.xml文gQ在相应的位|添加下面一行:(x)

<user name="user" password="user" roles="standard,manager"/>
然后重vtomcatQ在览器中输入http://localhost:8080/manager/Q会(x)弹出对话框,输入上面的用?/span>

名和密码卛_?/font>

2
、应用程序列?/span>
在浏览器中输?/span>http://localhost:8080/manager/listQ浏览器会(x)昄如下的信息:(x)
OK - Listed applications for virtual host localhost
/ex:running:1
/examples:running:1
/webdav:running:0
/tomcat-docs:running:0
/manager:running:0
/:running:0
上面昄的信息分别ؓ(f)Q应用程序的路径、当前状态、连接这个程序的session?/span>


3
、重新装载应用程?/span>
在浏览器中输?/span> http://localhost:8080/manager/reload?path=/examplesQ浏览器昄如下Q?/span>
OK - Reloaded application at context path /examples

q表C?/span>example应用E序装蝲成功Q如果我们将server.xml?/span>Context元素?/span>reloadable属性设?/span>trueQ则没必要利用这U方式重新装载应用程序,因ؓ(f)tomcat?x)自动装载?/span>

4、显C?/span>session信息
在浏览器中输?/span>http://localhost:8080/manager/sessions?path=/examplesQ浏览器昄如下Q?/span>
OK - Session information for application at context path /examples Default maximum session inactive

interval 30 minutes

5
、启动和关闭应用E序
在浏览器中输?/span>http://localhost:8080/manager/start?path=/examples?/span>

http://localhost:8080/manager/stop?path=/examples分别启动和关?/span>examples应用E序?/span>



I空 2006-10-17 11:55 发表评论
]]>
Java 关于中文q问题的解x案与l验http://m.tkk7.com/spark/archive/2006/10/12/74777.htmlI空I空Thu, 12 Oct 2006 05:53:00 GMThttp://m.tkk7.com/spark/archive/2006/10/12/74777.htmlhttp://m.tkk7.com/spark/comments/74777.htmlhttp://m.tkk7.com/spark/archive/2006/10/12/74777.html#Feedback1http://m.tkk7.com/spark/comments/commentRss/74777.htmlhttp://m.tkk7.com/spark/services/trackbacks/74777.html
一、字节和unicode

Java内核是unicode的,pclass文g也是Q但是很多媒体,包括文g/的保存方式是用字节流的。因此Java要对q些字节经行{化。char是unicode的,而byte是字节。Java中byte/char互{的函数在sun.io的包中间有。其中ByteToCharConvertercL中调度,可以用来告诉你,你用的convertor。其中两个很常用的静(rn)态函数是Q?

public static ByteToCharConverter getDefault();
public static ByteToCharConverter getConverter(String encoding);

如果你不指定converterQ则pȝ?x)自动用当前的encoding,gbq_上用gbk,enq_上用8859_1?

byte ??〉charQ?
"?的gb码是Q?xc4e3 ,unicode?x4f60
String encoding = "gb2312";
byte b[] = {(byte)´\u00c4´,(byte)´\u00e3´};
ByteToCharConverter converter = ByteToCharConverter.getConverter(encoding);
char c[] = converter.convertAll(b);
for (int i = 0; i < c.length; i++) {
System.out.println(Integer.toHexString(c[i]));
}
l果是什么?0x4f60
如果encoding ="8859_1"Q结果又是什么?0x00c4,0x00e3

如果代码改ؓ(f)Q?

byte b[] = {(byte)´\u00c4´,(byte)´\u00e3´};
ByteToCharConverter converter = ByteToCharConverter. getDefault();
char c[] = converter.convertAll(b);
for (int i = 0; i < c.length; i++) {
System.out.println(Integer.toHexString(c[i]));
}

l果又是什么?

q就要根据^台的~码而定?

char ??〉byteQ?
String encoding = "gb2312";
char c[] = {´\u4f60´};
CharToByteConverter converter = CharToByteConverter.getConverter(encoding);
byte b[] = converter.convertAll(c);
for (int i = 0; i < b.length; i++) {
System.out.println(Integer.toHexString(b[i]));
}
l果是什么?0x00c4,0x00e3
如果encoding ="8859_1"Q结果又是什么?0x3f
如果代码改ؓ(f)
String encoding = "gb2312";
char c[] = {´\u4f60´};
CharToByteConverter converter = CharToByteConverter.getDefault();
byte b[] = converter.convertAll(c);
for (int i = 0; i < b.length; i++) {
System.out.println(Integer.toHexString(b[i]));
}

l果又是什么?q是Ҏ(gu)q_的编码而定?

很多中文问题是从这两个最单的cL生出来的。而却有很多类不直接支持把encoding输入Q这l我们带来诸多不ѝ很多程序难得用encoding?jin),直接用default的encodingQ这q我们UL带来?jin)很多困难?

二、utf-8

utf-8是和unicode一一对应的,其实现很单:(x)

7位的unicode: 0 _ _ _ _ _ _ _
11位的unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _
16位的unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _
21位的unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _

大多数情冉|只用到16位以下的unicode:

"?的gb码是Q?xc4e3 ,unicode?x4f60
0xc4e3的二q制Q?
1100 Q?100 Q?110 Q?011

׃只有两位我们按照两位的编码来排,但是我们发现q行不通,因ؓ(f)W7位不?因此Q返??"

0x4f60的二q制Q?
0100 Q?111 Q?110 Q?000
我们用utf-8补齐Q变成:(x)
1110 Q?100 Q?011 Q?101 Q?010 Q?000
e4--bd-- a0
于是q回Q?xe4,0xbd,0xa0?

三、string和byte[]

string其实核心(j)是char[],然而要把byte转化成stringQ必ȝq编码。string.length()其实是char数组的长度,如果使用不同的编码,很可能会(x)错分Q造成散字和ؕ码。例如:(x)


String encoding = “?
byte [] b={(byte)´\u00c4´,(byte)´\u00e3´};
String str=new String(b,encoding);

如果encoding=8859_1Q会(x)有两个字Q但是encoding=gb2312只有一个字q个问题在处理分|l常发生?

四、Reader,Writer / InputStream,OutputStream

Reader和W(xu)riter核心(j)是charQInputStream和OutputStream核心(j)是byte。但是Reader和W(xu)riter的主要目的是要把char?写InputStream/OutputStream。例如:(x)


文gtest.txt只有一??字,0xc4,0xe3
String encoding = "gb2312";
InputStreamReader reader = new InputStreamReader(new FileInputStream(
"text.txt"), encoding);
char c[] = new char[10];
int length = reader.read(c);
for (int i = 0; i < length; i++) {
System.out.println(c[i]);
}

l果是什么???。如果encoding ="8859_1"Q结果是什么?"??"两个字符Q表CZ认识。反q来的例子自己做?

五、我们要对Java的编译器有所?jin)解Q?

Javac ?encoding

我们常常没有用到encodingq个参数。其实encodingq个参数对于跨^台的操作是很重要的。如果没有指定encodingQ则按照pȝ的默认encoding,gbq_上是gb2312Q英文^C是iso8859_1。Java的编译器实际上是调用sun.tools.Javac.main的类Q对文gq行~译Q这个类有compile函数中间有一个encoding的变?-encoding的参数其实直接传lencoding变量。编译器是Ҏ(gu)q个变量来读取Java文g的,然后把用utf-8形式~译成class文g。例子代码:(x)


String str = "?;
FileWriter writer = new FileWriter("text.txt");
write.write(str);
writer.close();

如果用gb2312~译Q你?x)找到e4 bd a0的字D?Q?
如果?859_1~译Q?00c4 00e3的二q制Q?
0000Q?000 Q?100Q?100 Q?000Q?000 Q?110Q?011
因ؓ(f)每个字符都大?位,因此?1位编码:(x)
1100Q?001Q?000Q?100Q?100Q?011Q?010Q?011
c1-- 84-- c3--  a3
你会(x)扑ֈc1 84 c3 a3

但是我们往往忽略掉这个参敎ͼ因此q样往往?x)有跨^台的问题Q?

样例代码在中文^C~译Q生成zhclass

样例代码在英文^C~译Q输出enclass

(1) zhclass在中文^C执行ok,但是在英文^C不行

(2) enclass在英文^C执行ok,但是在中文^C不行

原因是:(x)

(1) 在中文^C~译后,其实str在运行态的char[]?x4f60, 在中文^Cq行Qfilewriter的缺省编码是gb2312,因此chartobyteconverter?x)自动用调用gb2312的converter,把str转化成byte输入到fileoutputstream中,于是0xc4,0xe3放进?jin)文件。但是如果是在英文^CQchartobyteconverter的缺省值是8859_1, filewriter?x)自动调?859_1去{化str,但是他无法解释,因此他会(x)输出"?"

(2) 在英文^C~译后,其实str在运行态的char[]?x00c4 0x00e3, 在中文^Cq行Q中文无法识别,因此?x)出??Q在英文q_上,0x00c4-->0xc4,0x00e3->0xe3Q因?xc4,0xe3被放q了(jin)文g?

六、其它原因:(x)


<%@ page contentType="text/html; charset=GBK" %>

讄览器的昄~码Q如果response的数据是utf8~码Q显C将是ؕ码,但是q和上q原因还不一栗?

七、发生编码的地方Q?

1. 从数据库到JavaE序 byte??〉char

2. 从JavaE序到数据库 char??〉byte

3. 从文件到JavaE序 byte??〉char

4. 从JavaE序到文?char??〉byte

5. 从JavaE序到页面显C?char??〉byte

6. 从页面form提交数据到JavaE序byte??〉char

7. 从流到JavaE序byte??〉char

8. 从JavaE序到流char??〉byte

可以使用配置qo(h)器的Ҏ(gu)解决中文q的:(x)


<web-app>
<filter>
<filter-name>RequestFilter</filter-name>
<filter-class>net.golden.uirs.util.RequestFilter</filter-class>
<init-param>
<param-name>charset</param-name>
<param-value>gb2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>RequestFilter</filter-name>
<url-pattern>*.Jsp</url-pattern>
</filter-mapping>
</web-app>


public void doFilter(ServletRequest req, ServletResponse res,
FilterChain fChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession();
String userId = (String) session.getAttribute("userid");
req.setCharacterEncoding(this.filterConfig.getInitParameter("charset"));
// 讄字符集?
实际上是讄?jin)byte ??〉char的encoding
try {
if (userId == null || userId.equals("")) {
if (!request.getRequestURL().toString().matches(
".*/uirs/logon/logon(Controller){0,1}\\x2EJsp$")) {
session.invalidate();
response.sendRedirect(request.getContextPath() +
"/uirs/logon/logon.Jsp");
}
}
else {
// 看看是否h信息上报pȝ的权?
if (!net.golden.uirs.util.UirsChecker.check(userId, "信息上报pȝ",
net.golden.uirs.util.UirsChecker.ACTION_DO)) {
if (!request.getRequestURL().toString().matches(
".*/uirs/logon/logon(Controller){0,1}\\x2EJsp$")) {
response.sendRedirect(request.getContextPath() +
"/uirs/logon/logonController.Jsp");
}
}
}
}
catch (Exception ex) {
response.sendRedirect(request.getContextPath() +
"/uirs/logon/logon.Jsp");
}
fChain.doFilter(req, res);
}

I空 2006-10-12 13:53 发表评论
]]>
中文字符集与字符~码的基知识http://m.tkk7.com/spark/archive/2006/09/29/72748.htmlI空I空Fri, 29 Sep 2006 03:10:00 GMThttp://m.tkk7.com/spark/archive/2006/09/29/72748.htmlhttp://m.tkk7.com/spark/comments/72748.htmlhttp://m.tkk7.com/spark/archive/2006/09/29/72748.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/72748.htmlhttp://m.tkk7.com/spark/services/trackbacks/72748.html 字符是各U文字和W号的ȝQ包括各国家文字、标点符受图形符受数字等。字W集是多个字W的集合Q字W集U类较多Q每个字W集包含的字W个C同,常见字符集名Uͼ(x)ASCII字符集、GB2312字符集、BIG5字符集?GB 18030字符集、Unicode字符集等。计机要准的处理各种字符集文字,需要进行字W编码,以便计算够识别和存储各种文字?br />
中文文字数目大,而且q分为简体中文和J体中文两种不同书写规则的文字,而计机最初是按英语单字节字符设计的,因此Q对中文字符q行~码Q是中文信息交流的技术基。本文将按照字符集的旉序讨论几种典型的字W集Q选取几种代表性的中文字符集,研究历史由来、特炏V技术特征?br />
ASCII 字符?br />
1Q名U的由来

ASCIIQAmerican Standard Code for Information InterchangeQ美国信息互换标准代码)(j)是基于罗马字母表的一套电(sh)脑编码系l?br />
2Q特?br />
它主要用于显C现代英语和其他西欧语言。它是现今最通用的单字节~码pȝQƈ{同于国际标准ISO 646?br />
3Q包含内?br />
控制字符Q回车键、退根{换行键{?br />
可显C字W:(x)英文大小写字W、阿拉伯数字和西文符?br />
4Q技术特?br />
7位(bitsQ表CZ个字W,?28字符

5QASCII扩展字符?br />
7位编码的字符集只能支?28个字W,Z(jin)表示更多的欧z常用字W对ASCIIq行?jin)扩展,ASCII扩展字符集?位(bitsQ表CZ个字W,?56字符?br />
ASCII扩展字符集比ASCII字符集扩充出来的W号包括表格W号、计符受希腊字母和Ҏ(gu)的拉丁符受?

GB2312 字符?br />
1Q名U的由来

GB2312又称为GB2312-80字符集,全称为《信息交换用汉字~码字符集·基本集》,由原中国国家标准d发布Q?981q??日实施?br />
2Q特?br />
GB2312是中国国家标准的体中文字W集。它所收录的汉字已l覆?9.75%的用频率,基本满?jin)汉字的计算机处理需要。在中国大陆和新加坡获广泛用?br />
3Q包含内?br />
GB2312收录化汉字及(qing)一般符受序受数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符受汉语注韛_母,?7445 个图形字W。其中包?763个汉字,其中一U汉?755个,二汉字3008个;包括拉丁字母、希腊字母、日文^假名?qing)片假名字母、俄语西里尔字母在内?82个全角字W?

4Q技术特?br />
Q?Q分C:(x)

GB2312中对所收汉字进行了(jin)“分区”处理,每区含有94个汉?W号。这U表C方式也UCؓ(f)Z码?br />
各区包含的字W如下:(x)01-09Zؓ(f)Ҏ(gu)W号Q?6-55Zؓ(f)一U汉字,按拼x序;56-87Zؓ(f)二汉字Q按部首/W画排序Q?0-15区及(qing)88-94区则未有~码?br />
Q?Q双字节表示

两个字节中前面的字节为第一字节Q后面的字节为第二字节。习(fn)惯上U第一字节为“高字节?Q而称W二字节为“低字节”?br />
“高位字节”用了(jin)0xA1-0xF7(?1-87区的区号加上0xA0)Q“低位字节”用了(jin)0xA1-0xFE(?1-94加上0xA0)?br />
5Q编码D?br />
以GB2312字符集的W一个汉字“啊”字ZQ它的区?6Q位?1Q则Z码是1601Q在大多数计机E序中,高字节和低字节分别加0xA0得到E序的汉字处理编?xB0A1。计公式是Q?xB0=0xA0+16, 0xA1=0xA0+1?br />
BIG5 字符?br />
1Q名U的由来

又称大五码或五大码,1984q由台湾财团法h信息工业{进?x)和五间软g公司宏碁 (Acer)、神?(MiTAC)、佳佟뀁零?(Zero One)、大?(FIC)创立Q故U大五码?br />
Big5码的产生Q是因ؓ(f)当时台湾不同厂商各自推出不同的编码,如倚天码、IBM PS55、王安码{,彼此不能兼容Q另一斚wQ台湾政府当时尚未推出官方的汉字~码Q而中国大陆的GB2312~码亦未有收录繁体中文字?br />
2Q特?br />
Big5字符集共收录13,053个中文字Q该字符集在中国台湾使用。耐hd的是该字W集重复地收录了(jin)两个相同的字Q“兀?0xA461?xC94A)、“嗀?0xDCD1?xDDFC)?br />
3Q字W编码方?br />
Big5码用了(jin)双字节储存方法,以两个字节来~码一个字。第一个字节称为“高位字节”,W二个字节称为“低位字节”。高位字节的~码范围0xA1-0xF9Q低位字节的~码范围0x40-0x7E?xA1-0xFE?br />
各编码范围对应的字符cd如下Q?xA140-0xA3BF为标点符受希腊字母及(qing)Ҏ(gu)W号Q另外于0xA259-0xA261Q存放了(jin)双音节度量衡单位用字Q兙兛兞兝兡兣嗧瓩糎Q?xA440-0xC67E为常用汉字,先按W划再按部首排序Q?xC940-0xF9D5为次常用汉字Q亦是先按笔划再按部首排序?br />
4QBig5 的局限?br />
管Big5码内包含一万多个字W,但是没有考虑C会(x)上流通的人名、地名用字、方a用字、化学及(qing)生物U等用字Q没有包含日文^假名?qing)片假名字母?br />
例如台湾视“着”ؓ(f)“著”的异体字,故没有收录“着”字。康熙字怸的一些部首用?如“亠”、“疒”、“R”、“癶”等)、常见的人名用字(如“堃”、“煊”、“栢”、“喆”等) 也没有收录到Big5之中?br />
GB18030 字符?br />
1Q名U的由来

GB 18030的全U是GB18030-2000《信息交换用汉字~码字符集基本集的扩充》,是我国政府于2000q??7日发布的新的汉字~码国家标准Q?001q??1日后在中国市(jng)Z发布的Y件必ȝ合本标准

2Q特?br />
GB 18030字符集标准的出台l过q泛参与和论证,来自国内外知名信息技术行业的公司Q信息业部和原国家质量技术监督局联合实施?br />
GB 18030字符集标准解x字、日文假名、朝鲜语和中国少数民族文字组成的大字W集计算机编码问题。该标准的字Wȝ码空间超q?50万个~码位,收录?7484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满中国大陆、香港、台湾、日本和韩国{东亚地Z息交换多文种、大字量、多用途、统一~码格式的要求。ƈ且与Unicode 3.0版本兼容Q填补Unicode扩展字符字汇“统一汉字扩展A”的内容。ƈ且与以前的国家字W编码标准(GB2312QGB13000.1Q兼宏V?br />
3Q编码方?br />
GB 18030标准采用单字节、双字节和四字节三种方式对字W编码。单字节部分使用0×00?×7F?对应于ASCII码的相应?。双字节部分Q首字节码从0×81?×FEQ尾字节码位分别?×40?×7E?×80?×FE。四字节部分采用GB/T 11383未采用的0×30?×39作ؓ(f)对双字节~码扩充的后~Q这h充的四字节编码,其范围ؓ(f)0×81308130?×FE39FE39。其中第一、三个字节编码码位均?×81?×FEQ第二、四个字节编码码位均?×30?×39?br />
4Q包含的内容

双字节部分收录内容主要包括GB13000.1全部CJK汉字20902个、有x点符受表意文字描q符13个、增补的汉字和部?构g80个、双字节~码的欧元符L(fng)。  四字节部分收录了(jin)上述双字节字W之外的Q包括CJKl一汉字扩充A在内的GB 13000.1中的全部字符?br />
Unicode字符?br />
1Q名U的由来

Unicode字符集编码是Universal Multiple-Octet Coded Character Set 通用多八位编码字W集的简Uͼ是由一个名?Unicode 学术学会(x)(Unicode Consortium)的机构制订的字符~码pȝQ支持现今世界各U不同语a的书面文本的交换、处理及(qing)昄。该~码?990q开始研发,1994q正式公布,最新版本是2005q??1日的Unicode 4.1.0?br />
2Q特?

Unicode是一U在计算Z使用的字W编码。它为每U语a中的每个字符讑֮?jin)统一q且唯一的二q制~码Q以满跨语a、跨q_q行文本转换、处理的要求?br />
3Q编码方?br />
Unicode 标准始终使用十六q制数字Q而且在书写时在前面加上前~“U+”,例如字母“A”的~码?004116 和字W“€”的~码?20AC16。所以“A”的~码书写为“U+0041”?br />
4QUTF-8 ~码
UTF-8是Unicode的其中一个用方式?UTF?Unicode Translation FormatQ即把Unicode转做某种格式的意思?br />
UTF-8便于不同的计机之间使用|络传输不同语言和编码的文字Q得双字节的Unicode能够在现存的处理单字节的pȝ上正传输?br />
UTF-8使用可变长度字节来储?Unicode字符Q例如ASCII字母l箋使用1字节储存Q重x字、希腊字母或襉K?dng)字母等使?字节来储存,而常用的汉字p使用3字节。辅助^面字W则使用4字节?br />
5QUTF-16 ?UTF-32 ~码
UTF-32、UTF-16 ?UTF-8 ?Unicode 标准的编码字W集的字W编码方案,UTF-16 使用一个或两个未分配的 16 位代码单元的序列?Unicode 代码点进行编码;UTF-32 卛_每一?Unicode 代码点表CZؓ(f)相同值的 32 位整数?/span>



I空 2006-09-29 11:10 发表评论
]]>
java中的iopȝȝ.http://m.tkk7.com/spark/archive/2006/09/29/72733.htmlI空I空Fri, 29 Sep 2006 02:17:00 GMThttp://m.tkk7.com/spark/archive/2006/09/29/72733.htmlhttp://m.tkk7.com/spark/comments/72733.htmlhttp://m.tkk7.com/spark/archive/2006/09/29/72733.html#Feedback2http://m.tkk7.com/spark/comments/commentRss/72733.htmlhttp://m.tkk7.com/spark/services/trackbacks/72733.htmljava中的io中的Qinput/outputQstream无非是包括Z字符的stream、基于字节的stream和把字节导向的stream转换
字符为导向的stream的stream。(很难理解么?Q?br />以字节ؓ(f)导向的stream------InputStream/OutputStream
InputStream ?OutputStream是两个abstactc,对于字节为导向的stream都扩展这两个鸡肋Q基c^_^Q?
--InputStream
ByteArrayInputStream -- 把内存中的一个缓冲区作ؓ(f)InputStream使用.

construct---ByteArrayInputStream(byte[])创徏一个新字节数组输入,它从指定字节数组中读取数据?br />---ByteArrayInputStream(byte[], int, int) 创徏一个新字节数组输入,它从指定字节数组中读取数据?br />---mark::该字节数l未被复制?br />
StringBufferInputStream -- 把一个String对象作ؓ(f)InputStream .
注释Q不推荐使用 StringBufferInputStream Ҏ(gu)?此类不能字W正的转换为字节?br />?JDK 1.1 版中的类|从一个串创徏一个流的最x法是采用 StringReader cR?

construct---StringBufferInputStream(String) 据指定串创徏一个读取数据的输入串?br />
FileInputStream -- 把一个文件作为InputStreamQ实现对文g的读取操?

construct---FileInputStream(File) 创徏一个输入文件流Q从指定?File 对象d数据?br />---FileInputStream(FileDescriptor) 创徏一个输入文件流Q从指定的文件描q器d数据?br />---FileInputStream(String) 创徏一个输入文件流Q从指定名称的文件读取数据?br />
method ---- read() 从当前输入流中读取一字节数据?
read(byte[]) 当前输入流?b.length 个字节数据读C个字节数l中?
read(byte[], int, int) 输入流?len 个字节数据读入一个字节数l中?br />
PipedInputStreamQ实C(jin)pipe的概念,主要在线E中使用. 道输入是指一个通讯道的接收端?br />一个线E通过道输出发送数据,而另一个线E通过道输入读取数据,
q样可实C个线E间的通讯?br />
PipedInputStream() 创徏一个管道输入流Q它q未与一个管道输出流q接?
PipedInputStream(PipedOutputStream) 创徏一个管道输入流, 它已q接C个管道输出流?

SequenceInputStreamQ把多个InputStream合ƈZ个InputStream .“序列输入流”类允许应用E序把几个输入流q箋地合qv来,
q且使它们像单个输入一样出现。每个输入流依次被读取,直到到达该流的末?br />然后“序列输入流”类关闭q个ƈ自动地切换到下一个输入流?
SequenceInputStream(Enumeration) 创徏一个新的序列输入流Qƈ用指定的输入的枚D值初始化它?
SequenceInputStream(InputStream, InputStream) 创徏一个新的序列输入流Q初始化为首?读输入流 s1, 然后读输入流 s2?br />
--OutputSteam

ByteArrayOutputStreamQ把信息存入内存中的一个缓冲区?该类实现一个以字节数组形式写入数据的输出流?br />当数据写入缓冲区Ӟ它自动扩大。用 toByteArray() ?toString() 能检索数据?

construct --- ByteArrayOutputStream() 创徏一个新的字节数l输出流?br />--- ByteArrayOutputStream() 创徏一个新的字节数l输出流?
--- ByteArrayOutputStream(int) 创徏一个新的字节数l输出流Qƈ带有指定大小字节的缓冲区定w?
toString(String) Ҏ(gu)指定字符~码缓冲区内容转换为字W串Qƈ字节{换ؓ(f)字符?
write(byte[], int, int) 指定字节数l中从偏U量 off 开始的 len 个字节写入该字节数组输出?
write(int) 指定字节写入该字节数组输出?
writeTo(OutputStream) ?out.write(buf, 0, count) 调用输出的写方法将该字节数l输出流的全部内容写入指定的输出参数?

FileOutputStream:文g输出是?File ?FileDescriptor 输出数据的一个输出流?br />
FileOutputStream(File) 创徏一个文件输出流Q向指定?File 对象输出数据?
FileOutputStream(FileDescriptor) 创徏一个文件输出流Q向指定的文件描q器输出数据?
FileOutputStream(String) 创徏一个文件输出流Q向指定名称的文件输出数据?
FileOutputStream(String, boolean) 用指定系l的文g名,创徏一个输出文件?br />
PipedOutputStream:道输出是指一个通讯道的发送端?一个线E通过道输出发送数据,
而另一个线E通过道输入读取数据,q样可实C个线E间的通讯?br />
PipedOutputStream() 创徏一个管道输出流Q它q未与一个管道输入流q接?
PipedOutputStream(PipedInputStream) 创徏一个管道输出流Q它已连接到一个管道输入流?br />

以字Wؓ(f)导向的stream Reader/Writer

以Unicode字符为导向的streamQ表CZUnicode字符为单位从stream中读取或往stream 中写入信息?br />Reader/Writer 为abstactc?br />以Unicode字符为导向的stream包括下面几种cdQ?

Q- Reader

1) CharArrayReaderQ与ByteArrayInputStream对应
CharArrayReader(char[]) 用指定字W数l创Z?CharArrayReader?br />CharArrayReader(char[], int, int) 用指定字W数l创Z?CharArrayReader?br />
2) StringReaderQ与StringBufferInputStream对应
StringReader(String) 创徏一新的串读取者?br />3) FileReaderQ与FileInputStream对应

4) PipedReaderQ与PipedInputStream对应

Q- Writer

1) CharArrayWriteQ与ByteArrayOutputStream对应
2) StringWriteQ无与之对应的以字节为导向的stream
3) FileWriteQ与FileOutputStream对应
4) PipedWriteQ与PipedOutputStream对应

两种不现导向的stream之间的{?br />InputStreamReader和OutputStreamReaderQ把一个以字节为导向的stream转换成一个以字符为导向的stream?br />一?InputStreamReader cL从字节流到字W流的桥梁:(x)它读入字节,q根据指定的~码方式Q将之{换ؓ(f)字符?br />使用的编码方式可能由名称指定Q或q_可接受的~省~码方式?br />
InputStreamReader ?read() Ҏ(gu)之一的每ơ调用,可能?j)从基本字节输入流中读取一个或多个字节?br />Z(jin)辑ֈ更高效率Q考虑?BufferedReader 装 InputStreamReaderQ?br />BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

InputStreamReader(InputStream) 用缺省的字符~码方式Q创Z?InputStreamReader?
InputStreamReader(InputStream, String) 用已命名的字W编码方式,创徏一?InputStreamReader?br />
OutputStreamWriter 多个字W写入到一个输出流Q根据指定的字符~码多个字W{换ؓ(f)字节?
每个 OutputStreamWriter 合ƈ它自q CharToByteConverter, 因而是从字W流到字节流的桥梁?br />
FilterInputStream、RandomAccessFile 见例子?br />ObjectInputStream ?ObjectOutputStream见另外blog?/p>


Java IO的一般用原则:(x)

一、按数据来源Q去向)(j)分类Q?br />1、是文gQ?FileInputStream, FileOutputStream, FileReader, FileWriter
2、是byte[]QByteArrayInputStream, ByteArrayOutputStream
3、是Char[]: CharArrayReader, CharArrayWriter
4、是String: StringBufferInputStream, StringReader, StringWriter
5、网l数据流QInputStream, OutputStream, Reader, Writer

二、按是否格式化输出分Q?br />1、要格式化输出:(x)PrintStream, PrintWriter

三、按是否要缓冲分Q?br />1、要~冲QBufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter

四、按数据格式分:(x)
1、二q制格式Q只要不能确定是U文本的Q? InputStream, OutputStream?qing)其所有带Streaml束的子c?br />2、纯文本格式Q含U英文与汉字或其他编码方式)(j)QReader, Writer?qing)其所有带Reader, Writer的子c?/p>

五、按输入输出分:(x)
1、输入:(x)Reader, InputStreamcd的子c?br />2、输出:(x)Writer, OutputStreamcd的子c?/p>

六、特D需要:(x)
1、从Stream到Reader,Writer的{换类QInputStreamReader, OutputStreamWriter
2、对象输入输出:(x)ObjectInputStream, ObjectOutputStream
3、进E间通信QPipeInputStream, PipeOutputStream, PipeReader, PipeWriter
4、合q输入:(x)SequenceInputStream
5、更Ҏ(gu)的需要:(x)PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader

军_使用哪个cM?qing)它的构造进E的一般准则如下(不考虑Ҏ(gu)需要)(j)Q?br />首先Q考虑最原始的数据格式是什么:(x) 原则?br />W二Q是输入q是输出Q原则五
W三Q是否需要{换流Q原则六W??br />W四Q数据来源(dQ是什么:(x)原则一
W五Q是否要~冲Q原则三 Q特别注明:(x)一定要注意的是readLine()是否有定义,有什么比read, write更特D的输入或输出方法)(j)
W六Q是否要格式化输出:(x)原则?/p>

I空 2006-09-29 10:17 发表评论
]]>
JavaE序的输入与输出http://m.tkk7.com/spark/archive/2006/09/28/72496.htmlI空I空Thu, 28 Sep 2006 02:41:00 GMThttp://m.tkk7.com/spark/archive/2006/09/28/72496.htmlhttp://m.tkk7.com/spark/comments/72496.htmlhttp://m.tkk7.com/spark/archive/2006/09/28/72496.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/72496.htmlhttp://m.tkk7.com/spark/services/trackbacks/72496.html
7.1 理解java.io的类l承关系

  首先Q让我们考察Java提供的常用输?gu)出流c??.1)。由于类的数目较多,没有列出1.1版本中新增的字符类。在?.2中,我们把字W流cM字节类作了(jin)Ҏ(gu)Q在该图中可以看到字W流cȝl承关系。接口和异常cM被省略了(jin)?br />                        ┌BufferedInputStream
                        ├DataInputStream
              ┌FilterInputStream┼LineNumberInputStream
              ├FileInputStream └PushbackInputStream
              ├ByteArrayInputStream
     ┌InputStream──┼PipedInputStream
     │        ├SequenceInputStream
     │        ├StringBufferInputStream
     │        └ObjectInputStream ┌BufferedOutputStream
     │         ┌FilterOutputStream┼DataOutputStream
  Object┤         ├FileOutputStream └PrintStream
     ├OutputStream──┼ByteArrayOutputStream
     ├File       ├PipedOutputStream
     ├FileDescriptor └ObjectOutputStream
     ├ObjdecStreamClass
     ├RandomAccessFile
     └StreamTokenizer
    ?.1 java.io包中常用cdơ图(不含字符类)
  ?.1中包含了(jin)许多的输入和输出c?q还不包括我们欢天喜C要讲到的字符输入输出类)。ؓ(f)?jin)能正确q用它们Q我们必d它们的功能和关系有个大根式的认识?br />
  7.1.1 字节与字符?br />
  W二章中提到?jin)Unicode字符集和ASCII字符集。前者用16位来表示一个字W,而者用8位来表示一个字W。Unicode字符集可表示的符h然比ASCII字符集多得多Q它可以表示世界上大多数语言的符受?br />  在JDK1.0x版本中,只提供了(jin)字节输入输出类。也是_(d)输入输出的数据以字节写单位。这q操作一些双字节字符带来?jin)困难。比如汉字,用一个字节是不能表示Q这׃JavaE序的汉化成?jin)问题。例如,?.0x版的JDK开发一个文本编辑器Q就可能出现q样的情况:(x)用剪贴板可以把汉字脓(chung)q文本域却无法用键盘向文本域输入汉字字符。这是标准输入每ơ只接收?jin)一个汉字的W一字节引v的?br />  JDK1.1版对输入输出作了(jin)改进Qؓ(f)字节输入输出类增加?jin)对应的字符输入输出类q样Q程序员可以根据实际情况选用合适的cR?br />  字符I/O有其昄而易见的好处。首先它可以适用于世界上大部分语aQ从而ؓ(f)JavaE序的本地化带来方便。其ơ,一ơ读一个字W?16?比读一个字节来得快Q一般情况下可以弥补数据按当前语言标准~码、解码的旉开销?br />  字节I/Ocd字符I/Ocȝ命名有其对应关系。字节输入流cȝ名字以“InputStream”结。而字W输入流cȝ名字以“Reader?l尾。字节输出流cȝ名字后缀为“OutputStream”,而字W输出流cȝ名字后缀为“Writer”?br />  Z(jin)在适当的时候能把这两种类联系hQAPI中设|了(jin)两个c,充当二者的桥梁。InputStreamReaderҎ(gu)特定的编码规则从字节创建相应的字符,而Output。StreamWriter则根据编码规则从字符读取字W,把它们{化ؓ(f)字节Q写入字节流中?br />  下面列出两种类的对应关p??.2)。其中,左边一栏是按承关pL列的字符类Q右Ҏ(gu)对应的字节流cR?br />  Reader            InputStream
   ├BufferedReader      BufferedInputStream
   │  └LineNumberReader  LineNumberReader
   ├CharArrayReader     ByteArrayInputStream
   ├InputStreamReader     (none)
   │  └FileReader     FileInputStream
   ├FilterReader       FilterInputStream
   │  └PushbackReader   PushbackInputStream
   ├PipedReader        PipedInputStream
   └StringReader       StringBufferInputStream

  Write             OutputStream
  ├BufferedWriter       BufferedOutputStream
  ├CharArrayWriter       ByteArrayOutputStream
  ├OutputStreamWriter     (none)
  │  └FileWriter       FileOutputStream
  ├FilterWriter         FilterOutputStream
  ├PrintWriter         PrintStream
  ├PipedWriter         PipedOutputStream
  └StringWriter         (none)
    ?.2字符类与字节流cȝ对应关系

  另外Q?.1版的API中,对一?.0x版本中已存在的类也进行了(jin)微小的修改,q主要是因ؓ(f)有类对字节和字符的{换可能生错误。如以下构造函数和Ҏ(gu)标记Ӟ(x)
  Sting  DataInputStream.readLine()
  InputStream  Runtime.getLocalizedInputStream(InputStream)
  OutputStream Runtime.getLocalizedOutputStream(OutputStream)
         StreamTokenizer(InputStream)
         String(byte ascii[],int hibyte,int offset,int count)
         String(byte ascii[],int hibyte)
    void    String.getBytes(int srcBegin,int srcEnd,byte dst[],int dstBegin)
  另外Q添加了(jin)如下构造函数和Ҏ(gu)Q?br />         StreamTokenizer(Reader)
  byte[]     String.getBytes()
  void     Throwable.printStackTrace(PrintWriter)
  当程序员使用旧的API~程Ӟ可以?br />  javac -deprecation(文g?
  来进行编译,q样~译器会(x)l出较ؓ(f)详细的警告信息。编Eh员可Ҏ(gu)q些信息查找新文档,以获知新版本中的替代Ҏ(gu)?br />  本章的例子都是依?.1版本的API~写的?br />
  7.1.2 输入输出cȝ分类

  java.io包中的类各有各的分工Q粗略说来可以分Z下几c:(x)
  文gI/OQ有三类。对字节类来说Q包括把文g作ؓ(f)源进行流式输入的FileInputStreamc;把文件作为目的进行流式输出的 FileOutputStreamc;若你想随机存取文Ӟ卛_文g的Q意位|读、数据,那么可以使用RandomAccessFilecR字W类则有 FileReader和FileWritercR它们的功能对应于前两个字节类?br />  除此之外Q还有两个类是与文g讉K有关的,切地说其功能更q于文g理。它们是Filec,用以讉K文g或目录;FileDescriptor则封装了(jin)操作pȝ用以q踪被访问文件的信息?br />  内存~冲区I/OQ字节流cLByteArrayInputStreamc,字节数l{化ؓ(f)输入,是从一个字W串创徏输入,?ByteArrayInputStream异曲同工Q帮也归入此cd。相应地Q字W流cLCharArrayReader, CharArrayWriter,StringReader,此外q多一个StringWriter用来写字W串?br />  余下一些类可以不同方式存取中的数据。字节流cMQDataInputStream和DataOutputStream因其能对中的不同类的对象分别操作而显得与众不同;ObjectInputStream和ObjectOutputStream能把若干完整的对象按选定的格式进行读写,但要求被操作对象实现Serializable接口QBufferedInputStream和BufferedOutputStream可以Ҏ(gu)数据q行~冲Q实现类似“预输入”、“缓输出”的功能QLineNumberInputStream跟踪输入中的行敎ͼPusthbackInputStream提供?jin)一个“可推回”的,从这个流中读?jin)数据后Q还可以它攑֛中QPrintStreamcL供了(jin)许多重蝲的方法以化输出。对应的字符类可以?7.1.1节的对应关系中查出?br />  除了(jin)上述cM外,Javaq有U特D的I/OcZ—管道I/OcR它们是专门为线E通讯预备的。管道提供了(jin)自动同步机制Q可以防止线E通讯中的数据混ؕ?br />  臛_怿读者已对各个I/Ocȝ功能有所?jin)解。这里再解释一下过滤器I/O 推广java.io包中有不类是过滤器c,它们都是从FilterInputStream或FilterOutputStream之中z而来(参见?7.1)。在字符中Q也有类似的c,但ƈ不像字节类一样必然从某个公共的过滤器父类z而来?br />  qo(h)?Filter)形成的类对象从一个流中读入数据,写入另一个,像一个流l过qo(h)产生另一个流一栗过滤器可以联合使用Q也是说“过滤”过的流可以再经其它qo(h)器“过滤”,qo(h)器型cȝ共性是Q?br />  (1)用和U流为参数的构造,且输入型qo(h)器用输入,输出型过滤器用输出流Q?br />  (2)无明昄?目的限制Q?br />  (3)中数据的内容“多”ƈ未改变,只可能性质略有变化?br />读者不妨以q几条标准去理解qo(h)器I/OcM其子c,q在以后的示例中加以验证?br />
7.2 输入与输出?br />
  字节输入InputStream与字节输出流OUtputStream是两个抽象类。它们ؓ(f)java.io包中名目J多的字节输入和输出打下了(jin)基础。由于是抽象c,它们不能被实例化(也就是说Q不能得到其对象)Q但它们的方法可以被zcLl承或重写?br />  对于字符,相应的流cLReader和W(xu)riter。由于它们的Ҏ(gu)与InputStream和OutputStream对应Q只是把对字节的操作改ؓ(f)对字W的操作Q这里不再重复介l。但Z(jin)读者能够对它们的对应关pL个基本认识,在本节末N上ReadercȝҎ(gu)列表Q请读者参照?br />  InputStream的方C如下:(x)
  ■public abstract int read() throws IOException
  ■public int read(byte b[]) throws IOException
  ■public int read(byte b[],int offset,int length) throws IOException
  功能Z输入中L据。这一Ҏ(gu)有几U重载Ş式,可以M个字节或一l字节。当遇到文g时Q返?1。最后一UŞ式中的offset是指把结果放在b[]中从Woffset个字节开始的I间Qlength为长度?br />  ■public int available() throws IOException
  输入共有多字节可诅R注意此Ҏ(gu)对InputStream的各zcM一定都有效Q有时会(x)有返回零字节的错误结果?br />  ■public void close() throws IOException
  关闭输入ƈ释放资源?br />  ■public boolean markSupperted()
  q回布尔|说明此流能否做标记?br />  ■public synchronized void mark(int readlimit)
  为当前流做标记。其参数说明在标记失效前可以d字节,q个值通常也就讑֮?jin)流的缓冲区大小?br />  ■public synchronized void reset() throws IOException
  q回C一ơ做标记处?br />  ■public long skip (long n) throws IOEnception
从输入流跌几个字节。返回gؓ(f)实际跌的字节数?br />  对于“mark”我们还需解释一下。输入流提供“标记”这一机制QZ可以记录中某些特定的位|,q能重复读部分内宏V支持“mark”就必须要求当前有一定大的~冲区,存放部分数据Q即从标记点到当前位|的数据。当q一~冲满溢出,我们无法追t到上一个标记处的数据了(jin)Q这q之ؓ(f)“标记失效”。若想用reset()q回C个失效的标记处,会(x)发生输入输出异常(IOException)?br />  OutputStream的方法如下。各Ҏ(gu)均可能抛?gu)入输出异?throws IOException)?br />  ■public abstract void write(int b)
  ■public void write(byte b[])
  ■public void write(byte b[],int offset,int length)
  q三个重载Ş式都是用来向输出写数据的。具体每个不甘落后 作用Q读者可Ҏ(gu)前文read()Ҏ(gu)对照之?br />  ■public void flush()
  清除~冲区,缓冲区内尚未写出的数据全部输出。若要承OutputStreamc,q个Ҏ(gu)必须重写Q因为OutputStream中的Ҏ(gu)未做M实物性工作?br />  ■public void close()
  关闭输出,释放资源?br />  以上提到的这些方法,在下面的章节中将有不被q用Q读者可Ҏ(gu)实例领会(x)它们?br />  附ReadercȝҎ(gu)列表?br />  构造函敎ͼ(x)
  ■protected Reader() 
  ■protected Reader(object lock)
  Ҏ(gu)Q?br />  ■public int read() throws IOException
  ■public int read(char cbuf[]) throws IOException
  ■public abstract int read(char cbuf[],int off,int len)throws IOException
  ■public long skip(long n) throws IOException
  ■public boolean ready() throws IOException //判断是不可以读
  ■public boolean mark(int readAheadLimit)throws IOException
  ■public void reset() throws IOException
  ■public abstract void close() throws IOException

7.3 文gI/O

  q一节中我们结合实例讨论FileQFileInputStreamQFileOutputStreamQFileDescriptor和RandomAccessFilecȝҎ(gu)与用?br />
  7.3.1 一个文件I/O实例

  让我们用一个例子来演示Ҏ(gu)件的输入输出(?.1)。图7.3中列Z(jin)q个例子的运行结果?br />  ?.1 fileIODemo.java?br />  1:import java.io.*;
  2:import java.lang.*;
  3:
  4: public class fileIODemo{
  5:  public static void main(String args[]){
  6:   try{
     //创徏输入输出?br />  7:   FileInputStream inStream = new FileInputStream("text.src");
  8:   FileOutputStream outStream = new FileOutputStream("text.des");
      //Lq写入输出流
  9:     boolean eof = false;
  10:    while(!eof){
  11:     int c = inStream.read();
  12:     if(c==-1) eof = true;
  13:     outStream.write((char)c);
  14:    }
  15:    inStream.close();
  16:    outStream.close();
  17:   }catch(FileNotFoundException ex){
  18:    System.out.println("Error finding the files");
  19:   }catch(IOException ex){
  20:   System.out.println("IOException occured.");
  21:  }
    //获取文g理信息
  22:  File file = new File("text.des");
  23:  System.out.println("Parent Directory:"+file.getParent());
  24:  System.out.println("Path:"+file.getPath());
  25:  System.out.println("File Name:"+file.getName());
  26:  try{
     //创徏RandomAccessFile对象Q以侉K写?rw"代表可读可写
  27:   RandomAccessFile rafile = new RandomAccessFile("text.des","rw");
     //指针|到文g?br />  28:   rafile.seek(0);
  29:   boolean eof=false;
  30:   System.out.println("The content from very head:");
     //L?br />  31:   while(!eof)?br />  32:   int c = rafile.read();
  33:    if(c==-1) eof = true;
  34:    else System.out.print((char)c);
  35:   }
     //下两行把L针置到第三字?br />  36:   rafile.seek(0);
  37:   rafile.skipBytes(3);
  38:   System.out.println("\nThe pointer's position:"+rafile.getFilePointer());
  39:   System.out.println("The content from current position:");
  40:   eof=false;
  41:   while(!eof){
  42:    int c=rafile.read();
  43:    if(c==-1) eof=true;
  44:    else System.out.print((char)c);
  45:   }
     //强制输出~冲Z所有内?br />  46:   System.out.flush();
  47:   rafile.close();
  48:  }catch(IOException ex){
  49:   System.out.println("RandomAccessFile cause IOException!");
  50:  }
  51: }
  52:}
  ?.1的运行结果如下:(x)
  (?
  Z(jin)充分展示与文件I/O相关的类的作用,我们的例子中有一些冗余的东西。我们的q个E序位于C:\BookDemo\ch07路径?见例7.1?7)Q此路径又有一个子上当textQ其中有文gtext.src。运行此E序Q将在C:\bookDemo\ch07下创Z个新文g text.desQtext.src的内容被写信此文件。下面的D对Filecȝ演示说明?jin)文件的部分理信息。然后我们又使用?RandomAccessFileQ试验了(jin)文g在指定位|的d?br />  W?6行的Sytem.out.flush()语句不可以被省略Q读者不妨去掉它试一试。你?x)发玎ͼ有一部分输出信息不知道到哪儿M(jin)。实际上Qflush()的作用就是把~冲Z的数据全部输出,我们输出流输出以后Q某些输出流(有缓冲区的流)只是把数据写q了(jin)~冲已Q不?x)马上写到我们要求的目的地。如果不像例子中一样强制输出,部分数据可以来不及(qing)在程序结束前输出?jin)?br />  l心(j)的读者或许要问:(x)Z么第一ơ用ReadomAccessFileL件时Q输?gu)句后面没有flush()呢?岂非自相矛盾吗?原来Q?System.out是PrintStreamcȝ对象(关于PrintStream后有~冲Z的内Ҏ(gu)除出厅R因此许多地方就不必加flush() ?jin)。PrintStream的这个特点,在创建其对象时是可以L(disable)的?br />  q个E序中用C(jin)IOException和FileNotFoundException两个异常。后者是从前者派生出来的Q因此,如果dE序中的所有try、catchQ而在main()Ҏ(gu)开头加上throws IOExceptionQ哪样可以。但q样不好区分各种不同的异常情况,即找不到我们需要的text.src文gQ也不会(x)有Q何信息显C。这无疑是一U不良的~程风格。因此我们提倡对各个异常分别处理Q这样对出错情况可以很地掌握?br />
  7.3.2 文g输入输出的类库支?br />
  下面我们逐一介绍?.1中用到的各个cR?br />  1.Filec?br />  Filecȝ构造函数有三个。分别根据文件名、文件\径与文g名、文件对?目录)与文件名创徏实例。即Q?br />  ■public File(String path)
  ■public File(String path,String name)
  ■public File(File dir,String name)
  除了(jin)例子中用到的以外Q还有许多方法,下面仅列?gu)常用的?x)
  ■public boolean exists()判断文g是否存在
  ■public boolean canRead()判断文g是否可读
  ■public long length()q回文g长度
  ■public boolean mkdir()创徏目录
  ■public boolean renameTo(File dest)文g改名
其中Q后三个Ҏ(gu)可能抛出I/O异常?br />  2.FileInputStreamc?br />  它是文g输入类
  构造函数有三个Q?br />  ■public FileInputStream(String fileName) throws FileNotFoundException
  ■public FileInputStream(File file) throws FileNotFoundException
  ■public FileInputStream(int fd) throws FileNotFoundException
  三个构造函数分别根据文件名、文件对象、文件描q符创徏一个文件输入流。例子中用的是第一U?br />  Ҏ(gu)Q?br />  read()、skip()、available() 、close()分别重写?jin)抽象类InputStream的同名方法,功能如前所q。此外还有:(x)
  ■public final int getFD()
  q回相应的文件描q符?br />  ■protedted void finalize() throws IOException
  关闭输入,q收集无用内存空间?br />  现在我们必须介绍一下文件描q符cFileDescriptor。这个类用于讉K操作pȝl护的文件描q符(也称句柄)。但q个cM不能讉K很多信息。它只提供了(jin)两个Ҏ(gu)Q即valid()Q以判断文g描述W是否有效;sync()Q用以同步系l缓冲区?br />  3.FileOutputStreamc?br />  文g输出。三个构造函敎ͼ其参数、返回值及(qing)异常均与FileInputStream的相对应。write()、close()Ҏ(gu)重写?OutputStream的同名方法。getFD()与finalize()功能与InputStream的类伹{?br />  4.ReadomAccessFilec?br />  该类用于随机讉K文g?br />  构造函数有三种Q?br />  ■public RandomAccessFile(String Filename,String mode) throws IOException
  ■public RandomAccessFile(int FD) throws IOException
  ■public RandomAccessFile(File file,String mode)throws IOException
  ׃可见Q我们可以用文g名加d方式、文件描q符、File对象加读写方式来创徏其对象。其中读写方式用“r”表C只读,“rw”表C可dQ等{。用qE语言的读者对此应当不?x)陌生?br />  此类的成员方法很多。除?jin)重写InputStream的read()Ҏ(gu)之外Q还可以诅R写一个布?yu)(dng)倹{一个字节、一个整?.....{对象。这些方法都不可重写Qƈ且抛出テQO异常(IOException)。讯Ҏ(gu)名ؓ(f)“read”加cd?cd名的W一字母大写)Q写Ҏ(gu)名ؓ(f)“write”加cd名。如
  readInt()M个整型数
  writeDouble()写一个双_ֺ点?br />{。另外还有文件指针的操作Q如skipBytes(int n){?br />  有了(jin)以上q些cȝ支持Q处理文件输入输出和l护文g容易多?jin)?br />
7.4 内存~冲?br />
  内存~冲区I/OQ对字节来说指的是ByteArrayInputStream和ByteArrayOutputStreamcȝq用。此外, StringBufferInputStream与ByteArrayInputStream用法怼一q介l。对字符不另D例,它们使用与字节流cȝ伹{?br />
  7.4.1 E序CZ

  同上一节一P我们q是先看一个例??.2)
  ?.2 ByteArrayIODemo.java
  1:import java.io.*;
  2:
  3: public class ByteArrayIODemo{
  4:  public static void main(String args[]) throws IOException{
      String s ="This a test";
  5:   byte buffer[]=s.getBytes();
  6:   ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
  7Q  for(int i=0;i<buffer.length;++i)
  8:    byteArrayOut.write(buffer[i]);
  //由字节数l创建字节输入流
  9:   ByteArrayInputStream inStream = new
       ByteArrayInputStream(byteArrayOut.toByteArray());
  //d
  10:  boolean eof=false;
  11:  while(!eof){
  12:   int c=inStream.read();
  13:   if(c==-1) eof=true;
  14:    else System.out.print((char)c);
  15:  }
  16:  System.out.println("\nThe'writeTo' method can produce same results.");
  //用ByteArrayOutputStream的writeTo()Ҏ(gu)?br />  17:  byteArrayOut.writeTo(System.out);
  18:  byteArrayOut.close();
  //available()与reset()的?br />  19:  System.out.println("\nThe buf of inStream has the length(before
    seset):"+inStream.available());
  20:  inStream.reset();
  21:  System.out.println("\nThe buf of inStream has the length:"+inStream.available());
  22:  inStream.close();
  23: }
  24:}
  该程序的q行l果Q??
  q个例子看来相对单些。我们先把字节数l的内容写进一个字节数l输出流对象。然后,用一个字节数l输入流对象L据,再用System.out输出。程序显CZ(jin)writeTo()Ҏ(gu)的作用。另外,我们q在reset()前、后用了(jin)两疚available()Ҏ(gu)Q请注意两方法先后生的不同l果。这个例子主要用来演C字节数lI/O的部分方法?br />
  7.4.2~冲区I/O的类库支?br />
  看过?jin)例子,我们接下来介l有关的cR?br />  1.ByteArrayInputStreamc?br />  q个cȝ于从一?br />  字节数组取得输入数据?br />  它有两个构造函敎ͼ(x)
  ■public ByteArrayInputStream(byte Buf[])
  由字节数l创建相应的输入?br />  ■public ByteArrayInputStream(byte buf[],int offset,int length)
  由字节数l中L(fng)为offset长ؓ(f)length的一D创入流?br />  成员变量Q?br />  protected byte buf[]数据~冲?br />  protected int pos ~冲Z当前位置
  protected int count~冲Z字节数目
  该类的成员方法都是同?synchronized)的?br />  ■public synchronized int read()
  M个字节?br />  ■public synchronized int read(byte b[],int offset,intrlength)
  d多个字节Q返g般ؓ(f)d的字节数。但d末尾时返?1?br />  ■public synchronized long skip(long n)
  跌n个字节。若q回g{于nQ可能是遇到末尾?br />  ■public synchronized int available()
  求得~冲区内字节数目?br />  ■public synchronized void reset()
  该指针重新设|到输入的开始处。注意,q个reset()与InputStream中的功能不同。它q不作用于标记?br />  2.ByteArrayOutputStreamc?br />  q个cȝ于把数据写进字节数组(~冲??br />  构造函敎ͼ(x)
  ■public ByteArrayOutputStream()
  ■public ByteArrayOntput Stream(int size)
  其中size指定~冲区的初始大小(它是可以动态增长的)?br />  成员变量Q?br />  protected byte buf[]~冲?br />  protected int count~冲区大?br />  Ҏ(gu)Q?br />  ■public synchronized void write(int b)
  写一个字节?br />  ■public synchronized void write(byte b[],int offset,int length)
  把数lb中由offset开始长为length的一部分写入~冲区?br />  ■public synchronized void writeTo(OutputStream out)throws IOException
  把缓冲区内容写到另一输出out?br />  ■public synchronized void reset()
  指针定到~冲区开始。当?dng)以后再写入也是从缓冲区的开始位|重写了(jin)Q原有的内容都清掉?jin)?br />  ■public syschronized byte[] toByteArray()
  缓冲区内容作ؓ(f)一个字节数l返回?br />  ■public int size()
  当前~冲区大?br />  ■public string toString()
  ■public string toString(int hibyte)
  把缓冲区内容转化为字W串。其中h(hun)ibyte指把字符(通常是8位的ASCII字符)转ؓ(f)16位的Unicode值时Q高八的倹{?br />  3.StringBufferInputStreamc?br />  它的构造函C一个字W串为参敎ͼ原型为:(x)
  ■public StringBufferInputStream(String s)
  其余成员变量?qing)方法均与ByteArrayInputStream的同名且基本功能相同Q此不赘q?br />  q三个类的共性是内存中开辟了(jin)一D늩间来做I/O~冲区,故称~冲区I/OcR?br />
7.5 qo(h)器I/O

  q一节涉?qing)的c较多,但我们可以结合几个例子逐一介绍?br />  在第一节中Q我们已l谈?jin)一些过滤器cȝҎ(gu)。过滤器是可以“连接”的Q即一个数据流l过qo(h)后,其结果可以再ơ过滤。我们可以用这样一串过滤器中的M个方法来完成某种Ҏ(gu)的操作。关于这一点在W二个例子中有更明白的阐q?br />
  7.5.1 ?:各类数据的I/O

  W一个例??.3)演示?jin)对各类数据的输入输出?br />  ?.3FilterIODemo1.java?br />  1: import java.io.*;
  2: public class FilterIODemo1{
  3:  public static void main(String args[]) throws IOException{
      //串接qo(h)?br />  4:   BufferedOutputStream bufOut=
  5:    new BufferedOutputStream(new FileOutputStream("text.txt"));
  6:   DataOutputStream dataOut = new DataOutputStream(bufOut);
      //用DataOutputStreamcd各种数据
  7:   dataOut.writeBoolean(true);
  8:   dataOut.writeChar('a');
  9:   dataOut.writeInt(1);
  10:  dataOut.writeDouble(3.3);
  11:  bufOut.close();
  12:  dataOut.close();
  13:  BufferedInputStream bufIn=
  14:   new BufferedInputStream(new FileInputStream("text.txt"));
  15:  DataInputStream dataIn= new DataInputStream(bufIn);
    //用DataInputStreamc读各种数据
  16:  System.out.println(dataIn.readBoolean());
  17:  System.out.println(dataIn.readChar());
  18:  System.out.println(dataIn.readInt());
  19:  System.out.println(dataIn.readDouble());
  20:  bufIn.close();
  21:  dataIn.close();
  22: }
  23:}
  ?.3的运行结果如下:(x)(?
  上述例子演示?jin)DataInputStream、DataOutpurStream、BufferedInputStream?BufferedOutputStream的用。该E序中只有一个方法main()?br />  在方法的开_(d)我们实例化了(jin)BufferedOutputStreamc,得到对象bufOut。注意,我们的数据输出的最l目的地是文?“Text.txt”。ؓ(f)?jin)能够利用BufferedOutputStream的缓输出(把输出内容先存入~冲Q然后大块输?功能Q我们在文g输出应对上加一个过滤器QŞ成:(x)
  数据→过滤器对象bufOut→文件输出流
q样Q我们用dataOut来写数据Q就可以直接把各U类型的数据写入文gtext.txt?br />  E序的后半部分几乎是W一个程序的ȝ。我们在输入上也加?jin)过滤器Q就可以用过滤器的方法来操作输入了(jin)?br />  ׃BufferedOutputStream和BufferedInputStream没有提供新的Ҏ(gu)Q这个例子也怼(x)使读者生一U错觉,好像只有最外层(最接近“数据?的过滤器才能操纵输入。事实ƈ非如此,我们在下一个例子中说明q一炏V?br />  我们要解释的问题是,如果我们L据时Q选用的读Ҏ(gu)与写时不一致会(x)怎么样呢Q读者可以自行实验一下。如果我们把
  dataIn.readBoolean()换作dataIn.readChar()
d的结果就不正了(jin)(注意d的ƈ不是字符‘t?Q各U类型的数据存储的格式是不同的。虽然我们得C(jin)?.4所C的l果Q但如果你用type命o(h)看一?text.txtQ将?x)看C同的输出。因此,不要把程序的输出和数据的内部在存储؜Z谈。当使用dataI/OӞ应当对你要读的数据的cd?j)中有数。DataInputStreamq不能从一堆数据中析取你所需要的那个整数?br />
  7.5.2 qo(h)器类家庭

  下面我们介绍?中出现的qo(h)器类。首先介l一下它们的父类FilterInputStream和FilterOutputStream?br />  1.FilterInputStreamc?br />  q是一个抽象类。它是所有过滤器输入cȝ父类Q提供了(jin)从一个输入流创徏另一个输入流的方法?br />  构造函敎ͼ(x)
  ■public FilterInputStream(InputStream in)
  Z个输入流构造过滤器输入?br />  Ҏ(gu)Q?br />  重写?jin)InputStream的同名方法,未提供新的方法?br />  2.FilterOutputStreamc?br />  与FilterOutputStream相对应,提供从一个输出流创徏另一个输出流的方法?br />  构造函敎ͼ(x)
  ■public Filer OutputStream(OutputStream out)
  p出流创始创徏一个过滤器输出?br />  Ҏ(gu)Q?br />  重写?jin)OutputStream的同名方法?br />   3.BufferedInputStreamc?br />  从这个类开始,我们来介l例7.3中用到的qo(h)器子cRBufferedInputStreamcL供了(jin)一U“预输入”功能,它把输入数据在其~冲区内暂存Q在适当的时候把较大块的数据提交出去?br />  构造函敎ͼ(x)
  ■public BufferedInputStream(InputStream in)
  ■public BufferedInputStream(InputSteam in,int size)
  其中size指缓冲区大小?br />  Ҏ(gu)Q?br />  重写?jin)父cȝҎ(gu)。其中skip()、available()、mark()、reset()均ؓ(f)同步(synchonized)Ҏ(gu)?br />  4. BufferedOutputStreamc?br />  提供“缓输出”功能,把输出数据暂存后Q在适当时候大扚w出?br />  构造函敎ͼ(x)
  ■public BufferedOutputStream(OutputStream out)
  ■public BufferedOutputStream(OutputStream out,int size)
  Ҏ(gu)Q?br />  ■public synchronized void write(int b) throws IOException
  ■public synchronized void write(byte b[],int offset,int length) throws IOException
  ■public synchronized void flush() throws IOException
以上Ҏ(gu)重写?jin)父cȝ同名Ҏ(gu)?br />  在BufferedI/OcMQ还有一些protect型的成员变量Q是关于~冲区和标记的,q里׃一一列出?jin)?br />  5. DataInput接口和DataOutput接口
  要介lData I/Oc,必MlData I/O接口?br />  Data I/Ocȝ目的是从中析取或向中写入指定的数据对象。一个流可以是纯字符,也可以包含许多类型的数据。DataInput接口?DataOutput接口提供了(jin)从流中析取和写入数据的方法。用于读的方法除?jin)个别之外都是无参的Q写的方法则往往以被 写的数据cd为参数。方法的名字也很好记Q即为“read”或“write”后接类型名Q如readInt()QreadUnsignedByte()QwriteInt()Q?writeUnsignedByte(){。这引vҎ(gu)均可能抛出テQO异常。一般说来,L遇文件尾时抛出EOFException(?IOException的子c?Q读写时发生其它错误抛出IOException?br />除了(jin)上面所说的名字很有规律的方法外QData I/O接口中还有几个方法:(x)
  ■public abstract void readFully(byte buffer[])
  d部数据到buffer[]数组。读时系l处于阻塞状态?br />  ■public abstract void readFully(byte buffer[],int offset,int length)
  把数据读到数lbuffer[]中从Offset开始长为length的地斏V?br />  ■public abstract int skipBytes(int n)
  跌规定字节数。返gؓ(f)实际跌的字节数?br />  ■public abstract String readLine()
  d一行数据?br />  此外Q还有我们早已熟(zhn)的write()Ҏ(gu)的三U重载Ş式?br />  6. DataInputStreamc?br />  介绍q两个数据I/O的接口后Q介l数据I/O类q单多?jin)。DataInputStreamcdC(jin)DataInput接口Q因面也实C(jin)q个接口的所有成员方法。此外,q有两个read()Ҏ(gu)Q?br />  ■public final int read(byte b[])
  ■public final int read(byte b[],int offset,int length)
  重写?jin)FilterInputStream的同名方法?br />  DataInputStream只有一个构造函数。像所有过滤器输入类一Pq个构造函数的参数是InputStream的一个对象?br />  7.DataOutputStreamc?br />  q个cȝ成员Ҏ(gu)我们都很熟?zhn)了(jin)。除?jin)实现DataOutput接口的方法之外,再就是一个flush()Ҏ(gu)。write()与flush()重写?jin)FilterOutputStreamcȝ同名Ҏ(gu)?br />  现在我们可以回过头来再看一下例7.3Q印证一下刚才讲q的内容。这个例子的重点之一是演C滤器的“连接”,另一个是介绍相应的类?br />
  7.5.3 ?:行号与“可推回”的?br />
  在下面的例子(?.4)中,我们进一步理解过滤器的连接问题。前面例子基本上用的都是字节类Q这个例子用字W流cR?br />  ?.4 FilterIODemo2.java?br />  1:import java.io.*;

  3:public class FilterIODemo2{
  4: public static void main(String args[]) throws IOException{
  5:  String s="this is a multi-line string.\n It is \nused to demo filterIO.\n";
  6:  char array[]=new char[s.length()];
  7:  for(int i=0;i<s.length();++i)
  8:  array[i]=s.charAt(i);
    //创徏字符,串接qo(h)?br />  9:  CharArrayReader charReader = new CharArrayReader(array);
  10:  PushbackReader pushReader = new PushbackReader(charReader);
  11:  LineNumberReader lineReader = new LineNumberReader(pushReader);
  12:  String line;
    //dW流Q加行号输出
  13:  while((line = lineReader.readLine())!=null){
  14:   System.out.println(lineReader.getLineNumber()+":"+line);
  15:  }
    //指针|到开?br />  16:  try{ pushReader.reset();}catch(IOException e){}
    //dW流Q每d一?\n'把它推?br />  17:  boolean eof = false;
  18:  boolean met = false;
  19:  while(!eof){
  20:   int c=pushReader.read();
  21:   if(c==-1) eof=true;
  22:   else if(((char)c=='\n')&&!met){met =true;pushReader.unread(c);}
  23:   else met =false;
  24:   if(c!=-1) System.out.print((char)c);
  25:  }
  26:  System.out.flush();
  27:  pushReader.close();
  28:  charReader.close();
  29:  lineReader.close();
  30: }
  31:}
  该程序的q行l果如下Q??
  q个例子的功能是Q给一个字W串加上行号后输出;把每个换行符都“重复”一ơ,xơ换行时加一个空行。该例子使用的是字符I/OQ演CZ(jin)几个cȝ使用QCharArrayReaderQPushbackReaderQLineNumberReader。此外,我们q可以复?fn)一下前面提到的几个类?br />  PushbackReaderQ顾名思义是是可以把数据“推回”输入流的流cR我们用它来实现Ҏ(gu)行符的重复——只要读完后把“推回去”,下次可再读一遍了(jin)。LineNumberReader可以q踪输入的行敎ͼ用它来实现加行号输出?br />  现在来讲解一下程序。第Q行中,在main()Ҏ(gu)的开始,定义?jin)一个字W串s。其中,有三个换行符‘\n’。然后创Z个字节数lArray[]Qƈ在接下来的for循环(W???中ؓ(f)它赋倹{以此ؓ(f)参数创徏?jin)一个内存缓冲区输入的对象。这是我们一串过滤器的源炏V注意arrayq不是一个输入流Q相应的CaarArrayReader也不是一个过滤器?br />  现在考虑选用qo(h)器。可Ҏ(gu)我们惌的功能来选择。既然我们要行号Q那么显然最好是一行一行读数据。BufferedReader的readLine ()Ҏ(gu)正是我们需要?readLine()Ҏ(gu)本来是DataInputStreamcȝҎ(gu)Q但?.1版中q时?jin)。详l情况在W一节中已有说明。这里用DataInputStream也是可以的但~译时会(x)警告信息?加行h们可以一行一行地读,也可以自己高于个变量来篏计行数。当然也可以利用一个现成的cd现在的方法——选择LineNumbdrReadercd(qing)其getLineNumber()Ҏ(gu)。由于LineNumbdrReader本n是BuffredReadercȝ子类Q可以直接用它来逐行L据,不必再引入BufferedReadercRؓ(f)?jin)重复写回画换行W可选用 PushbackInputStreamcd它的unread()Ҏ(gu)?br />  下面的Q务是把它们串hQ如例子所C,可将它些qo(h)器一个“输出”作Z一个的“输入”。第一个while循环(W?3?5?中做的事很简单;M行信息,取得其行P然后一些输出?br />  W二个while循环(W?9行到25?的工作是重写操作W。我们用pushReader来读数据。布?yu)(dng)量eof来标识输入是否结束,met用来标识当瓣换行W是否被推回q。当输入没有l束Ӟ每读C个‘\n?Ӟ׃?x)再“推回”了(jin)Q保证换行符只被重复一ơ?br />  正如前面所提到q的Q一串过滤器中的M个都可以操作数据Q无qo(h)器是最先的或最末的或是中间的Q何一个?br />  ׃我们是用print()Ҏ(gu)来输出字W的Q程序结束时可能q有一部分数据在缓冲区中,没被写到屏幕上。因此我们加?jin)一个flush()Ҏ(gu)强制昄到屏q上?br />  用q的都关闭(W?7?9?是一U好的编辑风根{虽然Java的“垃圾收集”系l可以回收废弃不用的资源Q仍应自觉地打扫“战场”,把能回收的资源主动回收?br />
  7.5.4 cd支持

  下面详细介绍一下例7.4中新出现的类。有一炚w要解释,是字符I/OcM字节I/Ocȝl承关系q不是一一对应的。比如,字节I/OcM?PrintStream是FilterOutputStream的子c,而对应的字符类PrintWriter却是Writercȝ子类。因此,严格地说PrintWriterqqo(h)器类。但是,Z(jin)能够分六别类地研I这些类Q我们不苛求q个差别Q而是按照字节I/Ocȝl承关系Q对应地把相应字W流I/OcM看作qo(h)器类?br />  1.PushbackReaderc?br />  构造函C个:(x)
  ■public PushbackReader(Reader in,int size)
  创徏~冲区大ؓ(f)size的一个PushbackReader对象?br />  ■public PushbackReader(Reader in)
  创徏~冲区大ؓ(f)一个字W的一个PushbackReader对象?br />  Ҏ(gu)Q?br />  ■public int read()
  ■public int read(char cbuf[],int offset,int length)
  L据?br />  ■public void unread(int ch)
  回退一个字W。当~冲区满或发生其它输入输出的异常情况Ӟ抛出I/O异常?br />  ■public int avaliable()
  q回~冲区内字节个数?br />  ■public boolean markSupported()
  认输入是否支持标记功能?br />read()、unread()、available()均可能抛出IOException?br />  2.LineNumberReaderc?br />  构造函C个,与PushbackReadercM?br />  下面列出Ҏ(gu)的原型,其中我们已经熟?zhn)的,在此׃l出解释?jin)?br />  ■public int read() throws IOException
  ■public int read(char cbuf[],int offset,int length) throws IOException
  ■public void setLineNumber(int lineNumber)
  讄行号?br />  ■public int getLineNumber()
  读行受?br />  ■public long skip(long n) throws IOException
  ■public int available()throws IOException
  ■public void mark(int readAheadLimit)throws IOException
  在当前位|作标记。从此读取readAheadLimit个字W后标记变ؓ(f)无效?br />  ■public void reset()throws IOException
  q回C一标记?br />  3.PrintStreamcdPrintWriterc?br />  PrintStreamcLqo(h)器类中一个不可忽视的成员Q最基本的标准输出就要借助于它——我们常用的System.out变量是 PrintStream实例。与之对应的字符类是PrintWritercR?br />  PrintStream有两个构造函?在新版AQ;中已标记?Q?br />  ■public PrintStream(OutputStream out)
  ■public PrintStream(OutputStream out,boolean autoFlush)
其中QautoFlush|ؓ(f)trueӞ每当输出遇到换行W,~冲区的内容p强制全部输出Q如同调用了(jin)一ơflush()。但要注意,如果没遇到换行符Q还是会(x)有数据“憋”在~冲区里?br />  Ҏ(gu)(已熟(zhn)的׃解释)Q?br />  ■public void write(int b)
  ■public void write(byte b,int offset,int length)
  ■public void flush()
  ■public void close()
  ■public void print(Object obj)
  q个Ҏ(gu)功能是非常强大的Q它可以输出M对象Q而不必另加说明。此外print()Ҏ(gu)有许多重载Ş式,x多种参数。它们是字符?(String)、字W数l?char[])、字W?char)、整?int)、长整数(long)、QҎ(gu)(float)、双_ֺ点?(double)、布?yu)(dng)?boolean)。其中,输出多个数单位的print()Ҏ(gu)(也就是指参数为String和char[]?是同?(synchronized)Ҏ(gu)?br />  ■public void println()输出一个换行符?br />  ■public synchronized void println(Object obj)
  println()Ҏ(gu)?个重载Ş式,几乎是print()Ҏ(gu)的翻版。唯一的区别在于println()Ҏ(gu)都是同步的?br />  ■public boolean checkError()
  (g)查输?gu)E中有什么错误,如有Q返回true倹{只要输出流中出Cơ错误,则出错后的Q意对checkError()的调用均?x)返回真倹{?br />  下面介绍PrintWritercR?br />  如同W二节中所_(d)PrintWriter是JDK1.1版增加了(jin)与字节流I/O相对应的字符I/O。但是,Z(jin)保持兼容性,原先的类几乎没有改动。再加之调试的需要,PrintStreamc被保留Qƈ且SystemcM的成员变量out、err仍作为它的对象。然而,PrintWriter用于大多数输出比PrintStream更ؓ(f)合适。因?.1版的API中徏议新开发的代码使用PrintWriterc,q将 PrintStreamcȝ两个构造函数标Cؓ(f)q时。这P虽然使用System.out输出不会(x)产生问题Q在E序中创建新的PrintStream对象时却?x)生编译时的警告?br />  PrintWritercMPrintStreamcȝҎ(gu)是对应的。有一个不同之外需提请读者注意,是当前者的自动清空~冲区的功能被能时(构造函CautoFlush|ؓ(f)true)Q仅当println()Ҏ(gu)被调用时才自动清~冲区,而不是像PrintStream一样遇C个换行符清~冲?br />  到此为止Q我们已介绍?jin)各U类型的qo(h)器I/OcR适用于字节流和字W的各种对应qo(h)器类Q其Ҏ(gu)也是对应的。因此,Ҏ(gu)有介l的c读者可以从其对应类推理其功能?br />
7.6 道I/O

  道I/O是专门用于线E通信的。对于字节流Java提供?jin)两个类QPipedInputStreamc被U程用来写字节数据。两个管道I/O对象可以连接v来,q样一个线E写的数据就可以被另一个线E来诅R对于字W流也有两个c,分别叫做PipedReader和PipedWriter。我们只详细介绍字节的道I/OcR?br />
  7.6.1 PipedInputStreamc?br />
  q个cL两个构造函数。一个无参,用它建立赯入流后,需它与一个管道输出流相连接。另一个以道输出?PipedOutputStream)对象为参敎ͼ创徏一个与该输出流对象相连接的输入?br />  PipedInputStreamcȝ所有方法均可能抛出IOException?br />  ■public void connect (PipedOutputStream src)
  输入流q接到某道输出?br />  ■public synchronized int read()
  ■public synchronized int read(byte b[],int offset,int length)
  L据?br />  ■public void close()
  关闭?br />
  7.6.2 PipedOutputStreamc?br />
  与PipedInputStreamcd全对应,它有两个构造函敎ͼ其中一个以PipedInputStream对象为参敎ͼ另一个无参。成员方法也是包括connect()Qclose()Q另外还有两UŞ式的write()Ҏ(gu)Q这里就不细qC(jin)?br />
  7.6.3 E序CZ

  下面用一个示??.5)具体演示道Q/Q的使用?br />  ?.5 PipeIODemo.java
  1: import java.lang.*;
  2: import java.io.PipedInputStream;
  3: import java.io.PipedOutputStream;
  4: import java.io.IOException;
  5:

  6: public class PipeIODemo{
  7:  public static void main(String args[]){
     //q里的Reader和W(xu)riter不是字符输入输出的基本c,而是下文自定义的
  8:   Reader thread1=new Reader("1");
  9:   Writer thread2=new Writer("2");
    //联接道
  10:  try{
  11:   thread2.pipeOut.connect(thread1.pipeIn);
  12:  }catch(IOException ex){
  13:   System.out.println("IOException occured when connecting two stream");
  14:  }
    //启动U程
  15:  thread1.start();
  16:  thread2.start();
    //循环Q等U程均结束后E序中止
  17:  do{
  18:  }while(thread1.isAlive()||thread2.isAlive());
  19:  System.out.println("All over!");
  20: }
  21:}
  //自定义读者类
  22:class Reader extends Thread{
  23: public PipedInputStream pipeIn;
  24: String threadName;
  25: public Reader(String name){
  26:  super();
  27:  threadName = name;
  28:  pipeIn = new PipedInputStream();
  29: }
  30: public void run(){
  31:  try{
  32:   boolean over = false;
  33:   while(!over){
  34:    int ch=pipeIn.read();
  35:    try{
  36:     Thread.sleep(200);
  37:    }catch(InterruptedException ex){
  38:     System.out.println("Sleep is interrupted!");
  39:   }
  40:   if(ch=='.') over = true;
  41:    else System.out.println("Thread "+threadName+" read "+(char)ch);
  42:   }
  43:
  44:  }catch(IOException ex){
  45:   System.out.println("IOException occured when try to read data");
  46:  }
  47: }
  48:}
  //自定义写者类
  49:class Writer extends Thread{
  50: public PipedOutputStream pipeOut;
  51: String threadName;
   //待写内容
  52: String content = "orange apple";
  53: public Writer(String name){
  54:  super();
  55:  threadName=name;
  56:  pipeOut = new PipedOutputStream();
  57: }
  58: public void run(){
  59:  try{
     //字W串内容逐字输出
  60:   for(int i=0;i<content.length();++i){
  61:    pipeOut.write(content.charAt(i));
  62:    try{
  63:     Thread.sleep(200);
  64:    }catch(InterruptedException ex){
  65:     System.out.println("Sleep is interrupted!");
  66:    }
  67:    System.out.println("Thread "+threadName+" wrote "+content.charAt(i));
  68:   }
  69:    pipeOut.write('.');
  70:   }catch(IOException ex){
  71:   System.out.println("IOException occured when try to write data");
  72:  }
  73: }
  74:}
  该程序的q行l果如下Q??
  q个例子功能很简单。两个线E,一个是读者,一个是写者,读者取写者所写的内容。双方约定以?’ؓ(f)l束W?br />  q个例子演示?jin)管道I/O一般过E,首先是创建管理I/O类对象。这个工作是在Reader和W(xu)ritercȝ构造函C做的(W?8?6?。因此当我们创徏?jin)thread1和thread2两个U程ӞpipeIn和pipeOutp创徏?jin)。然后我们把它们q接hQ再启动两个U程工作Q最后打印“All Over!?表示q行l束?br />  可以看出Q读U程与写U程实际上是不必兛_(j)Ҏ(gu)的情늚。它们的工作是L写,每处理一个字W输Z条信息表明自己做q的工作。我们在pipeIn 的输Z息中加了(jin)一大段I格Q这L(fng)目的是两个U程的输?gu)?gu)分L。另外,让两个线E处理一个字W就睡眠(sleep) 一?x)儿q不是必ȝQ这样只是ؓ(f)?jin)增加线E交替执行的Z(x)。如果去q这一D,可能执行数次者不出现thread1、thread2交替输出信息的现象,Ҏ(gu)被误解ؓ(f)两个U程必须一个死亡才执行另一个。另外,作ؓ(f)l束W的??q没有显C出来?br />  q个例子实现的是单向通信。实际上Qؓ(f)每个U程都分别创入流对象和输出流对象Q再分别q接hQ就可以实现双向通信。读者有兴趣不妨一试?br />
7.7 java.io包中的其它类

  7.7.1 SequenceInputStreamc?br />
  q个cȝ功能是合q多个输入流。其构造函数有两个Q一个以枚D(Enumeration)对象为参敎ͼ一个以两个InputStream对象为参数。方法则有两个read()Ҏ(gu)Q分别读一个字W、读数据入字节数l中的一Dc(din)再是一个close()Ҏ(gu)。例7.6利用它来实现?jin)两上文件的q接。其中还使用?jin)ByteArrayOutputStreamQ用意是两个文件ƈ接的l果先在内存~冲Z暂存一下。这个例子允许目的的文g是两个源文g之一?br />  ?.6 FileCat.java
  import java.lang.System;
  import java.io.*;

  public class FileCat{
   public static void main(String args[]){
    SequenceInputStream seqIn;
    if(args.length!=3){System.out.println("Usage:java FileCat filesrc filesrc filedst");}
    else{
     try{
      FileInputStream f1=new FileInputStream(args[0]);
      FileInputStream f2=new FileInputStream(args[1]);
      seqIn=new SequenceInputStream(f1,f2);
      ByteArrayOutputStream byteArrayOut=new ByteArrayOutputStream();
      boolean eof=false;
      int byteCount=0;
      while(!eof){
       int c=seqIn.read();
       if(c==-1)eof=true;
       else{
        //读到的数据写入字节数组输出?br />        byteArrayOut.write((char)c);
        ++byteCount;
       }
      }
      FileOutputStream outStream=new FileOutputStream(args[2]);
      //数据写入文?br />      byteArrayOut.writeTo(outStream);
      System.out.println(byteCount+" bytes were read.");
      seqIn.close();
      outStream.close();
      byteArrayOut.close();
      f1.close();
      f2.close();
     }catch(FileNotFoundException ex){
      System.out.println("Cannot open source files.Please check if they"+
        "exists and allows freading.");
     }catch(IOException ex){
      System.out.println("IOexception occured!");
     }
    }
   }
  }

  7.7.2 Streamtokenizerc?br />
  q个cL用来构造词法分析器的。缺省情况下Q它可以识别数倹{字母以?qing)字W串。它的构造函数只有一个,以输入流(inputStream)对象为参数。本节我们给Z个例??.7)Qƈ介绍例子中出现的该类的部分方法?br />  ?.7 TokenIODemo.java?br />  1:import java.io.IOException ;
  2:import java.lang.System;
  3:import java.io.InputStreamReader ;
  4:import java.io.StreamTokenizer;
  5:import java.io.FileInputStream ;
  6:
  7:public class TokenIODemo{
  8: public static void main(String args[]) throws IOException{
    //从文件创入流
  9:  FileInputStream fileIn = new FileInputStream ("hello.c");
    //从字节流创徏字符?br />  10:  InputStreamReader inReader = new InputStreamReader (fileIn);
  11:  StreamTokenizer tokenStream = new StreamTokenizer (inReader);
    //讄注释风格
  12:  tokenStream.slashStarComments(true);
  13:  tokenStream.slashSlashComments (true);
    //识别行结束符;如果参数为假Q将行结束符视作I白W?br />  14:  tokenStream.eolIsSignificant (true);
    //讄引号的符可C?br />  15:  tokenStream.quoteChar ('"');
    //ASCII码ؓ(f)0-32的字W设为空白符
  16:  tokenStream.whitespaceChars (0,32);
  17:  boolean eof = false;
  18:  do{
  19:   int token = tokenStream.nextToken ();
  20:   switch(token){
      //文gl束W?br />  21:   case tokenStream.TT_EOF :
  22:    System.out.print(" EOF ");
  23:    eof=true;
  24:    break;
      //行结束符
  25:   case tokenStream.TT_EOL :
  26:    System.out.print (" EOL ");
  27:    break;
      //单词
  28:   case tokenStream.TT_WORD :
  29:    System.out.print (" Word "+tokenStream.sval );
  30:    break;
      //数字
  31:   case tokenStream.TT_NUMBER :
  32:    System.out.print(" Number "+tokenStream.nval );
  33:    break;
  34:   default:
  35:    System.out.print(" "+(char)token);
  36:   }
  37:  }while(!eof);
  38:  System.out.flush();
  39: }
  40:}
  下面是该例的q行l果Q?br />  E:\>java TokenIODemo
  # Word include < Word stdio.h > EOL EOL Word main ( ) { EOL Word print ( " ,
Number 1234.0 ) ; EOL EOL } EOL EOF
  E:\>
  其中Qhello.cE序的源代码如下Q?br />  #include <stdio.h>
  //To say "hello world"
  main(){
   print("hello world %d\n",1234);
   /* It is a test for TokenIODemo*/
  }
  例子中我们用C(jin)q样一些方法:(x)
  ■public void whitespaceChars(int low,int hi)
  把给定范围的字符设ؓ(f)I格(不可?字符。类似的Ҏ(gu)q有wordChars()(设ؓ(f)单词字符)QordinaryChars()(讄为除?jin)单词字W、数据字W等有实际含义字W之外的其它字符)?br />  ■public void slachStarComments(boolean flag)
  ■public void slachSlashComments(boolean flag)
  flag为真Q则可训别相应风格的注释。前?slashStar)指E风格的注?/*...*/)。后者指C++风格的注释?/”?br />  ■public int nextToken()
  从输入流取得下一个词法分析单位?br />  ■public void eolIsSingnificant(boolean flag)
  如果参数为真Q识别行l束W;否则Q将行结束符视作I白W?br />  例子中还用到?jin)一些常量和变量。TT_EOF、TT_EOL、TT_NUMBER、TT_WORD分别表示文gl束W、行l束W、数值和单词。public String sval是指字符串|public double nval指双_ֺ倹{这些常量、变量的使用在例子中已有明确的演C,q里׃多说?jin)?br />
  7.7.3 FilenameFilter接口

  q个接口不太常用Q只提供?jin)一个方法:(x)
  ■public abstract boolean accept(File dir,String fileName)
  功能是确定某一文g列表是否包含?jin)指定的文g?br />
  7.7.4 Serializable接口

  实现q一接口的类可以被“串行化”,卛_们的对象可以被{化ؓ(f)某种形式Q该形式可以被输入输出,而保存对象的l构。也是_(d)只有实现?jin)这一接口Q类的对象才能被完整地输入输出和存储?br />  该接口不含Q何方法和变量Q它只充当一个标记。编E时只要在类定义时中上:(x)
  ... implements Serializable
卛_使该cȝ对象h“串行性??br />
本章结

  在这一章中Q我们比较全面地介绍?jin)java.io包中的类和接口,q给Z(jin)CZ。读者通过q一章学?fn),应掌握java的输入输出类Qƈ种I/O手段灉|q用于自~的E序之中?br />


I空 2006-09-28 10:41 发表评论
]]>
JAVA全方位学?/title><link>http://m.tkk7.com/spark/archive/2006/09/28/72493.html</link><dc:creator>I空</dc:creator><author>I空</author><pubDate>Thu, 28 Sep 2006 02:33:00 GMT</pubDate><guid>http://m.tkk7.com/spark/archive/2006/09/28/72493.html</guid><wfw:comment>http://m.tkk7.com/spark/comments/72493.html</wfw:comment><comments>http://m.tkk7.com/spark/archive/2006/09/28/72493.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/spark/comments/commentRss/72493.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/spark/services/trackbacks/72493.html</trackback:ping><description><![CDATA[ <p>列出java语言的所有重?/p> <br /> <p>java 2全方位学?J2ME无线java应用开发?JAVA手机E序设计入门与应?<br />1、对于一般PCq_来说QJava的程序分成两大类Q一个是在PC的操作系l上通过JVM直接q行的Java ApplicationQ另一U是通过览器中附带的JVMq行的Java Applet?br />2?lt;applet code="要运行的class文g名称" width="昄的宽? height="昄的高?></applet>?br />3、javac,java,appletviewer?br />4、java是用unicode作ؓ(f)字符集的Q所以我们在JavaE序中用中文或是英文甚x其他的语a作ؓ(f)class名称、变量名U都可以?br />5、JFC-java foundation classes,GUI-graphical uesr interface?br />6、java -jar Java2D.jar?br />7、PDA-个h数据处理。jpda-Java Platform Debugger Architecture?/p> <p>W??E序基本单元<br />8、关键字与保留字的区别。标志符的魔力。Literal的含义。变量的意义Q变量命名的原则?br />9、基本数据类型:(x)整型QQ点,其他cd?br />10、ؓ(f)什么数D围正负值分开Q无理数或是无穷数的表C问题。其核心(j)是精度问题。QҎ(gu)不存?q个数|所以会(x)产生误差?br />11、其他数据类型:(x)boolean,char,常用转义字符Q特D字W的表示Ҏ(gu)?br />12、Java两种变量的模式:(x)成员变量Qmember variableQ,局部变量(local variableQ。成员变量初始值在声明时就指定?jin)。而局部变量则不会(x)Q要求用戯p定初始倹{?br />13、类型{换分动类型{换(promotionQ和强制cd转换QcastingQ两U。其中每U又分ؓ(f)攑֤QwideningQ和~小QnarrowingQ两U。放大{换属于自动类型{换,~小转换属于强制cd转换?br />14、数据类型的后面加上一个英文字母,是由于Java对于literal默认的数据类型有养I基本上JavaҎ(gu)数的lieral默认为int型,而对于QҎ(gu)的literal默认为double型?br />15、Java里有个特D的c,可以像一般的基本数据cd一样用,它就是String-字符丌Ӏ?/p> <p>W??Java的表辑ּ<br />16?%2?%-2?5%2?5%-2的区别?br />17、比较运符的结果只有两U,true和flase。instanceof?<br />18、逻辑与和一般与的差别。在需要改变变量的值时Q用一般与。通常使用逻辑q算W,因ؓ(f)q算速度?x)快一些?br />19、逻辑q算的优先在比较运符之下?br />20、赋D符是所有运符中最低的。赋D符从右边运到左边。而算术运符是从左边q算到右辏Vƈ且赋D符的左边只能有一个变量存在?br />21、位q算W(bitwiseQ?&,|,^,~QcomplementQ。位q算W只能用于整型数据类型中。位U运(shiftQ的用处。位U运比较难。要理解位移q算的用途。了(jin)解减ơ运的含义。    ?<br />22、运符的优先和结合性?/p> <p>W??Java的语?br />23、语句有很多U,_略的把它们分ؓ(f)四类Q第一cL一般的语句Q第二类是声明语句,W三cL条g程控制语句Q第四类是@环控制语句?br />24、对象的声明与变量的声明是不同的。对象在声明后,必须q行实例化,而变量声明是不需要的?br />25?:q算W的使用?br />26、Switch的参数只能是(<byte、short、int或char变量>)的其中一U。?<br />27、for(<控制循环变量初始D|?gt;;<循环l束判断条g语句>;<控制循环变量值改变方?gt;){<代码>s}。千万不使用点C为控制变量。由于QҎ(gu)误差问题?br />28、while(<循环l束判断条g语句>){<代码>s}?br />29、do{<代码>s} while(<循环l束判断条g语句>)?br />30、高U@环控Ӟ嵌套循环。以?qing)break和continue的用?br />31、标?lt;token>的用。以冒号Q?作ؓ(f)l束。运用适当的break、continue和token可以增强E序的弹性。但不要qtoken?br />32、必M(jin)解注释语句、if语句、switch语句、@环语句、break、continue和标记的使用与限制?br />                                    <br />W??Java面向对象E序设计<br />33、对象是W合某种cd义所产生出来的实例(instanceQ。类是抽象的Q而对象是实在的。属性(attributeQ是用来形容一个实例对象的Q其实就是变量。方法(methodQ是对象自己的行为或者是使用它们的方法,其实是函数。属性和Ҏ(gu)UCؓ(f)对象的成员。类可以说是蓝图QblueprintQ,cM?x)定义许多生该cd象时Q所必须具备的一些属性与Ҏ(gu)?br />34、承(inheritanceQ和多态(polymorphismQ是cȝ另外两个重要的特性。承最主要的目的是Z(jin)"扩展"原类的功能、加强或改进原类所没有定义的属性及(qing)Ҏ(gu)。被l承的类为父c,l承的类为子cR采用UMLQUnified Modeling LanguageQ的表达方式来设计类Q可以画出类关系图,其中最重要的部件是cd标和l承图标。多态的概念比较隄解,需要加强理解,其中q有覆盖QoverrideQ的概念?br />35、ؓ(f)?jin)增强程序的可读性和易用性。全世界的javaE序师都遵守以下的规则:(x)Q?QPackageQ包Q,作ؓ(f)Package名称的英文单词全部要写Q(2Q类Q每个英文单词的W一个字母大写;Q?Q接口,规则与类一PQ?Q属性,每个英文单词的第一个字母小写,其他单词的第一个英文字母大写;Q?Q方法,规则和属性一P不过后面有小括号Q(7Q常量,英文单词全部大写Q而且每两个英文单词之间用下划UK开?br />36、Animal和Zoo两个cd需要对Zoo.javaq行~译卛_。这是因为在Zoo.java中所有用到的cd果还没有q行q编译的话,在编译Zoo.java的过E中它们都会(x)被自动编译?br />37、构造函敎ͼconstuctorQ,除了(jin)可以在Java~译时ؓ(f)我们自动产生之外Q还可以自行~写所需要的构造函数。构造函C是一个方法?br />38、在一个类中,有多个构造函C用相同的名称Q但是参数类型与个数却各不相同,我们把这L(fng)一个行为称为构造函数重载(overloadingQ?br />39、原则上重蝲有两个规则一定要遵守Q一、方法名UC定要一栗否则的话,是两个不同的方法,不能UCؓ(f)重蝲。二、调用的参数cd一定要不一栗因为编译器要通过参数cd来判断调用的是哪一个方法?br />40、面向对象程序设计中一个非帔R要的概念Q我们称Z息的隐藏Qinformation hiddingQ,专用的技术术语ؓ(f)装QencapsulatioQ。封装的目的有两个:(x)一、保护类中的数据Q不让这些数据被错误的用或破坏Q二、隐藏不需要让别h知道的细节,以防别h误用。封装还有一些其他的重要的特点:(x)隐藏cȝ具体l节Q强制用户通过单一接口讉K数据Q程序更加容易维护?br />41、属性访问方法的命名规则Q设|属性值的Ҏ(gu)以set作ؓ(f)开_(d)获取属性值的Ҏ(gu)以get作ؓ(f)开_(d)Boolean数据cd值的获取用isXXX形式来命名?br />42、类的多态的Q指cd不同情况下,可以看作是不同的cR?br />43、类成员和实例成员。前面介l的属性和Ҏ(gu)Q属于对象等U的Q称为实例成员。类成员必须使用限定词static。类成员的调用方法ؓ(f)<cdU?gt;.<cL员名U?gt;Q也可以?lt;对象名称>.<cL员名U?gt;。但是类Ҏ(gu)中不能用实例成员?br />44、子cM生对象时Q会(x)往上通知它的父类Q它的父cd?x)通知父类的父c,持箋q个操作直到最上层的java.lang.ObjectcR通知上层父类最主要的目的时Q对于那些承自父类的属性或其他的设|做初始化的操作。从而达?E序代码的重复用,q也是承的目的。Java在编译时自动帮我们加上通知父类的程序代码,是加在构造函数里面。super();q行的意思必L白。super是关键字?br />45、调用super函数必须注意两点Q一、super调用必须在构造函数的W?行。二、如果子cM有好几个不同的构造函敎ͼ二父cd没有不需要参数的构造函敎ͼ那么必d子类中的每个构造函数的W一行加上适当的super调用?br />46、构造函数调用构造函数用thisq个关键字?br />47、super和this在用上有一些要注意的地方:(x)一、super和this只能使用在构造函数程序代码中的第一行;二、super和this同时只能使用一U;三、super和this的调用只能用在构造函CQ四、如果构造函C没有使用super或thisQ那么Java?x)自动帮你加上super()调用?br />48、屏?shadow)Q属性(l承关系Q、覆?override)Q方法(l承关系Q、重?overload)Q方法(同一个类下函数同名,但参C同)(j)。用属性的几种Ҏ(gu)必须?jin)解Qsuper、this、强制类型{换的使用?/p> <p>W??深入Java面向对象E序设计<br />49、什么是?package)Q包很像我们计算Z的目录或是文件夹。目录分隔符Qdos用\Qunix?。目录机制应用于Java面向对象的程序当中就是所谓的包?br />50、package语句中,原本的目录分隔符改用句点[.]来代ѝpackage <package名称>;必须注意Qpackage语句一定只能写在程序代码的W一行。package的UML囄。除?jin)每一个类的Java文g中的W一行设|package外,E序代码中用到其他类的地方也一q加上它的package的名U。package的设|与使用?br />51、import语句Q必d在package语句之后Q所有类声明之前。import语句的通配W?*)。用通配W只是将该package下的cimportq来Q不?x)把子目录下的其他目录中的类importq来?br />52、classpath的设|。classpath是JavaE序在编译与q行时会(x)使用到的一个【环境变量】,它的主要用途是告诉~译器去哪里扑ֈ~译或运行时所需要的cRwindows默认情况下classpath为?】。设|classpath的两U方法:(x)一、直接设|;二、javac加上-classpathq个参数?br />53、访问权限的限定词的使用。protected与default的用。成员限定词有四个,而类声明限定词只有两个?br />54、final限定词的使用Q用于常量。final和static的用?br />55、抽象类的用。关键字是abstract。能让承的子类一定覆盖某个特D的Ҏ(gu)Q这U机制就是【抽?abstract)】。在一个类中,我们可以指定某个Ҏ(gu)为抽象的Q而一个抽象的Ҏ(gu)不需要编写方法的内容Q也是说当Ҏ(gu)声明完后Q就直接以分受;】来l束Q不用加上左叛_括号。只要有M一个抽象方法,那么q个cd必须成ؓ(f)一个抽象类Q所以我们必Lcȝ声明加上abstractq个关键字。抽象类不能生成对象实例。abstract只能用在cdҎ(gu)上。属性和变量上没有意义?br />56、接口-一U标准、一些规范。在java中,接口是由一些常量和抽象Ҏ(gu)所l成的。关键字是【interface】,使用的格式如下:(x)<限定?gt;interface<接口名称>[extends<接口名称>s]。解决abstract不能解决的问题。接口中Ҏ(gu)的语法声明跟抽象Ҏ(gu)的语法声明是一L(fng)Q就是是只有Ҏ(gu)的声明,而没有方法本w,单的说就是声明完后直接以分号l束整个语句Q而不用再加上大括受接口中的方法也都全部是抽象Ҏ(gu)Q只是不需要额外加上abstractq个关键字。extends <cd>Qimplements <接口?gt;。简单的_(d)接口是一个完全抽象的cRJava用多重接口的Ҏ(gu)来完成类的多重承机制。implements<接口1>,<接口2>......。java中存在一U特D的接口Q它只有接口的声明,而内部是I的Q也是说完全没有Q何的帔R和方法的声明。这U特D大额接口称为【标记接?marker interface)】?/p> <p>W??Objectcȝ常用Ҏ(gu)介绍<br />57、对象之间的比较Q第一U观点,对象相等是指对象为同一个。包括用的内存。直接用==。第二种观点Q是两个对象的内Ҏ(gu)否相{。用equalsҎ(gu)?br />58、理解hash code的含义?br />59、引?reference)与复?clone)的区别。cloneҎ(gu)的用?br />60、将对象转ؓ(f)字符的方法【toString】?br />61、在设计的类的时候,最好也一q的把这几个Object的方法覆盖?/p> <p>W?0?深入内存<br />62、变量内存的使用Q变量声明后Q编译器分配了(jin)内存?br />63、对象内存的使用Q对象声明后Q编译器只是在内存中产生一个对象的引用(reference)Q它所存放的ƈ不是一个真正的对象实例 Q因为对象的实例我们q没生成。所以当一个对象被声明后,在内存中q个对象引用的初始g(x)是【null】。我们用newq个关键字,配合调用cȝ构造函敎ͼ来生成对象实例。但Q此时对象引用与对象实例q没有生关联。需要用复制语句它们兌。每个对象引用占?个字节的内存I间。对象的引用所存放的是撒对象实例真正在内存中的地址。对象引用实际占用的内存大小Q跟pȝQJVMQ实现的Ҏ(gu)有关Q不同的pȝ大小不一定相同?br />64、什么是数组Q数l是存放量大、性质相同且需要做相同处理的数据。数l可以用在基本数据类型的变量上,当然也可以用在对象上。数l与对象有点怼Q分成两个阶D——数l引用的声明和数l实例的生成。数l声明格式如?int a[];和int []a;数组声明完后Q在内存中表现的Ҏ(gu)也跟对象一P也是个引用,而且初始g是null。生成数l实例同栯用到new关键字,在这之后要用赋D句进行关联处理。也可以同时创徏和初始化数组Q如 int a[]={1,2,3,4}?br />65、数l的索引(index)Q是[]里面的数字,它表C个数l中的第几笔数据。数l的使用比较单,是在数l变量的名称后,加上要访问的索引。烦(ch)引从0开始到数组的大减1?br />66、数l的length属性获得数l的大小。必L意数l的大小是不能改变的。用上比较有弹性?br />67、数l的复制。数l不是承自java.lang.Objectcȝ对象Q所以没有cloneq个用来复制对象实例的方法。可以利用@环赋值来实现。java中提供了(jin)【System.arraycopy】方法。用这个方法时需?个参敎ͼ依次是源数组、来源数l数据v始位|、目的数l、目的数l数据v始位|、复制数据的个数。用上比较有弹性。arraycopyҎ(gu)只适用于基本数据类型的数组。相比而言Q第二种Ҏ(gu)使用JNI的方法,所以速度上会(x)比较快。arraycopy的三U异常,NULLPointerExceptionQArrayIndexOutOfBoudsExceptionQArrayStroeException?br />68、Java 本机接口QJava Native Interface (JNI)Q是一个本机编E接口,它是 Java 软g开发工L(fng)QJava Software Development Kit (SDK)Q的一部分。JNI 允许 Java 代码使用以其它语aQ譬?C ?C++Q编写的代码和代码库。Invocation APIQJNI 的一部分Q可以用来将 Java 虚拟机(JVMQ嵌入到本机应用E序中,从而允许程序员从本Z码内部调?Java 代码?<br />预备知识 <br />所有示例都是?Java、C ?C++ 代码~写的,q可以移植到 Windows 和基?UNIX 的^C。要完全理解q些CZQ?zhn)必须有一?Java 语言~程l验。此外,(zhn)还需要一?C ?C++ ~程l验。严格来_(d)JNI 解决Ҏ(gu)可以分成 Java ~程d?C/C++ ~程dQ由不同的程序员完成每项d。然而,要完全理?JNI 是如何在两种~程环境中工作的Q?zhn)必须能够理?Java ?C/C++ 代码?<br />pȝ需?<br />览器:(x)Netscape 4.x 或更高版? 或?Internet Explorer 4.x 或更高版?Q支?JavaScript ?要运行本教程中的CZQ?zhn)需要下列工具与lgQ?Java ~译器:(x)?SDK 一h供的 javac.exe?Java 虚拟机(JVMQ:(x)?SDK 一h供的 java.exe?本机Ҏ(gu) C 文g生成器:(x)?SDK 一h供的 javah.exe?定义 JNI 的库文g和本机头文g。jni.h C 头文件、jvm.lib ?jvm.dll ?jvm.so 文gQ这些文仉是随 SDK 一h供的?能够创徏׃n库的 C ?C++ ~译器。最常见的两?C ~译器是用于 Windows ?Visual C++ 和用于基?UNIX pȝ?cc?br />68、多l数l在内存中的样子。必ȝ解。不规则数组的生成?不规则数l是Java语言的一个重要特点,其他的程序语a像C或是BasicQ都只能声明规则的多l数l,而且l数有上限。java没有q个限制?br />69、以上讨论基本数据类型的数组Q现在来看对象数l。防止NullPointerException异常的生?br />70、变量的讉K范围【scope】,有点像类之间属性及(qing)Ҏ(gu)讉K的限Ӟq些限制是由于访问权限的限定词、package和承这几种关系l合h的。变量访问范围大致分为四个等U:(x)W一、类U?static)Q第二、对象实例Q第三、方法Q第四、局域。怎么样区分这几个U别Q必L意。必ȝ解这四个{。访问范围和视野的关pd好相反。内存存在的旉?br />71、参数的传递。以前的E序语言概念参数的传递有两种Ҏ(gu)Q一是【传?call by value)】,另一个是【传址(call by reference)】。但java里面只有传DU方式。基本数据类型参数g递与cd象型参数g递是不同的?br />72、内存回?garbage collection)。负责运行这个机制的是【garbage collector】。对象声明包括两部分Q对象引用和对象实例。如果一个对象实例不被Q何对象引用指到的话,但启动GCӞ׃(x)把对象实例回收回去,q把内存释放调。取消对象引用,只要它指定为【null】即可。GC是不定时的启动,也可以手动调用它Q方法是【System.gc()】,它会(x)调用【Runtime.getRuntime.gc()】,q两个方法都可以使用。finalizeҎ(gu)同样也是Objectcd用的一个方法,与GC有关。它是在对象被回收前QGC所调用的方法。回攉序与对象实例的生成顺序有兟뀂既是我们手动调用System.gc()QGC也不见得一定运行,GC正确的启动时间无法得知。                                                                                                                              ?<br />W?1?Application与Applet<br />73、Application的输出,Systemcȝout属性是PrintStream对象Q有prinlinҎ(gu)和printҎ(gu)Q也可以用err属性是PrintStream对象Q有prinlinҎ(gu)和printҎ(gu)Q但有区别,out属性可以重定向(redirected)Qerr属性只能输出到默认的设备上。Application默认的就是所打开的命令行H口QApplet默认的就是Java Console?可以?gt;来实现重定向。println和printҎ(gu)都是属于重蝲的方法,除了(jin)可以接受八种基本数据cd和Stringcd作ؓ(f)参数外,q可以接受一般的对象作ؓ(f)参数Q编译器?x)自动调用这个对象的【toString】方法,char数组也可以作两个Ҏ(gu)的参数?br />74、Application的输入,分ؓ(f)两种Q一是参数输入(命o(h)行参敎ͼ(j)QW(xu)rappercȝ使用。基本数据类型与Wrappercȝ对应关系。Wrappercȝ有相应的parseXXXҎ(gu)来实现字W串转换为基本数据类型。二是标准输入,Systemcȝin属性是InputStream对象Q有readҎ(gu)来读取输入,读进来是byte对类型,需要{化ؓ(f)其他cL据型。通常使用InputStreamReaderc,然后q接到BufferedReaderc,用BufferedReadercL供的d字符串的Ҏ(gu)【readLine】?br />75、系l参数的获取用【System.getProperties】方法。必L意系l参C命o(h)行参数的区别?br />76、Systemcȝ使用。setXXX(setOut、setErr、setIn)QsetProperties和SetProperty的区别。System.exit(n)Q虚拟机?x)调用Runtime.getRutime.exit(n)Ҏ(gu)。currentTimeMills?br />77、Runtimecȝ使用。可以通过execq个Ҏ(gu)来运行一个外部程序?br />78、Appplication必须有一个main的方法,W合四个条g。而一个Applet一定要l承java.applet.AppletcRmainҎ(gu)是Applicationq行的v始点Q而Appletq行的v始点在initҎ(gu)上。Applet中,System.out或System.errҎ(gu)来输出,但System.inҎ(gu)不能用。Applet有自q输入方式Q类g命o(h)行参数的方式。在HTML文g中,加上参数语法Q?lt;param name=<参数名称> value=<参数?gt;>。然后在javaE序中,应用java.applet.Appletcȝ【getParam】方法?br />79、Applet基本Ҏ(gu)的用。init、start、stop、destroy、paint。destroy和finalizeҎ(gu)的区别在于用地点不同。paintҎ(gu)的用。paintҎ(gu)中有个属性是Graphics对象Q注意Graphicscȝ【drawString】方法的使用?br />80、java的安全性,是指Applet满java指定的重重安全规范。四炚w制措施?<br />81、Application和Applet的结合。Java Web Start是取代Applet的机制?/p> <p>W?2?异常处理<br />82、异常是指程序在q行的过E中Q由于编写程序的倏忽Q外在环境的因素Q或是电(sh)脑系l本w的问题Q都可能DE序q行时生错误,造成L或是计算的结果不正确Q这些突发的状况UCؓ(f)异常?异常处理是指当程序出现异常时Q能够作Z些应变的处理?br />83、java.lang.ThrowablecRExceptionc(可以控制Q和Errorc(无法控制Q?br />84、RuntimeException常见的有以下几种QArithmeticException、ArrayIndexOutOfBoundsException、ArrayStoreException、ClassCastException、IllegalArgumentException、NativeArraySizeException、NullPointerException、SecurityException。由于自qE引L(fng)?br />85、CheckedException常见的有以下几种QClassNotFoundExecption、FileNotFoundException、InterrupedException、IOException、SQLException。一些外部因素引L(fng)?br />86、Error有OutOfMemoryError、StackOverflowError、UnknowError、AWTError、ThreadDeath。系l且非怸重的错误。错误原因是内存不或者是q行时挂赗?br />87、捕捉和处理异常。主要是针对CheckedExceptioncȝ异常。try、catch、finally三个关键字的使用。处理异常包括以下两个步骤:(x)一、把异常的名U及(qing)一些相关的信息昄出来Q二、用最安全的方法恢复程序的q行。显C异怿息用刎ͼtoString、getLocalizedMessage、getMessage、printStackTraceҎ(gu)。其中printStackTraceҎ(gu)有三U不同的重蝲。弹?flexibility)?finally关键字的使用注意以下三点Q一、没有异生-》进finally区块Q》方法中剩下未运行的E序代码。二、有异常产生Q》捕捉到Q》进catch区块Q》finally区块Q》方法中剩下未运行的E序代码Q三、有异常产生Q》没有捕捉到Q》进finally区块Q》方法中剩下未运行的E序代码。                  ?<br />88、注意异常捕捉的序。越上层的类Q越攑֜下面?br />89、throws关键字的使用Q在Ҏ(gu)声明上抛出异常。throw关键字,在方法内部抛出异常。必L意抛出RuntimeException和CheckedException两种异常在用上的差别?br />90、定义自qException?br />91、抛出异常方法覆盖的问题。注意两点:(x)一、不可抛出原有方法抛出异常类的父cL上层c;二、抛出的异常cL目不能笔原有的方法抛出的q多。主要是因ؓ(f)~译时抛出的异常cL法自动{化ؓ(f)父类中所声明的异常类?/p> <p>W?3?容器(Container)与布局(Layout)<br />92、什么是AWT(Abstract Windowing Toolkit)Q什么是GUI(Graphical User Interface)囑Ş用户接口。AWT包的l构图?br />93、Container包括F(xin)rame和Panel。Frame是先构造,然后setSizeQ然后再setVisible。理解Deprecation。Frame的常用方法。记住【Ctrl】+【C】来停止E序的方法。Panel不能独立出现在画面上Q必L在某个Container中才行,例如Frame或浏览器里面。Applet本n是一个panel。addҎ(gu)的用?br />94、什么是Layout。【setLayout(<xxxLayout>)】方法。有五个基本的LayoutcRFrame默认的布局是BorderLayoutcRPanel默认的布局是FlowLayout。另外还有CardLayout、GridLayout、GridBagLayout。也可以设计自己的LayoutcR?br />95、pack和setSizeҎ(gu)的区别。                                                    ?<br />96、如果不使用LayoutQ可以用【setSize】和【setLocation】方法来代替。最好用LayoutcR                                                                                     ?<br />W?4?事g处理<br />97、什么是事g【event】。事件就是别人给予它的一些操作。明白事件处理结构:(x)事g本n、事件生的来源、谁来处理事件?br />98、什么是委托处理模式【Delegation Model】。事件处理的机制?br />99、AWT Eventcȝl构图。分Zc:(x)LowQlevel和senmantic?br />100、【Listener】这个接?interface)与【Adapter】类的相对应?br />101、一个对象可以委托好几个cL处理相同的事Ӟ一个处理事件的cM可以同时处理不同对象所产生的事件。这U情늧为【multiplexer】?br />102、WindowEvent、MouseEvent、KeyEventcM件处理的接口Q类和方法。以?qing)其他常用的LowQlevel Eventc,分别是ContainterEvent和FocusEvent。                          ?<br />103、Swing是Java所设计的另外一l更丰富、功能更多的GUII间。理解Swing和AWT的区别?/p> <img src ="http://m.tkk7.com/spark/aggbug/72493.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/spark/" target="_blank">I空</a> 2006-09-28 10:33 <a href="http://m.tkk7.com/spark/archive/2006/09/28/72493.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java初学者备忘录http://m.tkk7.com/spark/archive/2006/09/28/72492.htmlI空I空Thu, 28 Sep 2006 02:32:00 GMThttp://m.tkk7.com/spark/archive/2006/09/28/72492.htmlhttp://m.tkk7.com/spark/comments/72492.htmlhttp://m.tkk7.com/spark/archive/2006/09/28/72492.html#Feedback0http://m.tkk7.com/spark/comments/commentRss/72492.htmlhttp://m.tkk7.com/spark/services/trackbacks/72492.html

 一.异常

  Java对异常的处理同Delphi一?不是L的去避免它的发生,而是{它发生后去补救.

  Delphi的异常处理简单来说就是一下语?

Try
Except//异常发生后就转入此处执行
Finally//不管异常发不发生Q都转入此处q行
End

  与此相类|Java的异常处理的基本形式如下

try{
}catch(ExceptionType1 e){
file&://?异常情况1的处?
}catch(ExceptionType2 e){
file&://?异常情况2的处?
throw(e)//抛出异常,和Delphi中的raise是一回事
}

  要补充的?对大多数的异?假如你要在正常运行的E序中而不是捕捉异常的E序中明的抛出,Java的编译器需要你事先对你要抛出的异常作声明,否则不允许编译通过.q个d是由throws来完成的.

  ?Java的输入输出流

  2.1 输出

System.out.print  file&://q?里out是一个静(rn)态方法哦
System.out.println
System.err.print  file&://err/和out一样也是标准输?至于有什么不?我目前还不清?
System.err.println

  2.2 输入

System.in.read()

  2.3 文g的操?

  只需要几个带注释的例子就可以?jin)?

  W一个是一个显C文件基本信息的E序

import java.io.*;//调入和io相关的类
class fileinfo{
file&://??main函数一定是?rn)态方?

 public static void main(String args[])throws IOException{
  File fileToCheck;//使用文g对象创徏实例
  if (args.length>0){
   for (int i=0;i
    fileToCheck=new File(args[i]);//为文件对象分配空?
    info(fileToCheck);//q里引用的info一定要是静(rn)态方法成?
   }
  }
  else{
   System.out.println("no file given");
  }
 }

 public static void info(File f)throws IOException{
  System.out.println("Name:"+f.getName());
  System.out.println("Path:"+f.getPath());
  if (f.exists()){
   System.out.println("File exists.");
   System.out.print((f.canRead()?" and is Readable":""));//判断函数Q如果满xӞ输出前者,否则输出后?
   System.out.print((f.canWrite()?"and is Writable":""));
   System.out.print(".");
   System.out.println("File is"+f.length()+"bytes.");
  }
  else{
   System.out.println("File does not exist.");
  }
 }
}


  W二个例子是一个存储电(sh)话信息的程?用户输入姓名和电(sh)话号?E序其存入phone.numbers文g中,通过FileOutputStream来实?

import java.io.*;

class phones{
 static FileOutputStream fos;
 public static final int lineLength=81;
 public static void main(String args[])throws IOException{
  byte[] phone=new byte[lineLength];
  byte[] name=new byte[lineLength];
  int i;
  fos=new FileOutputStream("phone.numbers");
  while(true){
   System.err.println("Enter a name(enter ‘done?to quit)");
   readLine(name);
   if ("done".equalsIgnoreCase(new String(name,0,0,4))){
    break;
   }
   System.err.println("Enter the phone number");
   readLine(phone);
   for (i=0;phone[i]!=0;i++){
    fos.write(phone[i]);
   }
   fos.write(??;
   for (i=0;name[i]!=0;i++){
    fos.write(name[i]);
   }
   fos.write(‘n?;
  }
  fos.close();
 }

 private static void readLine(byte line[])throws IOException{
  int i=0,b=0;
  while((i<(lineLength-1))&&((b=System.in.read())!=‘n?){
   line[i++]=(byte)b;
  }
  line[i]=(byte)(0);
 }
}
2.4 ?

  无非是两U?

  输出?让我们来写的

  输入?l我们来ȝ

  java.io包中有很多种cȝ输入输出:(x)

  1.FileInputStream和FileOutputStream 节点?

  2.BufferedInputStream和BufferedOutputStream qo(h)?

  3.DataInputStream和DataOutputStream 增强的过滤流

  4.PipedInputStream和PipledOutputStream 用于U程的流

  掌握?jin)流的概?可以开始Sockets的学?fn)?jin).关于Socket的作?昨天我已l讲?

  现在,我们创Z个简单的通讯E序,以获得对Socket的实质性的认识.该程序包括两个部?客户?RemoteFileClient)和服务器(RemoteFileServer).客户机向服务器发?gu)?要求d服务器上的文件信?服务器将响应h,相应的文g信息传给客户?相应的文g信息传给客户?

  首先我们创徏RemoteFileClientc:(x)

import java.io.*;//java.io 包提供对进行读写的工具,也是?TCP 套接字通信的唯一途径
import java.net.*;//java.net 包提供套接字工具?

public class RemoteFileClient {
  protected String hostIp;
  protected int hostPort;
  protected BufferedReader socketReader;//负责L据的对象
  protected PrintWriter socketWriter;//负责写数据的对象

  file&://c?的构造器有两个参敎ͼ(x)q程L?IP 地址(hostIp)和端口号(hostPort)各一?构造器它们赋l实例变?

  public RemoteFileClient(String aHostIp, int aHostPort) {
    hostIp = aHostIp;
    hostPort = aHostPort;
  }
  public static void main(String[] args) {
  }
file&://q?接到q程服务?
  public void setUpConnection() {
  }
file&://?q程服务器请求文件信?
  public String getFile(String fileNameToGet) {
  }
file&://?q程服务器上断开
  public void tearDownConnection() {
  }
}


  首先来实现main()

public static void main(String[] args) {
  RemoteFileClient remoteFileClient = new RemoteFileClient("127.0.0.1", 3000);//Z(jin)方便调试Q我们把本地服务器当作远E服务器
  remoteFileClient.setUpConnection();//q接。不能直接用setUpConnectionQ因为它是非?rn)态变量,需要创建实例后Q对实例q行引用Q可以看我第一天的日记Q上面写的非常详l?
  String fileContents =
    remoteFileClient.getFile("RemoteFile.txt");//d

  remoteFileClient.tearDownConnection();//断开

  System.out.println(fileContents);//输出d内容
}


  步骤非常清楚.那么我们分别看连?d,断开是怎么实现?

  1.q接

public void setUpConnection() {
  try {
    Socket client = new Socket(hostIp, hostPort);//创徏Socket对象


     OutputStream outToServerStream=client.getOutputStream();
     InputStream inFromServerStream=client.getInputStream();
     socketReader = new BufferedReader(new InputStreamReader(inFromServerStream));
file&://?Socket的InputStream包装qBufferedReader 以我们能够d的?

     socketWriter = new PrintWriter(outToServerStream);
file&://?Socket的OutputStream包装qPrintWriter 以我们能够发送文件请求到服务?

  } catch (UnknownHostException e) {
    System.out.println("Error setting up socket connection: unknown host at " + hostIp + ":" + hostPort);
file&://?Socket对象创徏错误的异常处?
  } catch (IOException e) {
    System.out.println("Error setting up socket connection: " + e);
file&://?IO错误的异常处?
  }
}

  2.d

public String getFile(String fileNameToGet) {
  StringBuffer fileLines = new StringBuffer();//StringBuffer对象也是String对象Q但是比它更灉|Q这里是用来存放d内容?

  try {
    socketWriter.println(fileNameToGet);
    socketWriter.flush();//文g存放地址输出到socketWriter?然后清空~冲?让这个地址送到服务器中?


    String line = null;
    while ((line = socketReader.readLine()) != null)
      fileLines.append(line + "n");
file&://?然已l发送到服务器去?那我们都要等待响?q里的程序就是等待服务器把我们所需要的文g内容传过?
  } catch (IOException e) {
    System.out.println("Error reading from file&: " + fileNameToGet);
  }

  return fileLines.toString();//别忘?jin)把buffer中的内容转成String再返?
}

  3.断开

public void tearDownConnection() {
  try {
    socketWriter.close();
    socketReader.close();
  } catch (IOException e) {
    System.out.println("Error tearing down socket connection: " + e);
  }
}

  tearDownConnection() Ҏ(gu)只别关闭我们?Socket ?InputStream ?OutputStream 上创建的 BufferedReader ?PrintWriter。这样做?x)关闭我们?Socket 获取的底层流Q所以我们必L捉可能的 IOException

  ?现在可以ȝ一下客hE序的创建步骤了(jin)

  1.用要q接的机器的IP端口号实例化SocketQ如有问题则抛出 ExceptionQ?

  2.获取 Socket 上的以q行d.

  3.把流包装q?BufferedReader/PrintWriter 的实?

  4.?Socket q行d.具体说来,是在Writer上传送文件地址信息l服务器,在Reader上读取服务器传来的文件信?
5.关闭打开的流?

  下面是RemoteFileClient 的代码清?

import java.io.*;
import java.net.*;

public class RemoteFileClient {
  protected BufferedReader socketReader;
  protected PrintWriter socketWriter;
  protected String hostIp;
  protected int hostPort;

  public RemoteFileClient(String aHostIp, int aHostPort) {
    hostIp = aHostIp;
    hostPort = aHostPort;
  }
  public String getFile(String fileNameToGet) {
    StringBuffer fileLines = new StringBuffer();

    try {
      socketWriter.println(fileNameToGet);
      socketWriter.flush();

      String line = null;
      while ((line = socketReader.readLine()) != null)
        fileLines.append(line + "n");
    } catch (IOException e) {
      System.out.println("Error reading from file&: " + fileNameToGet);
    }

    return fileLines.toString();
  }
  public static void main(String[] args) {
    RemoteFileClient remoteFileClient = new RemoteFileClient("127.0.0.1", 3000);
    remoteFileClient.setUpConnection();
    String fileContents = remoteFileClient.getFile("RemoteFile.txt");
    remoteFileClient.tearDownConnection();

    System.out.println(fileContents);
  }
  public void setUpConnection() {
    try {
      Socket client = new Socket(hostIp, hostPort);

      OutputStream outToServerStream=client.getOutputStream();
      InputStream inFromServerStream=client.getInputStream();
      socketReader = new BufferedReader(new InputStreamReader(inFromServerStream));
      socketWriter = new PrintWriter(outToServerStream);

    } catch (UnknownHostException e) {
      System.out.println("Error setting up socket connection: unknown host at " + hostIp + ":" + hostPort);
    } catch (IOException e) {
      System.out.println("Error setting up socket connection: " + e);
    }
  }
  public void tearDownConnection() {
    try {
      socketWriter.close();
      socketReader.close();
    } catch (IOException e) {
      System.out.println("Error tearing down socket connection: " + e);
    }
  }
}

  好了(jin),现在来看服务器端的程序怎么?

  创徏RemoteClientServerc:(x)

import java.io.*;
import java.net.*;

public class RemoteFileServer {
  protected int listenPort = 3000;
  public static void main(String[] args) {
  }
  public void acceptConnections() {
  }
  public void handleConnection(Socket incomingConnection) {
  }
}

  跟客h中一P首先导入 java.net ?java.io。接着,l我们的cM个实例变量以保存端口,我们从该端口侦听q入的连接。缺省情况下Q端口是 3000?

acceptConnections()允许客hq接到服务器
handleConnection()负责与客h Socket 交互以将(zhn)所h的文件的内容发送到客户机?

  首先看main()

public static void main(String[] args) {
  RemoteFileServer server = new RemoteFileServer();
  server.acceptConnections();
}

  非常?因ؓ(f)d数无非是让服务器q入监听状?所以直接调用acceptConnection().需要注意的?必须先创建RemoteFileServer()的实?而不是直接调?

  那么服务器是怎样通过acceptConnection()来监听客h的连接呢Qƈ且如果兼听到?jin),又怎样处理呢?我们来看

public void acceptConnections() {
  try {
    ServerSocket server = new ServerSocket(listenPort);//同客h的Socket对应,在服务器?我们需要ServerSocket对象,参数是兼听的端口?
    Socket incomingConnection = null;//创徏一个客L(fng)的Socket变量,以接收从客户端监听到的Socket
    while (true) {
      incomingConnection = server.accept();//调用?ServerSocket ?accept() 来告诉它开始侦?
      handleConnection(incomingConnection);
    }
file&://?断监听直到来?jin)一个连接请?然后交由handleConnection处理
  } catch (BindException e) {
    System.out.println("Unable to bind to port " + listenPort);
  } catch (IOException e) {
    System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);
  }
}

  无论何时如果创徏?jin)一个无法绑定到指定端口Q可能是因ؓ(f)别的什么控制了(jin)该端口)(j)?ServerSocketQJava 代码都将抛出一个错误。所以这里我们必L捉可能的 BindException。同Ӟ与在客户机端上时一P我们必须捕捉 IOExceptionQ当我们试图?ServerSocket 上接受连接时Q它?yu)׃?x)被抛出。可以通过用毫U数调用 setSoTimeout() 来ؓ(f) accept() 调用讄时Q以避免实际长时间的{待。调?setSoTimeout() accept() l过指定占用旉后抛?IOException

  最关键的处理在handleConnection()中,q时已经q接C(jin)客户端的SocketQ要从该Socket中读取客L(fng)的请求ƈ且响应?

public void handleConnection(Socket incomingConnection) {
  try {
    OutputStream outputToSocket = incomingConnection.getOutputStream();
    InputStream inputFromSocket = incomingConnection.getInputStream();

file&://?先获取同Socket相关联的outputToSocket和InputStream
file&://?中outputToSocket是要q回l客L(fng)Socket的流
file&://InputStream/是客L(fng)发来的请?在这里就是文件\??RemoteFile.txt"

    BufferedReader streamReader =
      new BufferedReader(new InputStreamReader(inputFromSocket));

file&://?先要InputStream转换到BufferedReader?

    FileReader fileReader = new FileReader(new File(streamReader.readLine()));
file&://?BufferedReader中读出文件\?建立新对象FileReader

    BufferedReader bufferedFileReader = new BufferedReader(fileReader);

file&://?ơ徏立BufferedReader对象Q这一ơ它d得是文g里面的内?

    PrintWriter streamWriter =
      new PrintWriter(OutputStream);

file&://?Socket的outputToSocket包装进PrintWriter 以我们能够发送文件信息到客户?

    String line = null;
    while ((line = bufferedFileReader.readLine()) != null) {
      streamWriter.println(line);
    }
file&://?bufferedFileReader中读出文件信息,再经由streamWriter输出到客L(fng)

    fileReader.close();
    streamWriter.close();//注意Socket的两个流关闭的顺?
    streamReader.close();
file&://?成之后关闭所有流

  } catch (Exception e) {
    System.out.println("Error handling a client: " + e);
  }
}


  h意完成所有操作之后关闭流的顺序,streamWriter的关闭在streamReader的关闭之前。这不是偶然?假如关闭次序颠倒过?客户端将不会(x)获取CQ何文件信?你可以调试一下看?q是Z么呢?原因是如果你在关?streamWriter 之前关闭 streamReaderQ则你可以以往 streamWriter中写M东西Q但没有M数据可以通过通道Q通道被关闭了(jin)Q?但奇怪的?我不是已l在之前的streamWriter.println()中输Z(jin)?N非要{到所有的关闭之后输出到客户端的信息的东西才能到?我试着?

streamWriter.close();
streamReader.close();

  屏蔽掉,看是否依然能够实现正常的通信,l果发现不行,E序L.可能是因为通道没有闭合D?那么臛_可以说明,只有通道按某U顺序正常关?才能完成通讯数据的传?否则客户端收不到信息.

  最后依然是ȝ一下创建服务器端程序的步骤

  1.用一个你惌它侦听传入客hq接的端?比如E序中的3000)来实例化一?ServerSocketQ如有问题则抛出 ExceptionQ?

  2.循环调用ServerSocket的accept()以监听连?

  3.获取客户端的Socket以q行d操作

  4.包装?

  5.对客L(fng)的Socketq行d

  6.关闭打开的流(切记,永远不要在关?Writer 之前关闭 Reader),完成通信

  下面?

RemoteFileServer 的代码清?

import java.io.*;
import java.net.*;

public class RemoteFileServer {
  int listenPort;
  public RemoteFileServer(int aListenPort) {
    listenPort = aListenPort;
  }
  public void acceptConnections() {
    try {
      ServerSocket server = new ServerSocket(listenPort);
      Socket incomingConnection = null;
      while (true) {
        incomingConnection = server.accept();
        handleConnection(incomingConnection);
      }
    } catch (BindException e) {
      System.out.println("Unable to bind to port " + listenPort);
    } catch (IOException e) {
      System.out.println("Unable to instantiate a ServerSocket on port: " + listenPort);
    }
  }
  public void handleConnection(Socket incomingConnection) {
    try {
      OutputStream outputToSocket = incomingConnection.getOutputStream();
      InputStream inputFromSocket = incomingConnection.getInputStream();

      BufferedReader streamReader = new BufferedReader(new InputStreamReader(inputFromSocket));

      FileReader fileReader = new FileReader(new File(streamReader.readLine()));

      BufferedReader bufferedFileReader = new BufferedReader(fileReader);
      PrintWriter streamWriter = new PrintWriter(outputToSocket);
      String line = null;
      while ((line = bufferedFileReader.readLine()) != null) {
        streamWriter.println(line);
      }

      fileReader.close();
      streamWriter.close();
      streamReader.close();
    } catch (Exception e) {
      System.out.println("Error handling a client: " + e);
    }
  }
  public static void main(String[] args) {
    RemoteFileServer server = new RemoteFileServer(3000);
    server.acceptConnections();
  }
}



I空 2006-09-28 10:32 发表评论
]]>
վ֩ģ壺 Ƶ߹ۿ| ˬָ߳ˮƵ | ޾ɫ1314ݺ| ĻֻѿӰ| վѹۿ| ɫʹۺ߹ۿ| AVַ߹ۿ| ɫһ | Ʒþþþþþ| ŷaԴ| Ƭ߷ѹۿ | AVһɫ| պƷƵַ| Ʒ߹ۿ| ޾ƷۺϾþһ| ĻƵ| ޹Ʒþ| ߿ѹۿAVҹӰԺ| ߾Ʒһ| ƷҹѸ| 2018Ƶ| ޹Ʒ˾þ| ޾Ʒѿ| ˵þþþƷ| ŮڵƵվ| лGAYƬվWWW| AVô뾫Ʒ| **ʵһëƬaa| ޵һڶĵ| ѹԺ߹ۿ| 99REþþƷﶼǾƷ| պƷһAVۿ| ҳվ߿| ѹվ߹ۿͼ| ޹Ʒ| 91Ƶ߹ۿѴȫ| ݺݺݰƵ| þþþþAv뾫Ʒר| 69˾ƷƵ| ƷƬѿ | ղһ|