import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import org.apache.log4j.Logger; /** * 列出FTP服務器上指定目錄下面的所有文件 */ public class FTPListAllFiles { private static Logger logger = Logger.getLogger(FTPListAllFiles.class); public FTPClient ftp; public ArrayList<String> arFiles; /** * 重載構造函數 * * @param isPrintCommmand 是否打印與FTPServer的交互命令 */ public FTPListAllFiles(boolean isPrintCommmand) { ftp = new FTPClient(); arFiles = new ArrayList<String>(); if (isPrintCommmand) { ftp.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); } } /** * 登陸FTP服務器 * * @param host FTPServer IP地址 * @param port FTPServer 端口 * @param username FTPServer 登陸用戶名 * @param password FTPServer 登陸密碼 * @return 是否登錄成功 * @throws IOException */ public boolean login(String host, int port, String username, String password) throws IOException { this.ftp.connect(host, port); if (FTPReply.isPositiveCompletion(this.ftp.getReplyCode())) { if (this.ftp.login(username, password)) { /** 需要注意這句代碼,如果調用List()方法出現,文件的無線遞歸,與真實目錄結構不一致的時候,可能就是因為轉碼后,讀出來的文件夾與正式文件夾字符編碼不一致所導致。 則需去掉轉碼,盡管遞歸是出現亂碼,但讀出的文件就是真實的文件,不會死掉。等讀完之后再根據情況進行轉碼。 如果ftp部署在windows下,則: for (String arFile : f.arFiles) { arFile = new String(arFile.getBytes("iso-8859-1"), "GBK"); logger.info(arFile); } */ this.ftp.setControlEncoding("GBK"); return true; } } if (this.ftp.isConnected()) { this.ftp.disconnect(); } return false; } /** * 關閉數據鏈接 * * @throws IOException */ public void disConnection() throws IOException { if (this.ftp.isConnected()) { this.ftp.disconnect(); } } /** * 遞歸遍歷出目錄下面所有文件 * * @param pathName 需要遍歷的目錄,必須以"/"開始和結束 * @throws IOException */ public void List(String pathName) throws IOException { if (pathName.startsWith("/") && pathName.endsWith("/")) { //更換目錄到當前目錄 this.ftp.changeWorkingDirectory(pathName); FTPFile[] files = this.ftp.listFiles(); for (FTPFile file : files) { if (file.isFile()) { arFiles.add(pathName + file.getName()); } else if (file.isDirectory()) { // 需要加此判斷。否則,ftp默認將‘項目文件所在目錄之下的目錄(./)’與‘項目文件所在目錄向上一級目錄下的目錄(../)’都納入遞歸,這樣下去就陷入一個死循環了。需將其過濾掉。 if (!".".equals(file.getName()) && !"..".equals(file.getName())) { List(pathName + file.getName() + "/"); } } } } } /** * 遞歸遍歷目錄下面指定的文件名 * * @param pathName 需要遍歷的目錄,必須以"/"開始和結束 * @param ext 文件的擴展名 * @throws IOException */ public void List(String pathName, String ext) throws IOException { if (pathName.startsWith("/") && pathName.endsWith("/")) { //更換目錄到當前目錄 this.ftp.changeWorkingDirectory(pathName); FTPFile[] files = this.ftp.listFiles(); for (FTPFile file : files) { if (file.isFile()) { if (file.getName().endsWith(ext)) { arFiles.add(pathName + file.getName()); } } else if (file.isDirectory()) { if (!".".equals(file.getName()) && !"..".equals(file.getName())) { List(pathName + file.getName() + "/", ext); } } } } } public static void main(String[] args) throws IOException { FTPListAllFiles f = new FTPListAllFiles(true); if (f.login("IP", 7000, "userName", "password")) { f.List("/", "tar"); } f.disConnection(); for (String arFile : f.arFiles) { logger.info(arFile); } } }
