在 ftp 服务器中不递归地列出文件、目录、子文件和子目录的想法

2023-12-15

我正在尝试生成 ftp 服务器中给定目录及其子目录的文件列表。

服务器工作正常,我已经成功地生成了当前目录的文件列表。当我尝试列出子目录及其文件时,事情就变得复杂了。

我被要求不要使用递归算法,所以我自己做了一些研究。我尝试过使用线程(对于找到的每个目录,启动一个新线程),但我无法保持连接稳定和开放。关于如何使用线程或其他替代方案正确执行此操作有什么想法吗?

编辑:下面是我的代码,当使用递归语句(最后一行代码)时,它可以工作

   class TEST {
        public static synchronized void main(String[] args) {
        String server = args[0]; //server,path will be given as an arguments
        String pass = "SOMEPASS";
        String user = "SOMEUSER";
        int port = 21;
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient.connect(server, port);
            showServerReply(ftpClient);
            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                System.out.println("Connect failed");
                return;
            }
            boolean success = ftpClient.login(user, pass);
            showServerReply(ftpClient);
            if (!success) {
                System.out.println("Could not login to the server");
                return;
            }
           /*START THE FILE LISTING HERE*/

        } catch (IOException ex) {
            System.out.println("Oops! Something wrong happened");
            ex.printStackTrace();
        } finally {
            // logs out and disconnects from server
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
    private static void showServerReply(FTPClient ftpClient) {
        String[] replies = ftpClient.getReplyStrings();
        if (replies != null && replies.length > 0) {
            for (String aReply : replies) {
                System.out.println("SERVER: " + aReply);
            }
        }
    }
    private static void scanDir(FTPClient client, String path) throws IOException {
        FTPFile[] files = client.listFiles(path); // Search all the files in the current directory
        
        for (int j = 0; j < files.length; j++) {
            System.out.println(files[j].getName()); // Print the name of each files
        }
        FTPFile[] directories = client.listDirectories(path); // Search all the directories in the current directory
        for (int i = 0; i < directories.length; i++) {
            String dirPath = directories[i].getName();
            System.out.println(dirPath); // Print the path of a sub-directory
            scanDir(client,dirPath); // Call recursively the method to display the files in the sub-directory DONT WANT TO DO THAT...
        }
    }
}

好的,这是一个example如何以非递归方式但使用列表来处理它。

请注意,此示例基于/访问本地文件系统,但可以轻松地针对任何类型的层次结构/递归结构进行重写/扩展。

package stackoverflow.nonrecursivefilesearch;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.stream.Stream;

public class NonRecursiveFileSearch {

    public static void main(final String[] args) throws IOException {
        final File searchDir = new File("D:\\test\\maven-test"); // set one

        System.out.println("\nOld Java");
        printDirs(listFiles_old(searchDir, true, true), "OLD: Depth first, include dirs");
        printDirs(listFiles_old(searchDir, true, false), "OLD: Breadth first, include dirs");
        printDirs(listFiles_old(searchDir, false, true), "OLD: Depth first, exclude dirs");
        printDirs(listFiles_old(searchDir, false, false), "OLD: Breadth first, exclude dirs");

        System.out.println("\nNew java.io with streams");
        printDirs(listFiles_newIO(searchDir, true), "Java NIO, include dirs");
        printDirs(listFiles_newIO(searchDir, false), "Java NIO, exclude dirs");
    }

    /**
     * this is the way to 'manually' find files in hierarchial/recursive structures
     *
     * reminder: "Depth First" is not a real depth-first implementation
     * real depth-first would iterate subdirs immediately.
     * this implementation iterates breadth first, but descends into supdirs before it handles same-level directories
     * advantage of this implementation is its speed, no need for additional lists etc.
     *
     * in case you want to exclude recursion traps made possible by symbolic or hard links, you could introduce a hashset/treeset with
     * visited files (use filename strings retrieved with canonicalpath).
     * in the loop, check if the current canonical filename string is contained in the hash/treeset
     */
    static public ArrayList<File> listFiles_old(final File pDir, final boolean pIncludeDirectories, final boolean pDepthFirst) {
        final ArrayList<File> found = new ArrayList<>();
        final ArrayList<File> todo = new ArrayList<>();

        todo.add(pDir);

        while (todo.size() > 0) {
            final int removeIndex = pDepthFirst ? todo.size() - 1 : 0;
            final File currentDir = todo.remove(removeIndex);
            if (currentDir == null || !currentDir.isDirectory()) continue;

            final File[] files = currentDir.listFiles();
            for (final File file : files) {
                if (file.isDirectory()) {
                    if (pIncludeDirectories) found.add(file);
                    // additional directory filters go here
                    todo.add(file);
                } else {
                    // additional file filters go here
                    found.add(file);
                }
            }
        }

        return found;
    }

    static private void printDirs(final ArrayList<File> pFiles, final String pTitle) {
        System.out.println("====================== " + pTitle + " ======================");
        for (int i = 0; i < pFiles.size(); i++) {
            final File file = pFiles.get(i);
            System.out.println(i + "\t" + file.getAbsolutePath());
        }
        System.out.println("============================================================");
    }

    /**
     * this is the java.nio approach. this is NOT be a good solution for cases where you have to retrieve/handle files in your own code.
     * this is only useful, if the any NIO class provides support. in this case, NIO class java.nio.file.Files helps handling local files.
     * if NIO or your target system does not offer such helper methods, this way is harder to implement, as you have to set up the helper method yourself.
     */
    static public Stream<Path> listFiles_newIO(final File pDir, final boolean pIncludeDirectories) throws IOException {
        final Stream<Path> stream = Files.find(pDir.toPath(), 100,
                (path, basicFileAttributes) -> {
                    final File file = path.toFile(); // conversion to File for easier access (f.e. isDirectory()), could also use NIO methods
                    return (pIncludeDirectories || !file.isDirectory() /* additional filters go here */ );
                });
        return stream;

    }
    static private void printDirs(final Stream<Path> pStream, final String pTitle) {
        System.out.println("====================== " + pTitle + " ======================");
        pStream.forEach(System.out::println);
        System.out.println("============================================================");
    }
}

并且,必须补充一点,java.nio.file.Files.find()可以递归地实现。但由于这只是一次调用,这也许也可以算作“非递归”。

另外,正如评论中所述,人们可能会使用堆栈或其他 FIFO/LIFO 集合。 LIFO 用于混合深度优先,FIFO 用于广度优先方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 ftp 服务器中不递归地列出文件、目录、子文件和子目录的想法 的相关文章

随机推荐

  • 撤销git中已删除的文件?

    新手需要一些帮助来解决混乱 我试图将我的网站推送到 git 存储库 所以我使用了 git add 命令 然后 在提交之前 我意识到我已经添加了根文件夹中的所有内容 而不仅仅是我想要的目录 由于我不想进行该提交 因此我使用 git rm ch
  • 大熊猫的累计不同计数

    我有一个数据框 其中有一列名为group另一列称为country 我想创建一个新列 输出不同值的累积计数country列同时分组group column 原始数据框 group country A usa A germany A germa
  • 如何比较 char* 和 NSString?

    您好 我正在比较数据库中的 UserName char 和 UITextField 中的 UserName NSString 这个怎么做 以下是我的代码 if UserName isEqual char sqlite3 column tex
  • htaccess 阻止热链接图像中的域

    我阻止了文件中的一些站点 但它们不断访问我的服务器并要求提供会减慢我的服务器速度的图像 我如何为它们添加规则 以便它们会看到大红色标志 停止热链接 RewriteEngine on RewriteCond HTTP REFERER Rewr
  • Rails 3 自定义 mime 类型 - 默认视图格式

    我需要渲染一些没有布局的视图 要跳过控制器操作中的 render layout gt false 行和 if else 逻辑 我有自定义 mime 类型 例如 phtml 纯 html Mime Type register text pht
  • 在 Bicep 模板上设置 Azure 应用服务服务器堆栈

    我正在尝试使用 Azure CLI 中的 Bicep 模板在 Linux 上部署 NET Core 3 1 Azure 应用服务 应用程序服务和相应的应用程序服务计划已正确部署 但 Azure 门户上的应用程序服务堆栈设置为空 我必须手动设
  • 当 WIFI 网络没有互联网连接时,.net 或 Xamarin 互联网可用性检查

    我知道如何检查设备是否有可用的互联网连接是一个大讨论 我尝试了 Ping WebClient 和 HTTPClient 我还使用 Xamarin Essentials 和连接插件 所有这些事情都有效 只需向谷歌或您选择的服务器发出请求 您就
  • Android:Vimeo 视频无法在 webview 中播放

    我必须在 webview 中播放 vimeo 视频 请考虑以下代码 当我播放它时 它只播放音频 但视频是黑色的 我正在使用下面的代码 WebSettings s wv getSettings wv setWebChromeClient ne
  • 有没有办法去掉重音符号并将整个字符串转换为常规字母?

    除了使用之外 是否有更好的方法来消除重音并使这些字母变得规则String replaceAll 方法并一一替换字母 例子 Input or p s d Output orcpzsiayd 它不需要包含所有带有重音符号的字母 例如俄语字母表或
  • C# 中字符串的第一个单词

    如何获取字符串的第一个单词 string test hello world I used test Split FirstOrDefault 但它返回 hello 我可以尝试将分隔符添加为逗号 但即使有逗号或空格 我也只需要单词 hello
  • 如何使用 GNU GAS 或 LLVM 汇编 ARM SVE 指令并在 QEMU 上运行?

    我想玩新的ARM SVE指令使用开源工具 首先 我想组装一个最小的示例 https developer arm com docs dui0965 latest getting started with the sve compiler as
  • Tesseract + opencv 3.0 + windows,文本模块尺寸小,链接错误

    我两天前在answers opencv org 上发布了这篇文章 现在我也将其发布在这里 http answers opencv org question 68634 text contrib module and tesseract 大家
  • 将窗口对象存储在本地存储中

    我需要能够保留窗口对象 我尝试对窗口对象进行字符串化 但在尝试将窗口对象转换为 JSON 时收到错误 将循环结构转换为 JSON 错误 无论如何 我可以将 window open 中的窗口对象存储在本地存储中吗 var myWindow w
  • 将列附加到 pandas 数据框

    这可能很简单 但我有以下数据 在数据框 1 中 index dat1 0 9 1 5 在数据框 2 中 index dat2 0 7 1 6 我想要一个具有以下形式的数据框 index dat1 dat2 0 9 7 1 5 6 我尝试过使
  • 在 C++ 中创建稀疏数组的最佳方法是什么?

    我正在研究一个需要操作巨大矩阵的项目 特别是用于连接计算的金字塔求和 简而言之 我需要跟踪矩阵 多维数组 中大量零的相对少量的值 通常为 1 在极少数情况下超过 1 稀疏数组允许用户存储少量值 并假设所有未定义的记录都是预设值 由于物理上不
  • PHP 显示中文字符:SET NAMES 'utf8' 不起作用

    我正在尝试使用我拥有的数据库 但无法在其中显示中文字符 数据库实际上首先是一个 MS Access 文件 我用程序将其转换为 mysql 无论如何 很多行中都有中文字符 我无法让它们在任何浏览器中正确显示 否则我可以很好地显示汉字 如果我使
  • 配置旁遮普向 Openfire 发送 xmpp 请求

    我正在尝试将旁遮普连接管理器与 Openfire 一起使用 我已经有一个正在运行的 Openfire 服务器 我还安装了 punjab 并且服务器正常启动 允许我导航到本地主机上的端口 5280 虽然http localhost 5280
  • 将整数和文本字符串等数据从手机发送到网络数据库

    我有一个项目 我应该将整数 浮点数和文本字符串等数据从 Android 应用程序发送到 Web 数据库 但是我不知道如何做到这一点 有人可以解释一下吗 任何建议或帮助将不胜感激 您需要编写一些服务器端逻辑 通过POST或GET方法接受参数k
  • 使用角度2中的viewchild更新元素的innerhtml

    我有像这样的html元素 section class span title span span class value span section 我使用访问组件中的元素 ViewChild hiddenElement hiddenEleme
  • 在 ftp 服务器中不递归地列出文件、目录、子文件和子目录的想法

    我正在尝试生成 ftp 服务器中给定目录及其子目录的文件列表 服务器工作正常 我已经成功地生成了当前目录的文件列表 当我尝试列出子目录及其文件时 事情就变得复杂了 我被要求不要使用递归算法 所以我自己做了一些研究 我尝试过使用线程 对于找到