2012-02-17 109 views
3

我制作了一个Applet搜索实用程序,其中提供了一个字符串作为输入,并在指定的文件或文件夹中查找该字符串。
我已经完成了这个,但我不满意它的表现。
该过程花费太多时间来响应。
我决定做一下分析,看看发生了什么,我注意到了scanner.hasNextLine()方法大部分时间都在使用。
虽然这是我的计划很重要的方法,因为我要读所有的线路,找到该字符串,有没有通过,我可以提高其性能,并减少执行时间
提高Java程序的性能

这里任何其他方式的代码我正在使用这种方法....

fw = new FileWriter("filePath", true); 
     bw = new BufferedWriter(fw); 

     for (File file : filenames) { 
      if(file.isHidden()) 
       continue; 

       if (!file.isDirectory()) { 
       Scanner scanner = new Scanner(file); 
       int cnt = 0; 
       while (scanner.hasNextLine()) { 
        String line = scanner.nextLine(); 
        if(!exactMatch) 
        { 
         if(!caseSensitive) 
         { 
          if (line.toLowerCase().contains(searchString.toLowerCase())) { 
           // System.out.println(line); 
           cnt += StringUtils.countMatches(line.toLowerCase(), 
             searchString.toLowerCase()); 
          } 
         } 
         else 
         { 
          if (line.contains(searchString)) { 
           // System.out.println(line); 
           cnt += StringUtils.countMatches(line, 
             searchString); 
          } 
         } 
        } 

是的,方法toLowerCase()也需要更多的时间,然后预期。


我已经改变了我的代码,现在我代替Scanner使用BufferedReader作为亚历克斯NRJ建议,我发现我的应用程序的性能很好的改善。
现在正在处理其早期版本的三分之一时间。
感谢所有答复.....

+0

究竟为什么你在网页中嵌入的文件搜索? – 2012-02-17 07:13:09

+0

Andrew感谢您的评论,但该applet并未嵌入网页中,而是一个桌面应用程序。 – 2012-02-17 07:16:21

+0

所以,'applet'是指a)'小应用',还是b)扩展'Applet'或'JApplet'的类? – 2012-02-17 07:20:18

回答

3

按照你的问题,我检查了Scanner代码,我认为你是对的。它不适合处理大量数据。我建议你用简单的BufferedReader一个包装InputStreamReader换行FileInputStream

BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(fileName)))

然后读取行由行:

r.readLine()

如果您尝试这是不够的阅读大量的行,然后处理它们。

关于toLowerCase()您可以尝试使用正则表达式代替。好处是你不必每次都改变线路的情况。缺点是在简单情况下,正则表达式的工作速度比常规字符串比较慢。

+0

谢谢亚历克斯我会尝试BufferedReader,如果它的作品,那么我一定会在这里通知所有观众。 – 2012-02-17 07:27:01

-2

我不会使用Java来搜索文件系统的字符串匹配。而是从Java调用本机算法。我会用这样的事情从Java调用的grep:

ProcessBuilder pb = new ProcessBuilder("grep", "-r", "foo"); 
pb.directory(new File("myDir")); 
Process p = pb.start(); 
InputStream in = p.getInputStream(); 
//Do whatever you prefer with the stream 
+0

请解释一下为什么不使用Java来做这件事? – bezmax 2012-02-17 09:08:07

+0

String.contains()算法扫描字符串行的每个字节,查找匹配字符串的第一个字符。只要它找到第一个匹配的字符,它就会尝试匹配字符串的其余部分。最好的情况是,它会以线性时间在O(n)中运行,并且有更好的字符串搜索算法。 Grep使用修改后的Boyer-Moore算法,它可以更快地搜索,它是本机C代码,因此不需要做任何动态翻译。 – algolicious 2012-02-17 10:04:23

+0

您可以用Java实现该算法,并且已经有成功使用它的库。而且,如果你用Java实现它 - 那么它将是跨平台的,并且不依赖于外部工具。因此,我不同意你的陈述'我不会使用Java在文件系统中搜索字符串匹配'。 – bezmax 2012-02-17 11:11:50

0
  1. 尝试使用BufferedReader

  2. 制作使用线程。您可以并行搜索文件,这会缩短搜索时间。

+0

由于IO开销,您不会从线程获得太多的性能提升。 – bezmax 2012-02-17 09:06:30

+0

@Max不应该高的IO允许更多的线程有机会运行?此外,现在所有的多核心,线程应该增加吞吐量在这里..纠正我,如果不是这种情况... – Nrj 2012-02-17 19:50:17

+0

很多人都很难估计与多线程做IO,因为有很多因素。问题在于,当您扫描文本文件时,基本上使用100%的IO来读取文件,这是应用程序的开销。但对于那些100%的IO,只会使用一小部分CPU(因为几乎不会进行数据处理)。使用多个线程读取不同的文件只会有助于IO也可以并行化(也许某种RAID阵列具有自定义驱动程序,但我不确定)。 – bezmax 2012-02-20 08:02:19

1

(只有小的优化,针对上述评论。)

  if(!caseSensitive) 
      { 
       searchString = searchString.toLowerCase(); 
      } 
      while (true) { 
       String line = bufferedReader.readLine(); 
       if (line == null) 
        break; 
       if(!caseSensitive) 
       { 
        line = line.toLowerCase(); 
       } 
       if(!exactMatch) 
       { 
        if (line.contains(searchString)) { 
         // System.out.println(line); 
         cnt += StringUtils.countMatches(line, 
           searchString); 
        } 
       }