当前位置:  开发笔记 > 编程语言 > 正文

是否有一种解决方法可以解决Java在行走大型目录时表现不佳的问题?

如何解决《是否有一种解决方法可以解决Java在行走大型目录时表现不佳的问题?》经验,为你挑选了2个好方法。

我试图一次处理一个通过网络存储的文件.由于缓冲不是问题,因此读取文件很快.我遇到的问题只是列出文件夹中的目录.在许多文件夹中,每个文件夹至少有10k个文件.

由于File.list()返回数组而不是iterable,因此性能非常慢.Java关闭并收集文件夹中的所有名称,并在返回之前将其打包到数组中.

这个错误条目是http://bugs.sun.com/view_bug.do;jsessionid=db7fcf25bcce13541c4289edeb4?bug_id=4285834并且没有解决方法.他们只是说这已经为JDK7修复了.

几个问题:

    有没有人解决这个性能瓶颈问题?

    我想要实现不可能吗?即使它只是遍历目录,性能仍然会变差吗?

    我可以使用测试版JDK7构建具有此功能,而无需建立在它在我的整个项目?

Bill K.. 7

虽然它不漂亮,但我通过在启动我的应用程序之前将dir/ls的输出传递给文件并传入文件名来解决这种问题.

如果你需要在应用程序中执行它,你可以使用system.exec(),但它会产生一些肮脏.

您询问.第一种形式将非常快,第二种形式也应该非常快.

确保每行执行一项(裸露,无装饰,无图形),完整路径并递归所选命令的选项.

编辑:

只需30分钟即可获得目录列表,哇.

让我感到震惊的是,如果你使用exec(),你可以将它的stdout重定向到管道而不是将其写入文件.

如果您这样做,您应该立即开始获取文件,并能够在命令完成之前开始处理.

这种互动实际上可能会减慢速度,但也许不会 - 你可能会尝试一下.

哇,我刚刚为你找到.exec命令的语法并遇到了这个,可能正是你想要的(它使用exec和"ls"列出一个目录并将结果传递到你的程序中进行处理): 良好的链接在韦巴克(约尔格在评论提供给替换这一个来自太阳,甲骨文爆发)

无论如何,这个想法是直截了当的,但正确的代码是令人讨厌的.我将从互联网中窃取一些代码并将其破解 - 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的代码捐赠者



1> Bill K..:

虽然它不漂亮,但我通过在启动我的应用程序之前将dir/ls的输出传递给文件并传入文件名来解决这种问题.

如果你需要在应用程序中执行它,你可以使用system.exec(),但它会产生一些肮脏.

您询问.第一种形式将非常快,第二种形式也应该非常快.

确保每行执行一项(裸露,无装饰,无图形),完整路径并递归所选命令的选项.

编辑:

只需30分钟即可获得目录列表,哇.

让我感到震惊的是,如果你使用exec(),你可以将它的stdout重定向到管道而不是将其写入文件.

如果您这样做,您应该立即开始获取文件,并能够在命令完成之前开始处理.

这种互动实际上可能会减慢速度,但也许不会 - 你可能会尝试一下.

哇,我刚刚为你找到.exec命令的语法并遇到了这个,可能正是你想要的(它使用exec和"ls"列出一个目录并将结果传递到你的程序中进行处理): 良好的链接在韦巴克(约尔格在评论提供给替换这一个来自太阳,甲骨文爆发)

无论如何,这个想法是直截了当的,但正确的代码是令人讨厌的.我将从互联网中窃取一些代码并将其破解 - 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> NiTiN..:

如何使用File.list(FilenameFilter filter)方法并实现FilenameFilter.accept(File dir,String name)处理每个文件并返回false。

我在Linux vm上运行了包含10K +文件的目录,这花费了<10秒的时间。

import java.io.File;  
import java.io.FilenameFilter;

public class Temp {
    private static void processFile(File dir, String name) {
        File file = new File(dir, name);
        System.out.println("processing file " + file.getName());
    }

    private static void forEachFile(File dir) {
        String [] ignore = dir.list(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                processFile(dir, name);
                return false;
            }
        });
    }

    public static void main(String[] args) {
        long before, after;
        File dot = new File(".");
        before = System.currentTimeMillis();
        forEachFile(dot);
        after = System.currentTimeMillis();
        System.out.println("after call, delta is " + (after - before));
    }  
}

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有