JAVA操作大型文本文件

来源:互联网 发布:美图秀秀有没有mac版 编辑:程序博客网 时间:2024/04/18 15:51

写在前面的废话不想看的可以skip-----由于工作需要,经常需要打开和查询250M左右的文本文件(总行数超过250万行)分析日志,公司发的笔记本内存才512M,地球人都知道,这样的电脑根本不能胜任。不知道有没有人和我一样倒霉,面对这么庞大的文件,曾经让我很无奈,很彷徨。从寻找优秀的类似notepad这样的文本工具,企图通过工具来提高下速度,其中JIURL这个记事本工具,我个人觉得很好,它陪我走了好长时间,虽然它老是有这样那样的BUG,不过它的速度确实比其他的记事本快很多,对于巨型文件,不会像其他记事本那样直接挂死。工具再好,也是死的,经常操作一样的动作,让我想撞墙。偶又去研究了Linux下的shell 命令,哎,不是我说MicroSoft的系统不好,Linux的命令确实好使,特别是查询文档,日志分析的时候,只要你使用的好,基本都能完成你的任务。像grep,gawk,wc,head,hail etc.这样的命令总是能给我们带来惊喜。Linux系统还是要好好学的,虽然和widows差别很大,但是很强,很方便。下面我就来说说用JAVASE怎么操作这些庞然大物的。

先介绍下我要操作的文本文件

[28-03-2008 00:00:00.101] |SH1|CIC015|->|SH1|AG015| >>IAM|CN15|CD51001500|CG15921351879|PA0|PB1|<<
[28-03-2008 00:00:00.101] |SH1|CIC153|->|SH1|AG144| >>IAM|CN144|CD51001500|CG13761957943|PA0|PB1|<<
[28-03-2008 00:00:00.117] |SH1|CIC015|<-|SH1|AG015| >>ACM|CN15|<<
[28-03-2008 00:00:00.117] |SH1|CIC153|<-|SH1|AG144| >>ACM|CN144|<<
[28-03-2008 00:00:00.179] |SH1|CIC111|->|SH1|AG105| >>REL|CN105|PA16|PB0|PC4|<<
[28-03-2008 00:00:00.179] |SH1|CIC111|<-|SH1|AG105| >>RLC|CN105|<<
[28-03-2008 00:00:00.273] |SH1|CIC1373|->|SH3|AG118| >>ANM|CN118|<<
[28-03-2008 00:00:00.383] |SH1|CIC1365|<-|SH3|AG110| >>REL|CN110|PA16|<<
[28-03-2008 00:00:00.461] |SH1|CIC1365|->|SH3|AG110| >>RLC|CN110|<<
[28-03-2008 00:00:00.586] |SH1|CIC2577|->|S11|AG196| >>ANM|CN196|<<

大家不要头晕,这个本来就是日志,搞过No.7的人都看的懂,不过这个不是重点了。我们要处理就是这样的文件,JAVASE里有一个新的包 java.nio,具体干啥的,我就不说了,自己去查看API吧。下面贴出具体代码,大家重点看getResult() 方法。在里面使用了MappedByteBuffer把文件映射到内存里面去,然后使用缓存的技术把他再读出来,如果不适用缓存,速度会很慢,想在这个里面查个东西,至少要7分钟以上,使用了缓存整个文件遍历最多13秒,差距很大吧,这个时间还是和硬件有关系的,我的电脑比较烂了,我老婆经常说我的是“低廉的双核”,我那个汗啊!o(∩_∩)o...,大家好好看看里面的代码吧。希望能对经常和大型文件打交道的人有个帮助!

 
package com.xhp.ss7 ;

import java.io.File ;
import java.io.RandomAccessFile ;
import java.io.BufferedReader ;
import java.io.StringReader ;
import java.util.List ;
import java.util.ArrayList ;
import java.util.Date ;
import java.util.regex.Pattern ;
import java.util.regex.Matcher ;
import java.nio.MappedByteBuffer ;
import java.nio.channels.FileChannel ;


public class SS7Handle...{
    
private String year ;
    
private String month ;
    
private String day ;
    
private long length ;
    
private File file ;
    
private int bufferSize = 0x600000;// 默认6M的缓冲 ;
    private long diff ;
    
    
    
public SS7Handle(String path)...{
        
this.loadFile(path) ;
    }

    
    
public List<String> getResult(int type,String number,String time,String minute,String second,int count)...{
        List
<String> result = new ArrayList<String>() ;
        String strRex 
= getStrRex(type,number,time,minute,second) ;
        Pattern pattern 
= Pattern.compile(strRex) ;
        
int counts = count ;
        Date begin 
= null ;
        Date end 
= null ;
        
try...{
            MappedByteBuffer inputBuffer 
= new RandomAccessFile(file,"r").getChannel()
                                .map(FileChannel.MapMode.READ_ONLY, 
0, length);
            
byte[] dst = new byte[bufferSize] ; //每次读出6M的内容 
            BufferedReader br = null ;
            
boolean findFirst  = false ; 
            
boolean over = false ;
            begin 
= new Date() ;        
            
for(int offset=0; offset < length; offset+= bufferSize)...{
                
//for(int offset=0; offset < 1; offset+= bufferSize){
                    
                
if(length - offset >= bufferSize)...{
                    
for(int i = 0;i < bufferSize;i++)
                              dst[i] 
= inputBuffer.get(offset + i);
                }
else...{
                    
for(int i = 0;i < length - offset;i++)
                    dst[i] 
= inputBuffer.get(offset + i);
                }

                
//把得到的dst 交给 BufferedReader 按行读出
                br = new BufferedReader(new StringReader(new String(dst))) ;
                String line ;
                StringBuffer next 
= new StringBuffer() ;

                
while((line=br.readLine()) != null )...{
                    
if(!findFirst)...{    
                        
if(pattern.matcher(line).find())...{
                                System.out.println(
"line-->"+line) ;
                                counts
-- ;
                                result.add(line) ;
                                findFirst 
= true ;
                                String[] temp 
= line.split("|") ;
                                next.append(temp[
4]).append("|").append(temp[5]) ;
                        }

                    }
else if(findFirst) ...{
                        
if(line.contains(next.toString()))...{
                            System.out.println(next) ;
                            result.add(line) ;
                            counts
-- ;
                        }

                    }

                    
if(counts<0)...{
                        over 
= true ;
                        
break ;
                    }
 
                }
            
                br.close() ;
                
if(over)...{
                    
break ;
                }
       
            }

            end 
= new Date();
            
this.setDiff(end.getTime()-begin.getTime()) ;
        }
catch(Exception e)...{
            System.out.println(
"error") ;
        }

        
return result ;
    }
 
    
    
    
private String getStrRex(int type,String number,String hour,String minute,String second)...{
        
if(0<minute.length() && minute.length()<2)...{
            minute 
= "0"+minute ;
        }
else if(0<second.length() && second.length()<2)...{
            second 
= "0" +second ;
        }

        StringBuffer temp 
= new StringBuffer() ;
        
if(type == 1)...{  // 查询 系统 打出的电话
            String outnumber = "CD"+number ;
            temp.append(
"^[").append(day).append("-").append(month).append("-").append(year)
                            .append(
" ").append(hour)
                            .append(
!(minute.trim()==null || "".equals(minute.trim()))?(":"+minute):"")
                            .append(
!(second.trim()==null || "".equals(second.trim()))?(":"+second):"")
                            .append(
".*<-.*IAM.*").append(outnumber).append(".*") ;
            System.out.println(temp.toString()) ; 
        }
else if(type ==2)...{  //查询 用户打进的 电话
            String innumber = "CG" + number ;
            temp.append(
"^[").append(day).append("-").append(month).append("-").append(year)
                            .append(
" ").append(hour)
                            .append(
!(minute.trim()==null || "".equals(minute.trim()))?(":"+minute):"")
                            .append(
!(second.trim()==null || "".equals(second.trim()))?(":"+second):"")
                            .append(
".*->.*IAM.*").append(innumber).append(".*") ; 
        }

        
return temp.toString() ;
    }

    
    
public void loadFile(String path)...{
        
this.file = new File(path) ;  
        
this.setLength(file.length()) ;
        
int pathLength = path.length() ;
        
int start = pathLength - new String("xxxxxxxx_xxx.xxx").length() ;
        
this.setYear(path.substring(start,start+4)) ;
        
this.setMonth(path.substring(start+4,start+6)) ;
        
this.setDay(path.substring(start+6,start+8)) ;
    }

    
    
public void setYear(String year)...{
        
this.year = year ;
    }

    
public void setMonth(String month)...{
        
this.month = month ;
    }

    
public void setDay(String day)...{
        
this.day = day ;
    }

    
private void setLength(long length)...{
        
this.length = length ;
    }

    
public void setDiff(long diff)...{
        
this.diff = diff ;
    }

    
public long getDiff()...{
        
return this.diff ;
    }

    
public long getLength()...{
        
return this.length ;
    }

    
public String getYear()...{
        
return this.year ;
    }

    
public String getMonth()...{
        
return this.month ;
    }

    
public String getDay()...{
        
return this.day ;
    }

    
public String toString()...{
        
return this.year+"-"+this.month+"-"+this.day ;
    }


}
原创粉丝点击