最近在使用FTPClient連續讀取ftp上的多個文件內容時,遇到了兩個問題:
1. 在for循環中,FTPClient只能讀取到第一個文件內容,讀取第二個時遇到NPE問題。
2. 遇到程序鎖死。
下面就遇到問題進行還原分析,並提供解決辦法:
現在使用FTPClient讀取ftp服務器/aaa/bbb/目錄下a.txt,b.txt兩個文件
問題1:
通過Debug發現在讀取第一個文件前FTPClient的_replyCode=226(226 Transter complete.) 數據傳輸完的狀態,當開始讀第一個文件之后_replyCode=125(125 Data connection already open; Transter starting.)數據傳輸開始正在傳輸,表明第一文件還沒有傳輸完,導致讀第二個文件時inputStrean為null。
解決辦法是在讀完第一文件之后,執行 ftpClient.completePendingCommand(); 告訴FTPClient數據已經傳完。
問題2:
ftpClient.completePendingCommand(); 在讀取執行執行造成鎖死。
解決辦法 ftpClient.completePendingCommand(); 只能在數據傳輸之后執行。
最后貼上完整的代碼:
1 package com.shipc.demo.ftp; 2 3 import org.apache.commons.net.ftp.FTPClient; 4 import org.apache.commons.net.ftp.FTPFile; 5 import org.apache.commons.net.ftp.FTPReply; 6 7 import java.io.*; 8 9 /** 10 * @author shipc 2019/10/24 10:00 11 * @version 1.0 12 */ 13 public class TestFTP { 14 15 private FTPClient connectServer() { 16 FTPClient ftpClient = new FTPClient(); 17 ftpClient.setConnectTimeout(1000 * 60 * 30); 18 ftpClient.setControlEncoding("UTF-8"); 19 ftpClient.enterLocalPassiveMode(); //設置被動模式,文件傳輸端口設置 20 try { 21 ftpClient.connect("172.17.0.16", 21); 22 ftpClient.login("ftp-user", "123456"); 23 ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); // 設置文件傳輸模式為二進制 24 final int replyCode = ftpClient.getReplyCode(); 25 if (!FTPReply.isPositiveCompletion(replyCode)) { 26 ftpClient.disconnect(); 27 } 28 } catch (Exception e) { 29 System.out.println(e.getMessage()); 30 } 31 return ftpClient; 32 } 33 34 private void readFiles(FTPClient ftpClient) throws IOException { 35 ftpClient.changeWorkingDirectory("/aaa/bbb"); 36 final FTPFile[] ftpFiles = ftpClient.listFiles(); 37 for (FTPFile ftpFile : ftpFiles) { 38 if (ftpFile.isFile()) { 39 System.out.println("********文件" + ftpFile.getName() + "的內容如下**********"); 40 // ftpClient.completePendingCommand(); // 一定不能在讀之前執行,否則會鎖死 41 42 InputStream inputStream = ftpClient.retrieveFileStream(ftpFile.getName()); 43 try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { 44 while (true) { 45 final String s = reader.readLine(); 46 if (s == null) { 47 break; 48 } 49 System.out.println(s); 50 } 51 } 52 inputStream.close(); 53 ftpClient.completePendingCommand(); // 每當讀完一個文件時,要執行該語句 54 } 55 } 56 } 57 58 public static void main(String[] args) { 59 final TestFTP testFTP = new TestFTP(); 60 FTPClient ftpClient = testFTP.connectServer(); 61 try { 62 testFTP.readFiles(ftpClient); 63 } catch (IOException e) { 64 e.printStackTrace(); 65 } 66 } 67 }