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就不会产生该问题,请问各位为什么呀?
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的代码
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(); }
}
是不是文件太大的原因啊?
现在在家试的 居然第一种方法也挂了
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应该如何操作大容量的文件啊
也就是说两种方式 对内存的消耗都不大 对内存的消耗都在JTextArea上
内容过多时会内存溢出
java.lang.OutOfMemoryError这个为Error
不是Exception 无法捕获
也就是说两种方式 对内存的消耗都不大 对内存的消耗都在JTextArea上
内容过多时会内存溢出
java.lang.OutOfMemoryError这个为Error
不是Exception 无法捕获
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组件的关系,有大小限制
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;
}