加载和显示大型文本文件

tra*_*god 16 java swing text latency

在Swing应用程序中,我有时需要支持对加载缓慢的大型面向行的文本文件的只读访问:日志,转储,跟踪等.对于少量数据,一个合适的 Document并且JTextComponent很好,如图所示在这里.我理解浏览大量数据的人为限制,但有问题的东西似乎总是在最大的文件中.对于10-100兆字节,百万行范围内的大量文本,是否有任何实用的替代方案?

tra*_*god 23

由于大小,您肯定希望在后台加载文件以避免阻塞事件派发线程 ; SwingWorker是一种常见的选择.而不是使用a Document,考虑更新a TableModel并在a的行中显示文本行JTable.这提供了几个优点:

  • 结果将立即开始出现,并且将减少感知延迟.

  • JTable使用flyweight模式进行渲染,可以很好地扩展到数兆字节,百万行范围.

  • 您可以在读取输入时解析输入以创建任意列结构.

  • 您可以利用排序和过滤的功能JTable,为例子.

  • 您可以TablePopupEditor将注意力集中在一条线上.

附录:以下示例DefaultTableModel用于方便起见.为了降低开销,扩展AbstractTableModel和管理List<String>List<RowData>,如图所示这里.该示例显示了不确定的进度; 此处显示了显示中间进度的更改.

码:

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.beans.PropertyChangeEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingWorker;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

/**
 * @see https://stackoverflow.com/a/25526869/230513
 */
public class DisplayLog {

    private static final String NAME = "/var/log/install.log";

    private static class LogWorker extends SwingWorker<TableModel, String> {

        private final File file;
        private final DefaultTableModel model;

        private LogWorker(File file, DefaultTableModel model) {
            this.file = file;
            this.model = model;
            model.setColumnIdentifiers(new Object[]{file.getAbsolutePath()});
        }

        @Override
        protected TableModel doInBackground() throws Exception {
            BufferedReader br = new BufferedReader(new FileReader(file));
            String s;
            while ((s = br.readLine()) != null) {
                publish(s);
            }
            return model;
        }

        @Override
        protected void process(List<String> chunks) {
            for (String s : chunks) {
                model.addRow(new Object[]{s});
            }
        }
    }

    private void display() {
        JFrame f = new JFrame("DisplayLog");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        DefaultTableModel model = new DefaultTableModel();
        JTable table = new JTable(model);
        JProgressBar jpb = new JProgressBar();
        f.add(jpb, BorderLayout.NORTH);
        f.add(new JScrollPane(table));
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        LogWorker lw = new LogWorker(new File(NAME), model);
        lw.addPropertyChangeListener((PropertyChangeEvent e) -> {
            SwingWorker.StateValue s = (SwingWorker.StateValue) e.getNewValue();
            jpb.setIndeterminate(s.equals(SwingWorker.StateValue.STARTED));
        });
        lw.execute();
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            new DisplayLog().display();
        });
    }
}
Run Code Online (Sandbox Code Playgroud)


Sta*_*avL 6

我会将问题分开.

第一个是模型 - 文档构建速度

第二个是Document rendering - 构建视图树来表示Document.

一个问题是你是否需要关键字着色等字体效果?

我将从文档构建部分开始.通过EditorKit.read()读取文件的IMHO即使对于大文件也应该快速.我会使用PainDocument来检查纯模型是否构建得足够快,适合您的应用程序.如果是的话,只需使用Document作为模型.如果没有实现自己的Document接口,因为AbstractDocument有很多方法可以进行更新处理(例如writeLock).

当我们足够快地加载文档时,我们必须解决文档渲染问题.默认情况下,javax.swing.text中使用的视图非常灵活.它们被设计为要扩展的基类 - 因此有很多我们不需要的代码.例如测量.

对于我将使用Monospaced字体的功能,我们不需要换行,因此视图的测量值是快=最长行字符数*字符widht.

高度也是char高度*线的数量.

所以我们的PLainTextViewReplacement非常快.此外,我们不必渲染整个视图,只需在滚动窗格中显示一个片段.因此渲染可以快得多.

当然应该有很多工作来提供正确的插入符导航,选择等.


归档时间:

查看次数:

3607 次

最近记录:

10 年,10 月 前