用代码打开FTP(2)

一、大数据量的ftp文件下载

  1.通过socket获取ftp服务器链接,并读取文件列表到本地文件

public void getFTPSocket() {
            try {
                // server是ftp的ip,userName为登录名,passWord为密码 
                Socket socket = new Socket(server, 21);
                InputStream is = socket.getInputStream();
                OutputStream os = socket.getOutputStream();
                //接收初始链接信息
                byte[] buffer = new byte[100];
                int length = is.read(buffer);
                String s = new String(buffer, 0, length);
                System.out.println(s);
                //发送用户名
                String str = "USER " + userName + "\n";
                os.write(str.getBytes());
                //得到返回值
                length = is.read(buffer);
                s = new String(buffer, 0, length);
                System.out.println(s);
                //发送密码
                str = "PASS " + passWord + "\n";
                os.write(str.getBytes());
                //得到返回值
                length = is.read(buffer);
                s = new String(buffer, 0, length);
                System.out.println(s);
                //发送切换文件夹指令
                str = "CWD " + path + "\n";
                os.write(str.getBytes());
                //得到返回值
                length = is.read(buffer);
                s = new String(buffer, 0, length);
                System.out.println(s);
                //进入被动模式
                str = "PASV\r\n";
                os.write(str.getBytes());
                //得到返回值
                length = is.read(buffer);
                s = new String(buffer, 0, length);
                System.out.println(s);
                //得到被动监听信息
                str = "EPSV\n";
                os.write(str.getBytes());
                //得到返回值
                length = is.read(buffer);
                s = new String(buffer, 0, length);
                System.out.println(s);
                //取得FTP被动监听的端口号
                String portlist=s.substring(s.indexOf("(|||")+4,s.indexOf("|)"));
                System.out.println(portlist);
                //设定传输方式为二进制方式
                str = "TYPE I\n";
                os.write(str.getBytes());
                length = is.read(buffer);
                s = new String(buffer, 0, length);
                System.out.println(s);
                //实例化ShowList线程类,链接FTP被动监听端口号
                scenicFlowList sl=new scenicFlowList();
                sl.port=Integer.parseInt(portlist);
                sl.start();
                // 读取文件列表
                str = "LIST\n";
                os.write(str.getBytes());
                //关闭链接
                is.close();
                os.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();

            }
        }
    //得到被动链接信息类,这个类是多线程的
    class scenicFlowList extends Thread{
        public int port=0;
        byte[] buffer = new byte[100];
        public void run(){
            try{
                Socket socket = new Socket(server,this.port);
                InputStream is = socket.getInputStream();
                OutputStream os = socket.getOutputStream();
                //将文件列表写入本地文件  
                writeToLocal(localPath,is);
                //关闭链接
                is.close();
                os.close();
                socket.close();
            }
            catch(Exception e){
            }
        }
    }
    /**
     * 将InputStream写入本地文件
     * @param destination 写入本地目录
     * @param input    输入流
     * @throws IOException
     */
    private static void writeToLocal(String destination, InputStream input)
            throws IOException {
        int index;
        byte[] bytes = new byte[10240];
        File file = new File(destination);
        if(file.exists()){
            file.delete();
        }
        file.createNewFile();
        FileOutputStream downloadFile = new FileOutputStream(destination);
        while ((index = input.read(bytes)) != -1) {
            downloadFile.write(bytes, 0, index);
            downloadFile.flush();
        }
        downloadFile.close();
        input.close();
    }            

  2.获取本地文件列表,读取文件内容

// 获取下载ftp文件列表
FileInputStream fileInputStream = new FileInputStream(localPath);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf8");
BufferedReader reader = new BufferedReader(inputStreamReader);
String tempString = null;
// 读取ftp文件列表每行文件名
while ((tempString = reader.readLine()) != null) {
    //从tempString中获取文件名fileName
    *****此处省略*******
    // 每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据。
    ftp.enterLocalPassiveMode();
    // 从服务器上读取指定的文件内容
    InputStream ins = ftp.retrieveFileStream(fileName);
    if (ins != null) {
        BufferedReader reader2 = new BufferedReader(new InputStreamReader(ins, "UTF-8"));
        String tempString2 = null;
     while ((tempString2 = reader2.readLine()) != null) {
        //对文件内容操作
           *****此处省略****** 
        }                            
    reader2.close();
    ins.close();                                    
        ftp.completePendingCommand();
    }
}                    

二、分析读取ftp文件内容1.2方式

  第一种方式(上篇内容),获取文件列表用  FTPFile[] fs = ftp.listFiles();列表量成千上万时,则该数组在内存中开辟大量空间,且循环数组效率低下。如果选择先存到本地

ftp.retrieveFile(ff.getName(), is); 再读取内容,效率更低。但是对于数据量不大的ftp文件,操作简单便利。

  第二种方式(本篇内容),通过ftp命令读取文件列表 str = "LIST\n"; 列表再多都能在1s内读完并存储在本地,节约内存空间。且用输入流读取列表每行文件名,速度更快。

其次,ftp.retrieveFileStream(fileName);直接读取内容进行处理,避免再将内容写入本地再读的过多操作,节省时间。对于大数据量的ftp文件,效率更高。

 

 

  

  

  

posted on 2018-12-07 15:56  kkw105  阅读(229)  评论(0)    收藏  举报