Я дал число (5-7) больших текстовых файлов UTF8 (7 МБ). В Юникоде их размер составляет около 15 МБ каждый.
Мне нужно загрузить определенные части данного файла. Файлы известны и не меняются. Я хотел бы получить доступ и загрузить линии в данном месте как можно быстрее. Я загружаю эти строки, добавляя 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-файла.
Последний вопрос и самый важный для меня. Я мог бы увеличить всю производительность, если бы все выполнялось в памяти, но из-за юникода и довольно больших файлов это могло легко привести к куче памяти более 100 МБ. Есть ли возможность загрузить zip-файл в память и поработать над этим. Это было бы быстро и использовало бы только немного памяти.
Краткое изложение вопросов
В моем случае, 1 большой файл лучше, чем множество маленьких.
Если файлы заархивированы, процесс распаковки (GZipInputStream) выполняется в памяти. Разархивирован ли весь файл в памяти, а затем получен доступ или возможен ли доступ к нему непосредственно на диске.
Если да на вопрос 2, может ли кто-нибудь отредактировать мой код, чтобы иметь возможность это сделать?
САМОЕ ВАЖНОЕ: возможно ли загрузить файл zip в память и как?
Надеюсь, мои вопросы достаточно ясны. ; -)
ОБНОВЛЕНИЕ : Спасибо Майку за подсказку getResourceAsStream, у меня все работает
Обратите внимание, что бенчмаркинг дает эффективную загрузку файла Gzip, но в большинстве случаев он слишком медленный.
~ 200 мс для файла gzip
~ 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);
}
}