2010-05-18 25 views
6

搜索的文件中的字符串和写入与匹配字符串的行到另一个 文件需要15 - 20分钟为70MB的一个zip文件(压缩状态)。 有什么方法可以将其最小化。搜索字符串和写入匹配的行到另一个文件中的Java

我的源代码:

越来越Zip文件条目

zipFile = new ZipFile(source_file_name); 

entries = zipFile.entries(); 

while (entries.hasMoreElements()) 

{ ZipEntry entry = (ZipEntry)entries.nextElement(); 

if (entry.isDirectory()) 
{ 
continue; 
} 
searchString(Thread.currentThread(),entry.getName(), new BufferedInputStream (zipFile.getInputStream(entry)), Out_File, search_string, stats); } 

zipFile.close(); 

检索串

public void searchString(Thread CThread, String Source_File, BufferedInputStream in, File outfile, String search, String stats) throws IOException 

{ 

    int count = 0; 
    int countw = 0; 
    int countl = 0; 
    String s; 
    String[] str; 
    BufferedReader br2 = new BufferedReader(new InputStreamReader(in)); 
    System.out.println(CThread.currentThread()); 

     while ((s = br2.readLine()) != null) 
     { 
      str = s.split(search); 
      count = str.length - 1; 
      countw += count; //word count 
      if (s.contains(search)) 
      { 
      countl++; //line count 
      WriteFile(CThread,s, outfile.toString(), search); 
      } 
     } 

    br2.close(); 
    in.close(); 


} 

-------------------------------------------------------------------------------- 

public void WriteFile(Thread CThread,String line, String out, String search) throws IOException 

{ 
    BufferedWriter bufferedWriter = null; 
    System.out.println("writre thread"+CThread.currentThread()); 
    bufferedWriter = new BufferedWriter(new FileWriter(out, true)); 
    bufferedWriter.write(line); 
    bufferedWriter.newLine(); 
    bufferedWriter.flush(); 
} 

请帮助我。对于使用线程的10个文件来说,它确实需要40分钟,在压缩后对于70MB的单个文件来说需要15-20分钟。任何方式来最小化时间。

+0

你只是使用一个线程。你的意思是使用多个?此外,你甚至没有使用countw,countl和count vars。摆脱你的分裂呼叫。 – 2010-05-18 13:46:34

+0

是的,我试图使用多个线程。一个用于文件夹中的每个文件。但即使是单个文件,这个过程也需要将近20分钟。所以想要最小化时间。 – Geeta 2010-05-18 13:49:47

+0

您也可以在单个文件上使用多个线程。 FileChannel可以锁定文件的区域进行处理(请参阅http://java.sun.com/j2se/1.4.2/docs/api/java/nio/channels/FileChannel.html#lock%28long,%20long,% 20boolean%29)。 – 2010-05-18 14:13:11

回答

3

我不知道,如果你看到的成本从磁盘操作或字符串操作。我现在假设问题在于字符串,你可以通过编写一个测试驱动程序来检查,该驱动程序一遍又一遍地用相同的代码运行你的代码。

我可以告诉你,split()将是非常昂贵你的情况,因为你生产你并不需要字符串,然后进行再利用,创造了更多的开销。您可能想要使用-Xmx增加JVM的可用空间量。

如果您仅仅通过空白的存在来区分单词,那么使用您在循环之前创建的正则表达式匹配程序并将其应用于字符串可以获得更好的效果。应用于给定字符串时的匹配数量将会是你的字数,而不应该创建一个字符串数组(这是非常浪费,你不使用)。您将在JavaDocs中看到split可以通过正则表达式工作;这是真的,但拆分是创建单独的字符串的额外步骤,这是您的浪费可能。

您还可以使用正则表达式搜索的匹配,而不是包含尽管这可能不是显著更快。

你可以通过使用多个线程来使事情平行。但是,如果split()是你悲伤的原因,那么你的问题就是开销和堆空间用尽,所以你不一定会从中受益。

更一般地说,如果你需要这么做很多,你可能想写一个更友善的语言来编写脚本来处理字符串。 Python中的10行脚本可以做得更快。

+1

'split()将非常昂贵'+1对于那个 – 2010-05-18 14:28:23

0

这里的一个问题可能是您在书写时停止阅读。我可能会使用一个线程来读取,另一个线程来写入文件。作为额外的优化,编写结果的线程可以将它们缓冲到内存中,并将它们作为批处理写入文件,比如每十个条目或其他内容。

在写入线程中,您应该在处理入口条目之前对其进行排队。

当然,你也许应该先调试如该时间花费,是它的IO或别的东西。

+0

“作为额外的优化,写入结果的线程可以将它们缓存到内存中” - 这正是BufferedWriter在内部已经做的。 – Adamski 2010-05-18 14:10:30

+0

是的,当然,你是对的。这更像是一般性评论。 – fish 2010-05-19 07:32:29

4

您重新打开该文件输出为您处理每写一行。

这很可能会对性能产生巨大的影响,远远超过其他性能问题的大规模。相反,我会建议创建BufferedWriter一次(例如第一场比赛),然后保持打开状态,写完每条匹配线,然后在完成后关闭Writer

此外,删除呼叫flush();不需要刷新每行,因为Writer.close()的调用将自动将任何未写入的数据刷新到磁盘。最后,作为一个附注,你的变量和方法命名风格并不遵循Java驼峰案例约定;你可能要考虑改变它。

1

哇,你这是在这个方法中

WriteFile(CThread,s, outfile.toString(), search); 
每次你得到了包含文本行时间

做,你正在创建BufferedWriter(new FileWriter(out, true));

就在您的searchString方法创建的BufferedWriter并用它来插入行。无需一次又一次地打开它。它将大大提高性能。

0

这段代码中有太多的潜在瓶颈,任何人都要确定关键的是什么。因此,您应该对应用程序进行配置,以确定导致其缓慢的原因。

用这些信息武装起来,决定问题是否在读ZIP文件,以便搜索或将匹配写入输出文件。

(反复打开和关闭输出文件是坏主意,但如果你只得到搜索的微小命中数也不会太大的差别,以整体性能。)

相关问题