有一些较大的文本文件,平均100MB左右,要一次读入内存,按分隔符分割,整理过滤之后显示在界面上。
现在的问题是,读入内存的过程就要消耗n>5倍左右的内存,也就是下面的code执行后heap size已经快1G了:
BufferedReader br = new BufferedReader(new FileReader("c:\\temp\\test-prices_bulk.log"));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
br.close;
String content = sb.toString();
但是手工GC,heap size能降下来一半。
请问有什么好的办法,能够在读取的时候,不让heap size迅速增长么?
谢谢!
现在的问题是,读入内存的过程就要消耗n>5倍左右的内存,也就是下面的code执行后heap size已经快1G了:
BufferedReader br = new BufferedReader(new FileReader("c:\\temp\\test-prices_bulk.log"));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
br.close;
String content = sb.toString();
但是手工GC,heap size能降下来一半。
请问有什么好的办法,能够在读取的时候,不让heap size迅速增长么?
谢谢!
import java.io.File;
import java.io.FileReader;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;public class ReadBig {
public static String fff = "C:\\mq\\read\\from.xml"; public static void main1(String[] args) throws Exception { final int BUFFER_SIZE = 0x300000;// 缓冲区大小为3M File f = new File(fff); /**
*
* map(FileChannel.MapMode mode,long position, long size)
*
* mode - 根据是按只读、读取/写入或专用(写入时拷贝)来映射文件,分别为 FileChannel.MapMode 类中所定义的
* READ_ONLY、READ_WRITE 或 PRIVATE 之一
*
* position - 文件中的位置,映射区域从此位置开始;必须为非负数
*
* size - 要映射的区域大小;必须为非负数且不大于 Integer.MAX_VALUE
*
* 所以若想读取文件后半部分内容,如例子所写;若想读取文本后1/8内容,需要这样写map(FileChannel.MapMode.READ_ONLY,
* f.length()*7/8,f.length()/8)
*
* 想读取文件所有内容,需要这样写map(FileChannel.MapMode.READ_ONLY, 0,f.length())
*
*/ MappedByteBuffer inputBuffer = new RandomAccessFile(f, "r")
.getChannel().map(FileChannel.MapMode.READ_ONLY,
f.length() / 2, f.length() / 2); byte[] dst = new byte[BUFFER_SIZE];// 每次读出3M的内容 long start = System.currentTimeMillis(); for (int offset = 0; offset < inputBuffer.capacity(); offset += BUFFER_SIZE) { if (inputBuffer.capacity() - offset >= BUFFER_SIZE) { for (int i = 0; i < BUFFER_SIZE; i++) dst[i] = inputBuffer.get(offset + i); } else { for (int i = 0; i < inputBuffer.capacity() - offset; i++) dst[i] = inputBuffer.get(offset + i); } int length = (inputBuffer.capacity() % BUFFER_SIZE == 0) ? BUFFER_SIZE
: inputBuffer.capacity() % BUFFER_SIZE; System.out.println(new String(dst, 0, length));// new
// String(dst,0,length)这样可以取出缓存保存的字符串,可以对其进行操作 } long end = System.currentTimeMillis(); System.out.println("读取文件文件一半内容花费:" + (end - start) + "毫秒"); } public static void main2(String[] args) throws Exception {
int bufSize = 1024;
byte[] bs = new byte[bufSize];
ByteBuffer byteBuf = ByteBuffer.allocate(1024);
FileChannel channel = new RandomAccessFile(fff, "r").getChannel();
while (channel.read(byteBuf) != -1) {
int size = byteBuf.position();
byteBuf.rewind();
byteBuf.get(bs); // 把文件当字符串处理,直接打印做为一个例子。
System.out.print(new String(bs, 0, size));
byteBuf.clear();
} } public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new FileReader(fff));
String line = null;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}}
我的压缩包里面不止一两样东西哦,那可是我学习和工作的所有资料,不管是学习还是工作都会需要。
http://download.csdn.net/user/yangtonghai
http://100049.onegrid.com.cn/bs99rj8KC2ajo.g?T2jK3jM99G34o-blogid=bD1MKs103e7i5&blogtype=Ts99DKiDPe299