Как сократить время загрузки открытого файла с помощью Swing?
Я хочу, чтобы открыть файл, не тратя времени. Когда я нажимаю кнопку "Открыть", он сразу открывается. Но в моем приложении это заняло более двух минут для больших файлов. Я пытаюсь открыть файл. Размер 44 МБ. Открытие этого файла занимает более двух минут. Я хочу быстро открыть файлы большого размера. Как только я проверю код моего открытого действия. Приведенный ниже код показывает рабочий пример моего приложения. Образец кода:
public class OpenDemo extends javax.swing.JFrame {
JTextPane textPane;
JScrollPane scrollPane;
int i=0;
JTextField status;
public OpenDemo() {
initComponents();
textPane=new JTextPane();
}
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
tp = new javax.swing.JTabbedPane();
jMenuBar1 = new javax.swing.JMenuBar();
jMenu1 = new javax.swing.JMenu();
open = new javax.swing.JMenuItem();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jMenu1.setText("File");
open.setText("Open");
open.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
openActionPerformed(evt);
}
});
jMenu1.add(open);
jMenuBar1.add(jMenu1);
setJMenuBar(jMenuBar1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tp, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tp, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
private void openActionPerformed(java.awt.event.ActionEvent evt) {
JFileChooser fileChooser=new JFileChooser();
int result = fileChooser.showOpenDialog(this);
if (result==JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try {
textPane.setPage(file.toURI().toURL());
} catch(Exception e) {
e.printStackTrace();
}
}
scrollPane=new JScrollPane(textPane);
tp.add(scrollPane);
textPane.setCaretPosition(0);
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(OpenDemo.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new OpenDemo().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JMenu jMenu1;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JMenuItem open;
private javax.swing.JTabbedPane tp;
// End of variables declaration
}
2 ответа
SwingWorker
API обрисовывает в общих чертах подходящий подход. Из-за размера я бы обновил TableModel
, как показано здесь, а не текстовый компонент. Линии начнут появляться практически сразу, а графический интерфейс остаётся отзывчивым. Прослушивание JTable
Вам нужно будет отображать только видимые линии, и вы сможете использовать сортировку и фильтрацию.
Есть некоторые издержки (анимация прогресса) и некоторые вещи, которые я бы не сделал, например, поток событий AWT, блокирующий actionPerformed.
Перейдите со своим кодом на https://codereview.stackexchange.com/ потому что обзор кода может быть полезен.
То, что я увидел как оптимизируемое:
Дайте начальную емкость StringBuilder
,
... = new StringBuilder(1024*64); // (int)file.length()?
Замените сканер на BufferdReader
с помощью readLine()
, Идеально было бы проверить скорость Files.readAllBytes
; нужна ли индикация прогресса.
String s = new String(Files.readAllBytes(file.toPath()));
Вторая попытка:
Сначала мера здравомыслия: закрытие файла.
Затем я сделал меньше анимации прогресса, что определенно должно ускорить процесс. Он больше не будет отображать весь текст в текстовой панели, только каждую сотую строку.
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
final int PROGRESS_EVERY = 100;
while ((line = br.readLine()) != null) {
lineNumber++;
text.append(line);
text.append("\n");
if (linenumber % PROGRESS_EVERY== 0) {
ProgressData data = new ProgressData();
data.number = lineNumber;
data.line = line;
publish(data);
}
}
if (linenumber % PROGRESS_EVERY != 0) {
ProgressData data = new ProgressData();
data.number = lineNumber;
data.line = line;
publish(data);
}
}
А потом
private StringBuilder text = new StringBuilder(1024 * 128);
Наконец:
+ Изменить textPane
от JTextPane
в JTextArea
, Значительный выигрыш в скорости.