2

我有一个包含 50 mb 数据的大文件。我想读取并附加到 jTextArea() 中。但是我在附加数据时出现*内存错误* 。我该怎么做?请任何人帮助我

例子:

BufferedReader br;
        StringBuilder builder = new StringBuilder();
        try {
            br = new BufferedReader(new FileReader("D:\\myFile.txt"));
            String line;
            try {
                while ((line = br.readLine()) != null) {
                   // process the line.
                    builder.append(line);// here getting error
                }
                System.out.println(builder.toString());

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            try {
                br.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
JTextArea jt = new JtextArea();
jt.append(builder.toString();
4

4 回答 4

2

您可以增加最大堆大小,也可以使用分页器设计模式。

分页通过仅加载那些实际可见的数据来工作。因此,如果您的文本区域可以显示两页文本,那么您一次只能加载显示的两页文本。如果用户向下滚动,您会丢弃已加载的页面并加载这两个新页面。这样一来,您在内存中将始终只有两页。

于 2012-11-15T11:11:17.653 回答
1

我怀疑是否会有用户阅读您将添加到JTextArea.

我建议你实现某种分页,一次只添加几 100 或 1000 行。

但是,如果您真的想添加所有文本-Xmx,请将应用程序的参数设置为更高的值。

于 2012-11-15T11:10:28.763 回答
1

尝试设置 JVM 的最大大小

于 2012-11-15T11:08:21.843 回答
0

Ignoring that it is impractical in terms of usability (and JTextArea will probably not perform well with that much text), you can make some changes to your code to reduce the amount of memory needed (You probably still need to increase -Xmx).

Your first lever is to properly size the StringBuilder for the amount of data you want to put into it. Replacing the new StringBuilder() with new StringBuilder(sizeOfFile) will avoid allocating more memory than needed (this may make a difference of several MB, due to StringBuilders internal memory allocation policy method).

Now when you do builder.toString(), you should be aware that this will double the amount of memory required, since everything in the builder is copied to create the String. With the normal Swing API, there is no way around that, since you absolutely need a String.

But you can change that - look at how the JTextArea works internally: the JTextArea does not really store the text it works with - storing of the text is delegated to a model object, in this case of type javax.swing.Document. If you take a look at Document, you'll find that its an interface. Normally when you use a JTextArea, it creates its own, private document which is not really intended for such large amounts of data (javax.swing.PlainDocument). Now the PlainDocument in turn works with a javax.swing.Content (again an interface), normally implemented in javax.swing.StringContent. This you can replace with your own, new content class that works with a StringBuilder directly (that way there would be no need to duplicate data in memory).

So, you can implement your own Content class working with StringBuilder and construct your JTextArea this way:

Content c = new StringBuilderContent(builder);
Document d = new PlainDocument(c);
JTextArea jt = new JTextArea(d);

Actually creating and implementing StringBuilderContent is left as an excercise to the reader. Actually, you could also implement Content to directly work with a file, that way you could handle files much larger than available heap, too.

于 2012-11-15T11:43:02.250 回答