简体   繁体   English

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

[英]How to read and display large text files in Swing?

This might sound a bit complicated, I'll try to simplify what I am asking. 这可能听起来有点复杂,我会尽量简化我的要求。 A program I am developing can read and write from/to files using a JTextArea . 我正在开发的程序可以使用JTextArea从/向文件读写。 When files are rather large, it does take a cumbersome amount of time to read the data from that file into the text area. 当文件相当大时,将该文件中的数据读入文本区域需要花费大量时间。 As an example, I have a file that currently has 40,000 lines of text, roughly 50 characters a line; 作为一个例子,我有一个文件,目前有40,000行文本,大约50个字符一行; also, some lines wrap. 还有,一些线包裹。 There is quite a lot of text and it takes a lot more time to read from that file then I would like. 有很多文本,从那个文件中读取需要花费更多的时间。

Currently, I am using the standard read method utilizing a BufferedReader instance that the JTextArea component includes. 目前,我正在使用标准读取方法,该方法利用JTextArea组件包含的BufferedReader实例。 What I would like to do is load the JTextArea with a certain amount of text loaded on screen. 我想要做的是加载JTextArea并在屏幕上加载一定量的文本。 The rest of the text that is off-screen loaded in a separate thread in the background. 屏幕上的其余部分在后台单独的线程中加载。

Would using a InputStream and write each character to an array then write characters to the JTextArea be sufficient? 使用InputStream并将每个字符写入数组然后将字符写入JTextArea就足够了吗? Or should there be a different approach at this? 或者应该采用不同的方法吗? I'm trying to accomplish a fast and efficient read method. 我正在努力实现快速有效的读取方法。

There are two, immediate, issues at hand 手头有两个即时的问题

First, the need to read a file in such away that it can progressively update the UI without causing unacceptable delays 首先,需要以这样的方式读取文件,以便它可以逐步更新UI而不会导致不可接受的延迟

Second, the ability for the JTextArea to actually deal with this amount of data... 第二, JTextArea实际处理这一数据量的能力......

The first issues is, relatively, simple to fix. 第一个问题相对来说很容易修复。 What you need to make sure of is that you are not blocking the Event Dispatching Thread while you read the file and that you are only updating the JTextArea from within the context of the Event Dispatching Thread. 您需要确保的是,在读取文件时您没有阻止事件调度线程,并且您只是在事件调度线程的上下文中更新JTextArea To this end a SwingWorker is an excellent choice, for example... 为此, 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);
        }
    }

}

Take a look at Concurrency in Swing and Worker Threads and SwingWorker for more details 有关更多详细信息,请查看SwingWorker Threads中的Concurrency 以及SwingWorker

ps- You don't need to use the List to store the contents, I just did it as an example... ps-你不需要使用List来存储内容,我只是把它作为一个例子......

The second problem is far more complicated and would need some additional testing to ensure that it is actually a problem, but generally speaking, contents of over about 1mb tends to lead to issues... 第二个问题要复杂得多,需要一些额外的测试以确保它实际上是一个问题,但一般来说,超过1mb的内容往往会导致问题......

To this end, you would need to be able to manage the JScrollPane , be able to request chunks of text from the file both in backwards and forwards direction and try and effectively "fudge" the process (so that you only have the text you need loaded, but can still make it look like you have all the text loaded within the JTextArea )... 为此,您需要能够管理JScrollPane ,能够从文件中向后和向前请求文本块,并尝试有效地“捏造”该过程(这样您只需要所需的文本加载,但仍然可以使它看起来像你在JTextArea加载了所有文本)...

You could also take a look at FileChannel , which provides more functionality over the standard java.io classes, including memory mapping, for starters, have a look at Reading, Writing, and Creating Files . 您还可以查看FileChannel ,它提供了比标准java.io类更多的功能,包括内存映射,对于初学者,请查看阅读,编写和创建文件

You also might consider using a JList or JTable which are highly optimised for displaying large quantities of data. 您还可以考虑使用高度优化的JListJTable来显示大量数据。 There are limitations to this, as there is an expectation of fixed row heights, which when changed (to dynamic row heights) can affect the performance, but might be a suitable alternative... 这有一些局限性,因为期望固定的行高,当改变时(动态行高)会影响性能,但可能是一个合适的替代方案......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM