如何在 Swing 中读取和显示大文本文件?

Posted

技术标签:

【中文标题】如何在 Swing 中读取和显示大文本文件?【英文标题】:How to read and display large text files in Swing? 【发布时间】:2014-09-22 19:04:05 【问题描述】:

这听起来可能有点复杂,我会尽量简化我的要求。 我正在开发的程序可以使用JTextArea 读写文件。当文件相当大时,将数据从该文件读取到文本区域确实需要大量时间。例如,我有一个文件,目前有 40,000 行文本,每行大约 50 个字符;此外,有些行会换行。有很多文本,从该文件中读取所需的时间比我想要的要多得多。

目前,我正在使用标准读取方法,该方法利用了JTextArea 组件包含的BufferedReader 实例。我想做的是加载JTextArea,并在屏幕上加载一定数量的文本。屏幕外的其余文本在后台的单独线程中加载。

使用InputStream 并将每个字符写入数组然后将字符写入JTextArea 就足够了吗?还是应该有不同的方法?我正在尝试实现一种快速高效的读取方法。

【问题讨论】:

(FWIW:2MB 的文件对于今天的硬件来说不是很“大”——也就是说,它运行速度是否太慢?对于真正的大文件,有更好的方法。) 嗯,它实际上有 4.20 mb 大,但我同意。但是,加载时间仍然比我喜欢的要长。 使用 BufferedReader(包装 InputStream),顺序 IO 应该“几乎是即时的”。对加载 (IO) 和加载 (UI) 计时,看看哪个引入了不希望的延迟。 好吧,我明白了。我目前正在使用带有包装器 FileReader 的 BufferedReader。那么 InputStream 会更高效吗? 几乎可以肯定,问题不在于读取文件,而在于试图让 JTextArea 处理数据。您可以进行某种手动分页,只将数据的某个子集设置到 jtextarea 中。 【参考方案1】:

手头有两个直接的问题

首先,需要读取一个文件,以便它可以逐步更新 UI 而不会导致不可接受的延迟

其次,JTextArea 实际处理这些数据量的能力...

第一个问题相对来说比较容易解决。您需要确保的是,您在读取文件时没有阻塞事件分派线程,并且您只是在事件分派线程的上下文中更新JTextArea。为此,SwingWorker 是一个很好的选择,例如...

public class FileReaderWorker extends SwingWorker<List<String>, String> 

    private File file;
    private JTextArea ta;

    public FileReaderWorker(File file, JTextArea ta) 
        this.file = file;
        this.ta = ta;
    

    public File getFile() 
        return file;
    

    public JTextArea getTextArea() 
        return ta;
    

    @Override
    protected List<String> doInBackground() throws Exception 
        List<String> contents = new ArrayList<>(256);
        try (BufferedReader br = new BufferedReader(new FileReader(getFile()))) 
            String text = null;
            while ((text = br.readLine()) != null) 
                // You will want to deal with adding back in the new line characters
                // here if that is important to you...
                contents.add(text);
                publish(text);
            
        
        return contents;
    

    @Override
    protected void done() 
        try 
            get();
         catch (InterruptedException | ExecutionException ex) 
            ex.printStackTrace();
            // Handle exception here...
        
    

    @Override
    protected void process(List<String> chunks) 
        JTextArea ta = getTextArea();
        for (String text : chunks) 
            ta.append(text);
        
    


查看Concurrency in Swing 和Worker Threads and SwingWorker 了解更多详情

ps-你不需要使用List来存储内容,我只是做了一个例子......

第二个问题要复杂得多,需要一些额外的测试来确保它确实是一个问题,但一般来说,超过 1mb 的内容往往会导致问题......

为此,您需要能够管理JScrollPane,能够从文件中向后和向前请求文本块,并尝试有效地“捏造”该过程(这样您只能已经加载了您需要的文本,但仍然可以让它看起来像您已经在 JTextArea) 中加载了所有文本...

您还可以查看FileChannel,它提供了比标准java.io 类更多的功能,包括内存映射,对于初学者,请查看Reading, Writing, and Creating Files。

您还可以考虑使用为显示大量数据而高度优化的JListJTable。这有一些限制,因为有固定行高的预期,当更改(动态行高)时会影响性能,但可能是一个合适的替代方案......

【讨论】:

我会尝试使用 JListJTable 作为视图,以利用享元渲染。 @trashgod 对于查看,绝对,如果 OP 期望能够编辑值,它会变得有点复杂,但并非不可能...... 好点;默认的JTable 编辑器就足够了,但回写可能很乏味。 还有固定行高和动态行高的问题,固定行高的组件得到了很好的优化,动态行高意味着组件需要测试每一行才能计算出行高组件,如果认真做,更新可以做得很好,但是要牢记的一个考虑...

以上是关于如何在 Swing 中读取和显示大文本文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何提高java读取大文本文件的效率

Tensorflow 2.3:如何并行读取大文件中的文本?

如何在 Windows 上读取大文本文件? [关闭]

在火花分析之前从 FTP 读取大文本文件

在火花分析之前从FTP读取大文本文件

C#读取大文本文件