![]() |
1
7
虽然这并不漂亮,但我曾经通过在启动应用程序之前将dir/ls的输出管道传输到一个文件中,并传入文件名来解决了这类问题。 如果你需要在应用程序中做这件事,你可以使用System.Exec(),但这会造成一些不愉快。 你问。第一种形式会非常快,第二种形式也会非常快。 请确保每行执行一项(裸、无装饰、无图形)、所选命令的完整路径和递归选项。 编辑: 30分钟就可以得到一个目录列表,哇。 我突然想到,如果使用exec(),可以将它的stdout重定向到管道中,而不是将其写入文件。 如果您这样做了,您应该立即开始获取文件,并且能够在命令完成之前开始处理。 实际上,交互可能会减慢速度,但可能不会——您可以尝试一下。 哇,我刚刚为您找到了.exec命令的语法,并遇到了这个问题,可能正是您想要的(它使用exec和“ls”列出了一个目录,并将结果通过管道传输到您的程序中进行处理): good link in wayback (j_¶rg在评论中提供,以取代 this one 神谕破灭的太阳) 不管怎样,这个想法很简单,但是让代码正确是很烦人的。我去从互联网上窃取一些密码,然后把它们破解出来——brb /** * Note: Only use this as a last resort! It's specific to windows and even * at that it's not a good solution, but it should be fast. * * to use it, extend FileProcessor and call processFiles("...") with a list * of options if you want them like /s... I highly recommend /b * * override processFile and it will be called once for each line of output. */ import java.io.*; public abstract class FileProcessor { public void processFiles(String dirOptions) { Process theProcess = null; BufferedReader inStream = null; // call the Hello class try { theProcess = Runtime.getRuntime().exec("cmd /c dir " + dirOptions); } catch(IOException e) { System.err.println("Error on exec() method"); e.printStackTrace(); } // read from the called program's standard output stream try { inStream = new BufferedReader( new InputStreamReader( theProcess.getInputStream() )); processFile(inStream.readLine()); } catch(IOException e) { System.err.println("Error on inStream.readLine()"); e.printStackTrace(); } } // end method /** Override this method--it will be called once for each file */ public abstract void processFile(String filename); } // end class 感谢代码捐赠者 IBM |
![]() |
2
4
另一种方法是通过不同的协议来提供文件。正如我理解的那样,您正在使用SMB,Java只是试图将它们列为常规文件。 这里的问题可能不只是Java(在使用微软Explorer x:\\共享)打开该目录时,它的行为在我的经验中也需要相当长的时间。 您可以将协议更改为类似HTTP的内容,但只能获取文件名。通过这种方式,您可以通过HTTP检索文件列表(不应该太多的10K行),并让服务器处理文件列表。这将非常快,因为它将与本地资源(服务器中的资源)一起运行。 然后当你有了这个列表,你就可以按照你现在的方式来处理它们了。 关键是在节点的另一侧有一个辅助机制。 这是可行的吗? 今天:
提出:
HTTP服务器可能是一个非常小和简单的文件。 如果你现在就是这样的话,你要做的就是把所有的10K文件信息提取到你的客户机上(我不知道这些信息有多少),而你只需要文件名来进行以后的处理。 如果现在处理速度很快,可能会慢一点。这是因为预取的信息不再可用。 试一试。 |
![]() |
3
3
我怀疑这个问题与你引用的错误报告有关。 问题在于“只”使用内存,但不一定要加快速度。 如果您有足够的内存,那么这个bug与您的问题不相关。 你应该衡量你的问题是否与记忆有关。打开垃圾收集器日志,例如使用 gcviewer 分析您的内存使用情况。 我怀疑这与导致问题的SMB协议有关。 您可以尝试用另一种语言编写一个测试,看看它是否更快,或者您可以尝试通过其他方法获取文件名列表,如在另一篇文章中所描述的。 |
![]() |
4
3
如何使用file.list(file name filter filter)方法和实现file name filter.accept(file dir,string name)来处理每个文件并返回false。 我在Linux虚拟机上运行这个目录,其中包含10多个文件,用了10秒。
|
![]() |
5
2
一个不可移植的解决方案是对操作系统进行本机调用并传输结果。 对于Linux 你可以看到 readdir . 您可以像链接列表一样浏览目录结构,并批量或单独返回结果。 对于Windows 在Windows中,使用 FindFirstFile 和 FindNextFile API。 |
![]() |
6
1
如果您最终需要处理所有文件,那么让iterable over string[]不会给您带来任何好处,因为您仍然需要去获取整个文件列表。 |
![]() |
7
1
如果你在Java 1.5或1.6上,清除“DIR”命令并在Windows上解析标准输出流是一种完全可接受的方法。我在过去使用这种方法处理网络驱动器,通常比等待本机java.io.file listfiles()方法返回要快得多。 当然,JNI调用应该比炮击“dir”命令更快,更安全。以下JNI代码可用于使用Windows API检索文件/目录列表。这个函数可以很容易地重构成一个新的类,这样调用者就可以增量地检索文件路径(即一次获取一个路径)。例如,可以重构代码,以便在构造函数中调用findfirstfilew,并有单独的方法来调用findnextfilew。
信用: https://sites.google.com/site/jozsefbekes/Home/windows-programming/miscellaneous-functions 即使有了这种方法,仍然有效率有待提高。如果将路径序列化为java.io.file,则会造成巨大的性能损失,特别是当路径表示网络驱动器上的文件时。我不知道sun/oracle在引擎盖下做什么,但是如果您需要文件路径以外的其他文件属性(例如大小、mod日期等),我发现下面的jni函数比在网络上实例化java.io.file对象的路径快得多。
您可以在 javaxt-core 图书馆。在使用Java1.60E38的测试中,当Windows主机击中Windows共享时,我发现这个JNI方法大约快10倍,然后调用java. Io.ListListFes()或清除“DIR”命令。 |
![]() |
8
0
我想知道为什么一个目录中有10万个文件。有些文件系统不能很好地处理这么多文件。对于文件系统有特定的限制,例如每个目录的最大文件量和子目录的最大级别。 我用迭代器解决了一个类似的问题。 我需要递归地遍历大型目录和多个级别的目录树。 我尝试使用apache commons io的fileutils.iteratefiles()。但它通过在列表中添加所有文件,然后返回list.iterator()来实现迭代器。这对记忆很不利。 所以我更喜欢这样写:
注意迭代器会被大量文件迭代器停止,它也有一个文件过滤器。 DirectoryStack是:
|
![]() |
9
0
使用iterable并不意味着文件将被传输给您。事实上,它通常是相反的。所以数组通常比iterable快。 |
![]() |
10
0
你确定这是因为Java,而不仅仅是一个目录中的10K条目,特别是网络上的一般问题吗? 您是否尝试过使用win32 findfirst/findnext函数编写概念验证程序来在C中执行相同的操作,以查看它是否更快? 我不知道SMB的输入和输出,但我强烈怀疑列表中的每个文件都需要一次往返行程——这不会很快,尤其是在具有中等延迟的网络上。 在数组中有10k个字符串听起来像是不应该对现代Java VM征税太多的东西。 |