有一些较大的文本文件,平均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迅速增长么?
谢谢! 

解决方案 »

  1.   

    分批处理~~import java.io.BufferedReader;
    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);
      }
     }}
      

  2.   

    想要相关语言的所有资料吗?java,c++,c#,html,javascript,javaweb,sqlserver,oracle,jquery,Linux,等等等等,程序员必备的学习资料,快来看看吧。
    我的压缩包里面不止一两样东西哦,那可是我学习和工作的所有资料,不管是学习还是工作都会需要。
    http://download.csdn.net/user/yangtonghai
      

  3.   

    兄弟,我博客有个办法。可以读取500多M的txt 再大的没试过。 去看看吧。
    http://100049.onegrid.com.cn/bs99rj8KC2ajo.g?T2jK3jM99G34o-blogid=bD1MKs103e7i5&blogtype=Ts99DKiDPe299