如何使用JSch在Java中获取SFTP服务器目录完整层级结构
我来帮你把这段代码完善成能递归遍历SFTP远程目录完整层级的版本~
用JSch递归遍历SFTP远程目录的完整层级结构
你目前的代码只实现了单层目录的遍历,要获取包含子文件夹的完整层级结构,核心是递归处理每个子目录。下面是完善后的完整代码示例:
import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import com.jcraft.jsch.ChannelSftp.LsEntry; import java.util.ArrayList; import java.util.List; import java.util.Vector; public class SftpDirTraversal { public static void main(String[] args) { // 替换成你的SFTP服务信息 String host = "your-sftp-host"; int port = 22; String username = "your-username"; String password = "your-password"; String remoteRootDir = "/your/target/directory"; Session session = null; ChannelSftp sftpChannel = null; try { // 初始化JSch并建立Session JSch jsch = new JSch(); session = jsch.getSession(username, host, port); session.setPassword(password); // 跳过主机密钥验证(生产环境不建议,最好配置信任密钥) session.setConfig("StrictHostKeyChecking", "no"); session.connect(); // 打开SFTP通道 sftpChannel = (ChannelSftp) session.openChannel("sftp"); sftpChannel.connect(); // 存储完整目录结构的列表 List<String> fullDirStructure = new ArrayList<>(); // 启动递归遍历 traverseRemoteDir(sftpChannel, remoteRootDir, fullDirStructure); // 打印结果 System.out.println("远程目录完整层级:"); for (String path : fullDirStructure) { System.out.println(path); } } catch (Exception e) { e.printStackTrace(); } finally { // 确保资源正确关闭 if (sftpChannel != null && sftpChannel.isConnected()) { sftpChannel.disconnect(); } if (session != null && session.isConnected()) { session.disconnect(); } } } /** * 递归遍历SFTP目录,收集所有文件和文件夹的完整路径 * @param sftpChannel 已连接的SFTP通道 * @param currentDir 当前遍历的目录路径 * @param resultList 存储结果的列表 */ private static void traverseRemoteDir(ChannelSftp sftpChannel, String currentDir, List<String> resultList) throws Exception { // 切换到当前目录 sftpChannel.cd(currentDir); // 获取当前目录下的所有条目 Vector<?> entries = sftpChannel.ls("*"); for (Object entryObj : entries) { if (entryObj instanceof LsEntry) { LsEntry entry = (LsEntry) entryObj; String entryName = entry.getFilename(); // 跳过.和..目录,避免无限递归 if (entryName.equals(".") || entryName.equals("..")) { continue; } // 拼接完整路径 String fullPath = currentDir + "/" + entryName; // 将路径加入结果列表 resultList.add(fullPath); // 如果是目录,递归遍历其子内容 if (entry.getAttrs().isDir()) { traverseRemoteDir(sftpChannel, fullPath, resultList); } } } } }
几个关键细节说明:
- 递归核心:
traverseRemoteDir方法会判断每个条目是否是目录,如果是就递归调用自身,深入遍历子目录,这样就能覆盖所有层级。 - 避免无限递归:必须跳过
.和..这两个特殊目录,不然会一直循环遍历上级目录。 - 资源安全:在
finally块里手动关闭SFTP通道和Session,防止资源泄漏。 - 生产环境优化:代码里的
StrictHostKeyChecking=no是为了方便测试,生产环境建议配置信任的主机密钥,或者用密钥登录替代密码登录,提升安全性。
如果需要区分每个条目是文件还是目录,可以把结果列表改成存储自定义实体类,比如:
public class SftpItem { private String fullPath; private boolean isDirectory; // 构造方法、getter、setter }
遍历的时候创建SftpItem对象加入列表,就能更清晰地区分每个条目的类型啦~
内容的提问来源于stack exchange,提问作者Ayush
相关产品推荐
相关产品推荐

