BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("c:/temp")));
            String line = null;
            while ((line = br.readLine()) != null) {
                this.jTextArea1.append(line);
                this.jTextArea1.append("\n");
            }
            br.close();请问上面这段代码 读取文件放到TextArea上面的操作,文件稍大,就会内存溢出,
BufferedReader是如何对内存进行操作的?改用FileChannel 和 MappedByteBuffer就不会产生该问题,请问各位为什么呀?

解决方案 »

  1.   

    看了api将文件中的某个区域直接映射到内存中;对于较大的文件,这通常比调用普通的 read 或 write 方法更为高效。因为他只映射了某个区域,所以不溢出了,不知道理解的对不对,同等高手。
      

  2.   

    LZ说的文件稍大是多大呢...........还有文件的存储又是怎么样的呢......readline 必须要读到\n的.............JTEXTAREA 给的单行是多少个字符呢...........
      

  3.   

    是啊我理解另外两种虽然同样也都含有buffer机制,可能优化的程度不及或具有防溢出的设计有代码吗
      

  4.   


                FileChannel fChannel = new RandomAccessFile("c:/temp", "r").getChannel();
                MappedByteBuffer mByteBuffer = fChannel.map(FileChannel.MapMode.READ_ONLY, 0, fChannel.size());
                Charset charset = Charset.forName("EUC-JP");
                CharsetDecoder decoder = charset.newDecoder();
                CharBuffer charBuffer = CharBuffer.allocate(1024);
                charBuffer = decoder.decode(mByteBuffer);
                this.jTextArea1.setText(new String(charBuffer.array(), 0, charBuffer.limit()));
                fChannel.close();
                try {
                    clean(mByteBuffer);
                } catch (Exception ex) {
                    Logger.getLogger(LogReaderView.class.getName()).log(Level.SEVERE, null, ex);
                }    public static void clean(final Object buffer) throws Exception {
            AccessController.doPrivileged(new PrivilegedAction() {            public Object run() {
                    try {
                        Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);
                        getCleanerMethod.setAccessible(true);
                        sun.misc.Cleaner cleaner = (sun.misc.Cleaner) getCleanerMethod.invoke(buffer, new Object[0]);
                        cleaner.clean();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                }
            });    }
    这段是使用FileChannel 和 MappedByteBuffer的代码
      

  5.   

    BufferedReader可以指定一次读多少进内存,构造方法里就可以设定
      

  6.   

    尝试过设BufferedReader 缓存区大小为1024K ,还是内存溢出了
      

  7.   

    你的文件大小多少
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.io.RandomAccessFile;
    import java.nio.CharBuffer;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import javax.swing.JTextArea;public class Test {
        
        public static void main(String[] args) throws InterruptedException {
         long startMemory = Runtime.getRuntime().freeMemory();
         System.out.println("start memory is: " + startMemory);
         try {
    new Test().go1();
    } catch (Exception e) {
    // TODO Auto-generated catch block
    long usedMemory =  Runtime.getRuntime().freeMemory() - startMemory;;
    System.out.println("used memory is: " + usedMemory);

    e.printStackTrace();
    }    }
        
        public void go1() throws Exception {
         FileChannel fChannel = new RandomAccessFile("c:/temp", "r").getChannel();
            MappedByteBuffer mByteBuffer = fChannel.map(FileChannel.MapMode.READ_ONLY, 0, fChannel.size());
            Charset charset = Charset.forName("EUC-JP");
            CharsetDecoder decoder = charset.newDecoder();
            CharBuffer charBuffer = CharBuffer.allocate(1024);
            charBuffer = decoder.decode(mByteBuffer);
            JTextArea jta = new JTextArea();
            jta.setText(new String(charBuffer.array(), 0, charBuffer.limit()));
            fChannel.close();
        }
        
        public void go2() throws Exception {
         BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("c:/temp")));
            String line = null;
            JTextArea jta = new JTextArea();
            while ((line = br.readLine()) != null) {
                jta.append(line);
                System.out.println(line);
                jta.append("\n");
            }
            br.close();    }
    }
      

  8.   

    你说的内存溢出是不是outofmemoryexception?
    是不是文件太大的原因啊?
      

  9.   

    文件17M
    现在在家试的 居然第一种方法也挂了
    go1:
    start memory is: 4930880
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOfRange(Arrays.java:3209)
    at java.lang.String.<init>(String.java:216)
    at Test.go1(Test.java:37)
    at Test.main(Test.java:18)go2:
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at javax.swing.text.GapContent.allocateArray(GapContent.java:77)
    at javax.swing.text.GapVector.resize(GapVector.java:197)
    at javax.swing.text.GapVector.shiftEnd(GapVector.java:212)
    at javax.swing.text.GapContent.shiftEnd(GapContent.java:328)
    at javax.swing.text.GapVector.open(GapVector.java:184)
    at javax.swing.text.GapVector.replace(GapVector.java:125)
    at javax.swing.text.GapContent.insertString(GapContent.java:115)
    at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:709)
    at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:693)
    at javax.swing.text.PlainDocument.insertString(PlainDocument.java:114)
    at javax.swing.JTextArea.append(JTextArea.java:470)
    at Test.go2(Test.java:46)
    at Test.main(Test.java:18)公司内存4G 第一个方法过了
    家里内存3G。 无语了
    到底Java IO应该如何操作大容量的文件啊
      

  10.   

    继续尝试了一下 如果不将内容放到TextArea上 内存都是不会溢出的
    也就是说两种方式 对内存的消耗都不大 对内存的消耗都在JTextArea上
    内容过多时会内存溢出
    java.lang.OutOfMemoryError这个为Error
    不是Exception 无法捕获
      

  11.   

    继续尝试了一下 如果不将内容放到TextArea上 内存都是不会溢出的
    也就是说两种方式 对内存的消耗都不大 对内存的消耗都在JTextArea上
    内容过多时会内存溢出
    java.lang.OutOfMemoryError这个为Error
    不是Exception 无法捕获
      

  12.   

    又试了下,选了temp文件大小是11213650 bytes
    import java.io.BufferedReader;
    import java.io.FileInputStream;
    import java.io.InputStreamReader;
    import java.io.RandomAccessFile;
    import java.nio.CharBuffer;
    import java.nio.MappedByteBuffer;
    import java.nio.channels.FileChannel;
    import java.nio.charset.Charset;
    import java.nio.charset.CharsetDecoder;
    import javax.swing.JTextArea;public class Test {
        
        public static void main(String[] args) throws InterruptedException {
            long startFreeMemory = Runtime.getRuntime().freeMemory();
            System.out.println("start free memory is: " + startFreeMemory);
            try {
                new Test().go1();
                
                long endFreeMemory = Runtime.getRuntime().freeMemory();
                System.out.println("end free memory is: " + endFreeMemory);
            } catch (Exception e) {
                long endFreeMemory = Runtime.getRuntime().freeMemory();
                System.out.println("end free memory is: " + endFreeMemory);
                
                e.printStackTrace();
            }    }
        
        public void go1() throws Exception {
            FileChannel fChannel = new RandomAccessFile("temp", "r").getChannel();
            MappedByteBuffer mByteBuffer = fChannel.map(FileChannel.MapMode.READ_ONLY, 0, fChannel.size());
            Charset charset = Charset.forName("iso-8859-1");
            CharsetDecoder decoder = charset.newDecoder();
            CharBuffer charBuffer = CharBuffer.allocate(1024);
            charBuffer = decoder.decode(mByteBuffer);
            JTextArea jta = new JTextArea();
            System.out.println("set text length = " + new String(charBuffer.array(), 0, charBuffer.limit()).length());
            
            jta.setText(new String(charBuffer.array(), 0, charBuffer.limit()));
            fChannel.close();
        }
        
        public void go2() throws Exception {
            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("temp")));
            String line = null;
            JTextArea jta = new JTextArea();
            while ((line = br.readLine()) != null) {
                jta.append(line);
                System.out.println(line);
                jta.append("\n");
            }
            br.close();    }
    }
    运行结果:
    start free memory is: 132628296
    set text length = 11213650
    end free memory is: 36272480这个是成功的,JTextArea一次性可以set 11213650 bytes 的text但是BufferedReader是失败的
    Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at javax.swing.text.BoxView.updateLayoutArray(BoxView.java:194)
    at javax.swing.text.BoxView.replace(BoxView.java:168)
    at javax.swing.text.View.updateChildren(View.java:1095)
    at javax.swing.text.View.insertUpdate(View.java:679)
    at javax.swing.plaf.basic.BasicTextUI$RootView.insertUpdate(BasicTextUI.java:1589)
    at javax.swing.plaf.basic.BasicTextUI$UpdateHandler.insertUpdate(BasicTextUI.java:1848)
    at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:185)
    at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:734)
    at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:693)
    at javax.swing.text.PlainDocument.insertString(PlainDocument.java:114)
    at javax.swing.JTextArea.append(JTextArea.java:470)
    at Test.go2(Test.java:48)
    at Test.main(Test.java:18)
    失败原因和楼主一样,是JTextArea组件的关系,有大小限制
      

  13.   

    搞什么,明显是textarea不能放太多的字符么。跟bufferedreader无关
      

  14.   

    如果BufferedReader也用setText而不用append的话,就不会溢出
    append最终有更多限制:/**
         * Resizes the given layout array to match the new number of
         * child views.  The current number of child views are used to
         * produce the new array.  The contents of the old array are
         * inserted into the new array at the appropriate places so that
         * the old layout information is transferred to the new array.
         *
         * @param oldArray the original layout array
         * @param offset location where new views will be inserted
         * @param nInserted the number of child views being inserted; 
         * therefore the number of blank spaces to leave in the
         * new array at location <code>offset</code>
         * @return the new layout array
         */
        int[] updateLayoutArray(int[] oldArray, int offset, int nInserted) {
    int n = getViewCount();
    int[] newArray = new int[n]; System.arraycopy(oldArray, 0, newArray, 0, offset);
    System.arraycopy(oldArray, offset, 
     newArray, offset + nInserted, n - nInserted - offset);
    return newArray;
        }