这可能听起来有点复杂,我会尝试简化我的要求。
我正在开发的程序可以使用JTextArea
从/向文件进行读写。当文件相当大时,将该文件中的数据读入文本区域需要花费大量时间。作为一个例子,我有一个文件,目前有40,000行文本,大约50个字符一行;还有,一些线包裹。有很多文本,从那个文件中读取需要花费更多的时间。
目前,我正在使用BufferedReader
组件包含的JTextArea
实例的标准读取方法。我想要做的是加载JTextArea
并在屏幕上加载一定量的文本。屏幕上的其余部分在后台单独的线程中加载。
使用InputStream
并将每个字符写入数组然后将字符写入JTextArea
就足够了吗?或者应该采用不同的方法吗?我试图完成一种快速有效的读取方法。
答案 0 :(得分:7)
手头有两个即时的问题
首先,需要读取文件,以便逐步更新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
,能够从文件中向后和向前请求文本块,并尝试有效地&#34;软糖&#34;这个过程(这样你只需要加载你需要的文本,但仍然可以看起来你在JTextArea
中加载了所有文字)......
您还可以查看FileChannel
,它提供了比标准java.io
类更多的功能,包括内存映射,对于初学者,请查看Reading, Writing, and Creating Files。
您还可以考虑使用高度优化的JList
或JTable
来显示大量数据。这有一些限制,因为期望固定的行高,当改变时(到动态行高)会影响性能,但可能是一个合适的替代...