java 通过nio包解析大文件

前言:java通过流读取小文件还行,要是读取大文件(100M以上)则就不行,此时就要通过java.nio包中的方法进行读取解析。

代码:

package com.lezhi.treadstone.ifc.common;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.Arrays;

/**
 * 功能:解析日志文件
 * 作者:gaohx
 * 时间:2015年5月22日上午10:15:27
 */
public class ParseLogFile {

 private File cfFile = null;
 Charset charset = null;
 RandomAccessFile raf=  null;
 FileChannel fc=null;

 //一次读取文件,读取的字节缓存数
 ByteBuffer fbb=ByteBuffer.allocate(1024*1024*5);
 //每行缓存的字节
 ByteBuffer bb=ByteBuffer.allocate(256);

 boolean EOF=false;

 public ParseLogFile(File cfFile,String charset) throws IOException {
  this.cfFile = cfFile;
  this.charset= Charset.forName("UTF-8");;
  raf = new RandomAccessFile(this.cfFile,"r");
  init();
 }

 private void init() throws IOException {
  fc=raf.getChannel();
  fc.read(fbb);
  fbb.flip();
 }

 public boolean hasNext() throws IOException {
  if(EOF)return false;

  if(fbb.position()==fbb.limit()){//判断当前位置是否到了缓冲区的限制
   if(readByte()==0)  return false;
  }
  while(true){
   if(fbb.position()==fbb.limit()){
    if(readByte()==0)  break;
   }
   byte a=fbb.get();
   if(a==13){// || a==10|| a==0
    if(fbb.position()==fbb.limit()){
     if(readByte()==0)  break;
    }
    return true;
   }else{
    if (bb.position() < bb.limit()) {
     bb.put(a);
    }else {
     if(readByte()==0)  break;
    }
    //bb.put(a);
   }
  }
  return true;
 }


 private int readByte() throws IOException{
  //使缓冲区做好了重新读取已包含的数据的准备:它使限制保持不变,并将位置设置为零。
  fbb.rewind();
  //使缓冲区做好了新序列信道读取或相对 get 操作的准备:它将限制设置为当前位置,然后将该位置设置为零。
  fbb.clear();
  if(this.fc.read(fbb)==-1){
   EOF=true;
   return 0;}
  else{
   fbb.flip();
   return fbb.position();
  }
 }

 public byte[] next(){
  bb.flip();
  //此处很重要,返回byte数组方便,行被分割的情况下合并,否则如果正好达到缓冲区的限制时,一个中文汉字被拆了两个字节,就会显示不正常
  byte tm[] = Arrays.copyOfRange(bb.array(), bb.position(), bb.limit());
  bb.clear();
  return tm;
 }

}


测试类:

package com.lezhi.treadstone.ifc.common;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;

import com.lezhi.treadstone.model.util.JSONUtil;

public class ParseLogFileTest {

 public static void main(String[] args)    {
  JSONUtil json = new JSONUtil();
  Runtime runtime = Runtime.getRuntime();
  File f = new File("D:\\userLog\\SchoolInfoSyncAction\\school_info\\2015-05-22.log");
  // RandomAccessFile
  if (args.length > 0) {
   f = new File(args[0]);
  }
  System.out.println(runtime.freeMemory());
  try {
   ParseLogFile cf = new ParseLogFile(f,"UTF-8");
   while(cf.hasNext()){
    String lineContent = new String(cf.next() ,"GBK");
    if(lineContent.indexOf("测试调用地址") != -1){
     String paramsStr = lineContent.substring(lineContent.indexOf("GET")+4,lineContent.length());
     Map<String, String> map = json.readJsonMap(paramsStr);
     System.out.println("======="+map);
    }
   }
  } catch (IOException e) {
   e.printStackTrace();
  }
 }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值