Как сократить время загрузки открытого файла с помощью 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, Значительный выигрыш в скорости.

Другие вопросы по тегам