我给出了(5-7)个大型UTF8文本文件(7 MB)。在unicode中,每个文件的大小约为15MB。
我需要加载给定文件的给定部分。这些文件是已知的,不会更改。我想尽可能快地访问和加载给定位置的线路。我加载这些行并添加HTML标记,并将其显示在JEditorPane中。我知道瓶颈将是JEditorPane生成的HTML呈现,但现在我想集中精力于文件访问性能。
此外,用户可以在所有文件中搜索给定的单词。
现在我使用的代码是:
private static void loadFile(String filename, int startLine, int stopLine) {
try {
FileInputStream fis = new FileInputStream(filename);
InputStreamReader isr = new InputStreamReader(fis, "UTF8");
BufferedReader reader = new BufferedReader(isr);
for (int j = startLine; j <= stopLine; j++) {
//here I add HTML tags
//or do string comparison in case of search by the user
sb.append(reader.readLine());
}
reader.close();
} catch (FileNotFoundException e) {
System.out.println(e);
} catch (IOException e) {
System.out.println(e);
}
}
现在我的问题是:
由于每个文件的部分数目已知,在我的情况下(对于每个文件)为67个,因此我可以创建67个较小的文件。加载给定零件将“更快”,但是当我执行搜索时,它会变慢,因为我必须打开67个文件中的每个文件。
我没有做基准标记,但是我的感觉是,在进行搜索的情况下打开67个文件比在加载文件的一部分时执行空的reader.readlines的时间长得多。
因此,就我而言,最好有一个更大的文件。你同意吗 ?
如果我将每个大文件放在资源中,则意味着在Jar文件中,性能会变差吗?
相关的问题是,如果我将每个文件压缩到备用大小该怎么办。据我了解,Jar文件只是一个zip文件。
我想我不知道如何解压缩。如果我压缩文件,则该文件将在内存中解压缩,还是我的程序能够直接访问磁盘上我需要的给定行。
与Jar文件相同,它将在内存中解压缩。
如果内存中没有解压缩,则有人可以编辑我的代码以使用zip文件。
最后一个问题,对我来说最重要。如果所有事情都在内存中执行,我可以提高所有性能,但是由于unicode和非常大的文件,这很容易导致超过100MB的内存堆。是否有可能将zip文件加载到内存中并进行处理。这样会很快,并且只使用很少的内存。
问题总结
就我而言,最好是一个大文件而不是很多小文件。
如果压缩文件,则在内存中执行解压缩过程(GZipInputStream)。是将所有文件解压缩到内存中然后访问,还是可以直接在磁盘上访问它。
如果问题2是,则有人可以编辑我的代码以执行此操作吗?
最重要:可以将zip文件加载到内存中吗?
我希望我的问题很清楚。 ;-)
更新:感谢Mike的getResourceAsStream提示,我可以使用它
请注意,基准测试可以使Gzip文件的加载有效,但在某些情况下则太慢。
gzip文件约为200毫秒
标准文件约为125毫秒,因此快1.6倍。
假设资源文件夹称为资源
private static void loadFile(String filename, int startLine, int stopLine) {
try {
GZIPInputStream zip = new GZIPInputStream(this.class.getResourceAsStream("resources/"+filename));
InputStreamReader isr = new InputStreamReader(zip, "UTF8");
BufferedReader reader = new BufferedReader(isr);
for (int j = startLine; j <= stopLine; j++) {
//here I add HTML tags
//or do string comparison in case of search by the user
sb.append(reader.readLine());
}
reader.close();
} catch (FileNotFoundException e) {
System.out.println(e);
} catch (IOException e) {
System.out.println(e);
}
}
最佳答案
如果文件确实不是经常更改,我建议使用其他一些数据结构。创建一个包含所有单词和位置的哈希表将使搜索变得更快,创建所有行开始位置的索引将使搜索过程变得更快。
但是,要直接回答您的问题:
是的,一个大文件可能仍然比许多小文件好,我怀疑与打开许多文件或解压缩许多文件相比,从UTF8中读取行并进行解码是否会引起注意。
是的,解压缩过程是在内存中即时进行的。它在您请求数据时发生,但充当缓冲流,它将一次解压缩整个块,因此实际上非常有效。
我无法直接修复您的代码,但是我建议您查找getResourceAsStream:
http://docs.oracle.com/javase/6/docs/api/java/lang/Class.html#getResourceAsStream%28java.lang.String%29
此功能将打开zip / jar文件中的文件,并允许您以流的形式对其进行访问,并在使用时自动在内存中对其进行解压缩。
如果您将其视为资源,则Java会为您完成所有工作,您将不得不阅读处理资源的一些细节,但是Java应该相当聪明地处理它。