java 解析ip

    package com.showtime.IPparse;  
      
    import java.io.File;  
    import java.io.FileNotFoundException;  
    import java.io.IOException;  
    import java.io.RandomAccessFile;  
    import java.nio.ByteOrder;  
    import java.nio.MappedByteBuffer;  
    import java.nio.channels.FileChannel;  
    import java.util.ArrayList;  
    import java.util.HashMap;  
    import java.util.List;  
    import java.util.Map;  
    import com.showtime.util.LogFactory;  
    import org.apache.log4j.Level;  
      
    public class IPSeeker {  
        //纯真IP数据库名  
        private String IP_FILE="QQWry.Dat";  
        //保存的文件夹  
        private String INSTALL_DIR="f:/qqwry";  
          
          
        // 一些固定常量,比如记录长度等等  
        private static final int IP_RECORD_LENGTH = 7;  
        private static final byte REDIRECT_MODE_1 = 0x01;  
        private static final byte REDIRECT_MODE_2 = 0x02;  
          
        // 用来做为cache,查询一个ip时首先查看cache,以减少不必要的重复查找  
        private Map<String, IPLocation> ipCache;  
        // 随机文件访问类  
        private RandomAccessFile ipFile;  
        // 内存映射文件  
        private MappedByteBuffer mbb;  
        // 起始地区的开始和结束的绝对偏移  
        private long ipBegin, ipEnd;  
        // 为提高效率而采用的临时变量  
        private IPLocation loc;  
        private byte[] buf;  
        private byte[] b4;  
        private byte[] b3;  
          
        public IPSeeker(String fileName,String dir)  {  
            this.INSTALL_DIR=dir;  
            this.IP_FILE=fileName;  
            ipCache = new HashMap<String, IPLocation>();  
            loc = new IPLocation();  
            buf = new byte[100];  
            b4 = new byte[4];  
            b3 = new byte[3];  
            try {  
                ipFile = new RandomAccessFile(IP_FILE, "r");  
            } catch (FileNotFoundException e) {  
                // 如果找不到这个文件,再尝试再当前目录下搜索,这次全部改用小写文件名  
                //     因为有些系统可能区分大小写导致找不到ip地址信息文件  
                String filename = new File(IP_FILE).getName().toLowerCase();  
                File[] files = new File(INSTALL_DIR).listFiles();  
                for(int i = 0; i < files.length; i++) {  
                    if(files[i].isFile()) {  
                        if(files[i].getName().toLowerCase().equals(filename)) {  
                            try {  
                                ipFile = new RandomAccessFile(files[i], "r");  
                            } catch (FileNotFoundException e1) {  
                                LogFactory.log("IP地址信息文件没有找到,IP显示功能将无法使用",Level.ERROR,e1);  
                                ipFile = null;  
                            }  
                            break;  
                        }  
                    }  
                }  
            }   
            // 如果打开文件成功,读取文件头信息  
            if(ipFile != null) {  
                try {  
                    ipBegin = readLong4(0);  
                    ipEnd = readLong4(4);  
                    if(ipBegin == -1 || ipEnd == -1) {  
                        ipFile.close();  
                        ipFile = null;  
                    }             
                } catch (IOException e) {  
                    LogFactory.log("IP地址信息文件格式有错误,IP显示功能将无法使用",Level.ERROR,e);  
                    ipFile = null;  
                }             
            }  
        }  
          
          
        /** 
         * 给定一个地点的不完全名字,得到一系列包含s子串的IP范围记录 
         * @param s 地点子串 
         * @return 包含IPEntry类型的List 
         */  
        public List getIPEntriesDebug(String s) {  
            List<IPEntry> ret = new ArrayList<IPEntry>();  
            long endOffset = ipEnd + 4;  
            for(long offset = ipBegin + 4; offset <= endOffset; offset += IP_RECORD_LENGTH) {  
                // 读取结束IP偏移  
                long temp = readLong3(offset);  
                // 如果temp不等于-1,读取IP的地点信息  
                if(temp != -1) {  
                    IPLocation ipLoc = getIPLocation(temp);  
                    // 判断是否这个地点里面包含了s子串,如果包含了,添加这个记录到List中,如果没有,继续  
                    if(ipLoc.getCountry().indexOf(s) != -1 || ipLoc.getArea().indexOf(s) != -1) {  
                        IPEntry entry = new IPEntry();  
                        entry.country = ipLoc.getCountry();  
                        entry.area = ipLoc.getArea();  
                        // 得到起始IP  
                        readIP(offset - 4, b4);  
                        entry.beginIp = Util.getIpStringFromBytes(b4);  
                        // 得到结束IP  
                        readIP(temp, b4);  
                        entry.endIp = Util.getIpStringFromBytes(b4);  
                        // 添加该记录  
                        ret.add(entry);  
                    }  
                }  
            }  
            return ret;  
        }  
          
        public IPLocation getIPLocation(String ip){  
            IPLocation location=new IPLocation();  
            location.setArea(this.getArea(ip));  
            location.setCountry(this.getCountry(ip));  
            return location;  
        }  
          
        /** 
         * 给定一个地点的不完全名字,得到一系列包含s子串的IP范围记录 
         * @param s 地点子串 
         * @return 包含IPEntry类型的List 
         */  
        public List<IPEntry> getIPEntries(String s) {  
            List<IPEntry> ret = new ArrayList<IPEntry>();  
            try {  
                // 映射IP信息文件到内存中  
                if(mbb == null) {  
                    FileChannel fc = ipFile.getChannel();  
                    mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, ipFile.length());  
                    mbb.order(ByteOrder.LITTLE_ENDIAN);               
                }  
                  
                int endOffset = (int)ipEnd;  
                for(int offset = (int)ipBegin + 4; offset <= endOffset; offset += IP_RECORD_LENGTH) {  
                    int temp = readInt3(offset);  
                    if(temp != -1) {  
                        IPLocation ipLoc = getIPLocation(temp);  
                        // 判断是否这个地点里面包含了s子串,如果包含了,添加这个记录到List中,如果没有,继续  
                        if(ipLoc.getCountry().indexOf(s) != -1 || ipLoc.getArea().indexOf(s) != -1) {  
                            IPEntry entry = new IPEntry();  
                            entry.country = ipLoc.getCountry();  
                            entry.area = ipLoc.getArea();  
                            // 得到起始IP  
                            readIP(offset - 4, b4);  
                            entry.beginIp = Util.getIpStringFromBytes(b4);  
                            // 得到结束IP  
                            readIP(temp, b4);  
                            entry.endIp = Util.getIpStringFromBytes(b4);  
                            // 添加该记录  
                            ret.add(entry);  
                        }  
                    }  
                }             
            } catch (IOException e) {  
                LogFactory.log("",Level.ERROR,e);  
            }  
            return ret;  
        }  
      
        /** 
         * 从内存映射文件的offset位置开始的3个字节读取一个int 
         * @param offset 
         * @return 
         */  
        private int readInt3(int offset) {  
            mbb.position(offset);  
            return mbb.getInt() & 0x00FFFFFF;  
        }  
      
        /** 
         * 从内存映射文件的当前位置开始的3个字节读取一个int 
         * @return 
         */  
        private int readInt3() {  
            return mbb.getInt() & 0x00FFFFFF;  
        }  
          
        /** 
         * 根据IP得到国家名 
         * @param ip ip的字节数组形式 
         * @return 国家名字符串 
         */  
        public String getCountry(byte[] ip) {  
            // 检查ip地址文件是否正常  
            if(ipFile == null)   
                return Message.bad_ip_file;  
            // 保存ip,转换ip字节数组为字符串形式  
            String ipStr = Util.getIpStringFromBytes(ip);  
            // 先检查cache中是否已经包含有这个ip的结果,没有再搜索文件  
            if(ipCache.containsKey(ipStr)) {  
                IPLocation ipLoc = ipCache.get(ipStr);  
                return ipLoc.getCountry();  
            } else {  
                IPLocation ipLoc = getIPLocation(ip);  
                ipCache.put(ipStr, ipLoc.getCopy());  
                return ipLoc.getCountry();  
            }  
        }  
          
        /** 
         * 根据IP得到国家名 
         * @param ip IP的字符串形式 
         * @return 国家名字符串 
         */  
        public String getCountry(String ip) {  
            return getCountry(Util.getIpByteArrayFromString(ip));  
        }  
          
        /** 
         * 根据IP得到地区名 
         * @param ip ip的字节数组形式 
         * @return 地区名字符串 
         */  
        public String getArea(byte[] ip) {  
            // 检查ip地址文件是否正常  
            if(ipFile == null)   
                return Message.bad_ip_file;  
            // 保存ip,转换ip字节数组为字符串形式  
            String ipStr = Util.getIpStringFromBytes(ip);  
            // 先检查cache中是否已经包含有这个ip的结果,没有再搜索文件  
            if(ipCache.containsKey(ipStr)) {  
                IPLocation ipLoc = ipCache.get(ipStr);  
                return ipLoc.getArea();  
            } else {  
                IPLocation ipLoc = getIPLocation(ip);  
                ipCache.put(ipStr, ipLoc.getCopy());  
                return ipLoc.getArea();  
            }  
        }  
          
        /** 
         * 根据IP得到地区名 
         * @param ip IP的字符串形式 
         * @return 地区名字符串 
         */  
        public String getArea(String ip) {  
            return getArea(Util.getIpByteArrayFromString(ip));  
        }  
          
        /** 
         * 根据ip搜索ip信息文件,得到IPLocation结构,所搜索的ip参数从类成员ip中得到 
         * @param ip 要查询的IP 
         * @return IPLocation结构 
         */  
        private IPLocation getIPLocation(byte[] ip) {  
            IPLocation info = null;  
            long offset = locateIP(ip);  
            if(offset != -1)  
                info = getIPLocation(offset);  
            if(info == null) {  
                info = new IPLocation();  
                info.setCountry (  Message.unknown_country);  
                info.setArea(Message.unknown_area);  
            }  
            return info;  
        }     
      
        /** 
         * 从offset位置读取4个字节为一个long,因为java为big-endian格式,所以没办法 
         * 用了这么一个函数来做转换 
         * @param offset 
         * @return 读取的long值,返回-1表示读取文件失败 
         */  
        private long readLong4(long offset) {  
            long ret = 0;  
            try {  
                ipFile.seek(offset);  
                ret |= (ipFile.readByte() & 0xFF);  
                ret |= ((ipFile.readByte() << 8) & 0xFF00);  
                ret |= ((ipFile.readByte() << 16) & 0xFF0000);  
                ret |= ((ipFile.readByte() << 24) & 0xFF000000);  
                return ret;  
            } catch (IOException e) {  
                return -1;  
            }  
        }  
      
        /** 
         * 从offset位置读取3个字节为一个long,因为java为big-endian格式,所以没办法 
         * 用了这么一个函数来做转换 
         * @param offset 整数的起始偏移 
         * @return 读取的long值,返回-1表示读取文件失败 
         */  
        private long readLong3(long offset) {  
            long ret = 0;  
            try {  
                ipFile.seek(offset);  
                ipFile.readFully(b3);  
                ret |= (b3[0] & 0xFF);  
                ret |= ((b3[1] << 8) & 0xFF00);  
                ret |= ((b3[2] << 16) & 0xFF0000);  
                return ret;  
            } catch (IOException e) {  
                return -1;  
            }  
        }     
          
        /** 
         * 从当前位置读取3个字节转换成long 
         * @return 读取的long值,返回-1表示读取文件失败 
         */  
        private long readLong3() {  
            long ret = 0;  
            try {  
                ipFile.readFully(b3);  
                ret |= (b3[0] & 0xFF);  
                ret |= ((b3[1] << 8) & 0xFF00);  
                ret |= ((b3[2] << 16) & 0xFF0000);  
                return ret;  
            } catch (IOException e) {  
                return -1;  
            }  
        }  
        
        /** 
         * 从offset位置读取四个字节的ip地址放入ip数组中,读取后的ip为big-endian格式,但是 
         * 文件中是little-endian形式,将会进行转换 
         * @param offset 
         * @param ip 
         */  
        private void readIP(long offset, byte[] ip) {  
            try {  
                ipFile.seek(offset);  
                ipFile.readFully(ip);  
                byte temp = ip[0];  
                ip[0] = ip[3];  
                ip[3] = temp;  
                temp = ip[1];  
                ip[1] = ip[2];  
                ip[2] = temp;  
            } catch (IOException e) {  
                LogFactory.log("",Level.ERROR,e);  
            }  
        }  
          
        /** 
         * 从offset位置读取四个字节的ip地址放入ip数组中,读取后的ip为big-endian格式,但是 
         * 文件中是little-endian形式,将会进行转换 
         * @param offset 
         * @param ip 
         */  
        private void readIP(int offset, byte[] ip) {  
            mbb.position(offset);  
            mbb.get(ip);  
            byte temp = ip[0];  
            ip[0] = ip[3];  
            ip[3] = temp;  
            temp = ip[1];  
            ip[1] = ip[2];  
            ip[2] = temp;  
        }  
          
        /** 
         * 把类成员ip和beginIp比较,注意这个beginIp是big-endian的 
         * @param ip 要查询的IP 
         * @param beginIp 和被查询IP相比较的IP 
         * @return 相等返回0,ip大于beginIp则返回1,小于返回-1。 
         */  
        private int compareIP(byte[] ip, byte[] beginIp) {  
            for(int i = 0; i < 4; i++) {  
                int r = compareByte(ip[i], beginIp[i]);  
                if(r != 0)  
                    return r;  
            }  
            return 0;  
        }  
          
        /** 
         * 把两个byte当作无符号数进行比较 
         * @param b1 
         * @param b2 
         * @return 若b1大于b2则返回1,相等返回0,小于返回-1 
         */  
        private int compareByte(byte b1, byte b2) {  
            if((b1 & 0xFF) > (b2 & 0xFF)) // 比较是否大于  
                return 1;  
            else if((b1 ^ b2) == 0)// 判断是否相等  
                return 0;  
            else   
                return -1;  
        }  
          
        /** 
         * 这个方法将根据ip的内容,定位到包含这个ip国家地区的记录处,返回一个绝对偏移 
         * 方法使用二分法查找。 
         * @param ip 要查询的IP 
         * @return 如果找到了,返回结束IP的偏移,如果没有找到,返回-1 
         */  
        private long locateIP(byte[] ip) {  
            long m = 0;  
            int r;  
            // 比较第一个ip项  
            readIP(ipBegin, b4);  
            r = compareIP(ip, b4);  
            if(r == 0) return ipBegin;  
            else if(r < 0) return -1;  
            // 开始二分搜索  
            for(long i = ipBegin, j = ipEnd; i < j; ) {  
                m = getMiddleOffset(i, j);  
                readIP(m, b4);  
                r = compareIP(ip, b4);  
                // log.debug(Utils.getIpStringFromBytes(b));  
                if(r > 0)  
                    i = m;  
                else if(r < 0) {  
                    if(m == j) {  
                        j -= IP_RECORD_LENGTH;  
                        m = j;  
                    } else   
                        j = m;  
                } else  
                    return readLong3(m + 4);  
            }  
            // 如果循环结束了,那么i和j必定是相等的,这个记录为最可能的记录,但是并非  
            //     肯定就是,还要检查一下,如果是,就返回结束地址区的绝对偏移  
            m = readLong3(m + 4);  
            readIP(m, b4);  
            r = compareIP(ip, b4);  
            if(r <= 0) return m;  
            else return -1;  
        }  
          
        /** 
         * 得到begin偏移和end偏移中间位置记录的偏移 
         * @param begin 
         * @param end 
         * @return 
         */  
        private long getMiddleOffset(long begin, long end) {  
            long records = (end - begin) / IP_RECORD_LENGTH;  
            records >>= 1;  
            if(records == 0) records = 1;  
            return begin + records * IP_RECORD_LENGTH;  
        }  
          
        /** 
         * 给定一个ip国家地区记录的偏移,返回一个IPLocation结构 
         * @param offset 国家记录的起始偏移 
         * @return IPLocation对象 
         */  
        private IPLocation getIPLocation(long offset) {  
            try {  
                // 跳过4字节ip  
                ipFile.seek(offset + 4);  
                // 读取第一个字节判断是否标志字节  
                byte b = ipFile.readByte();  
                if(b == REDIRECT_MODE_1) {  
                    // 读取国家偏移  
                    long countryOffset = readLong3();  
                    // 跳转至偏移处  
                    ipFile.seek(countryOffset);  
                    // 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向  
                    b = ipFile.readByte();  
                    if(b == REDIRECT_MODE_2) {  
                        loc.setCountry (  readString(readLong3()));  
                        ipFile.seek(countryOffset + 4);  
                    } else  
                        loc.setCountry ( readString(countryOffset));  
                    // 读取地区标志  
                    loc.setArea( readArea(ipFile.getFilePointer()));  
                } else if(b == REDIRECT_MODE_2) {  
                    loc.setCountry ( readString(readLong3()));  
                    loc.setArea( readArea(offset + 8));  
                } else {  
                    loc.setCountry (  readString(ipFile.getFilePointer() - 1));  
                    loc.setArea( readArea(ipFile.getFilePointer()));  
                }  
                return loc;  
            } catch (IOException e) {  
                return null;  
            }  
        }     
          
        /** 
         * 给定一个ip国家地区记录的偏移,返回一个IPLocation结构,此方法应用与内存映射文件方式 
         * @param offset 国家记录的起始偏移 
         * @return IPLocation对象 
         */  
        private IPLocation getIPLocation(int offset) {  
            // 跳过4字节ip  
            mbb.position(offset + 4);  
            // 读取第一个字节判断是否标志字节  
            byte b = mbb.get();  
            if(b == REDIRECT_MODE_1) {  
                // 读取国家偏移  
                int countryOffset = readInt3();  
                // 跳转至偏移处  
                mbb.position(countryOffset);  
                // 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向  
                b = mbb.get();  
                if(b == REDIRECT_MODE_2) {  
                    loc.setCountry (  readString(readInt3()));  
                    mbb.position(countryOffset + 4);  
                } else  
                    loc.setCountry (  readString(countryOffset));  
                // 读取地区标志  
                loc.setArea(readArea(mbb.position()));  
            } else if(b == REDIRECT_MODE_2) {  
                loc.setCountry ( readString(readInt3()));  
                loc.setArea(readArea(offset + 8));  
            } else {  
                loc.setCountry (  readString(mbb.position() - 1));  
                loc.setArea(readArea(mbb.position()));  
            }  
            return loc;  
        }  
          
        /** 
         * 从offset偏移开始解析后面的字节,读出一个地区名 
         * @param offset 地区记录的起始偏移 
         * @return 地区名字符串 
         * @throws IOException 
         */  
        private String readArea(long offset) throws IOException {  
            ipFile.seek(offset);  
            byte b = ipFile.readByte();  
            if(b == REDIRECT_MODE_1 || b == REDIRECT_MODE_2) {  
                long areaOffset = readLong3(offset + 1);  
                if(areaOffset == 0)  
                    return Message.unknown_area;  
                else  
                    return readString(areaOffset);  
            } else  
                return readString(offset);  
        }  
          
        /** 
         * @param offset 地区记录的起始偏移 
         * @return 地区名字符串 
         */  
        private String readArea(int offset) {  
            mbb.position(offset);  
            byte b = mbb.get();  
            if(b == REDIRECT_MODE_1 || b == REDIRECT_MODE_2) {  
                int areaOffset = readInt3();  
                if(areaOffset == 0)  
                    return Message.unknown_area;  
                else  
                    return readString(areaOffset);  
            } else  
                return readString(offset);  
        }  
          
        /** 
         * 从offset偏移处读取一个以0结束的字符串 
         * @param offset 字符串起始偏移 
         * @return 读取的字符串,出错返回空字符串 
         */  
        private String readString(long offset) {  
            try {  
                ipFile.seek(offset);  
                int i;  
                for(i = 0, buf[i] = ipFile.readByte(); buf[i] != 0; buf[++i] = ipFile.readByte());  
                if(i != 0)   
                    return Util.getString(buf, 0, i, "GBK");  
            } catch (IOException e) {             
                LogFactory.log("",Level.ERROR,e);  
            }  
            return "";  
        }  
          
        /** 
         * 从内存映射文件的offset位置得到一个0结尾字符串 
         * @param offset 字符串起始偏移 
         * @return 读取的字符串,出错返回空字符串 
         */  
        private String readString(int offset) {  
            try {  
                mbb.position(offset);  
                int i;  
                for(i = 0, buf[i] = mbb.get(); buf[i] != 0; buf[++i] = mbb.get());  
                if(i != 0)   
                    return Util.getString(buf, 0, i, "GBK");         
            } catch (IllegalArgumentException e) {  
                LogFactory.log("",Level.ERROR,e);  
            }  
            return "";     
        }  
    }  



在实际项目用我使用spring注入IP地址库文件的名字和所在目录,并能保证IPSeeker的单一实例。


下面是个工具类,把string和btye数组之间互相转换的类。
Java代码  收藏代码

    package com.showtime.IPparse;  
      
      
    import java.io.UnsupportedEncodingException;  
    import java.util.StringTokenizer;  
      
    import org.apache.log4j.Level;  
      
    import  com.showtime.util.LogFactory;  
      
      
      
    /** 
     * 工具类,提供一些方便的方法 
     */  
    public class Util {  
          
        private static StringBuilder sb = new StringBuilder();  
        /** 
         * 从ip的字符串形式得到字节数组形式 
         * @param ip 字符串形式的ip 
         * @return 字节数组形式的ip 
         */  
        public static byte[] getIpByteArrayFromString(String ip) {  
            byte[] ret = new byte[4];  
            StringTokenizer st = new StringTokenizer(ip, ".");  
            try {  
                ret[0] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
                ret[1] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
                ret[2] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
                ret[3] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
            } catch (Exception e) {  
              LogFactory.log("从ip的字符串形式得到字节数组形式报错", Level.ERROR, e);  
            }  
            return ret;  
        }  
        /** 
         * @param ip ip的字节数组形式 
         * @return 字符串形式的ip 
         */  
        public static String getIpStringFromBytes(byte[] ip) {  
            sb.delete(0, sb.length());  
            sb.append(ip[0] & 0xFF);  
            sb.append('.');       
            sb.append(ip[1] & 0xFF);  
            sb.append('.');       
            sb.append(ip[2] & 0xFF);  
            sb.append('.');       
            sb.append(ip[3] & 0xFF);  
            return sb.toString();  
        }  
          
        /** 
         * 根据某种编码方式将字节数组转换成字符串 
         * @param b 字节数组 
         * @param offset 要转换的起始位置 
         * @param len 要转换的长度 
         * @param encoding 编码方式 
         * @return 如果encoding不支持,返回一个缺省编码的字符串 
         */  
        public static String getString(byte[] b, int offset, int len, String encoding) {  
            try {  
                return new String(b, offset, len, encoding);  
            } catch (UnsupportedEncodingException e) {  
                return new String(b, offset, len);  
            }  
        }  
    }  




下面是个常量值的类,用接口形式来定义省事不少。
Java代码  收藏代码

    package com.showtime.IPparse;  
      
    public interface Message {  
        String bad_ip_file="IP地址库文件错误";  
        String unknown_country="未知国家";  
        String unknown_area="未知地区";  
    }  




一个封装国家和地区的实体类
Java代码  收藏代码

    package com.showtime.IPparse;  
      
      
    /**  
     *  
     * @category 用来封装ip相关信息,目前只有两个字段,ip所在的国家和地区 
     */  
      
    public class IPLocation {  
        private String country;  
        private String area;  
          
        public IPLocation() {  
            country = area = "";  
        }  
          
        public IPLocation getCopy() {  
            IPLocation ret = new IPLocation();  
            ret.country = country;  
            ret.area = area;  
            return ret;  
        }  
      
        public String getCountry() {  
            return country;  
        }  
      
        public void setCountry(String country) {  
            this.country = country;  
        }  
      
        public String getArea() {  
            return area;  
        }  
      
        public void setArea(String area) {  
                    //如果为局域网,纯真IP地址库的地区会显示CZ88.NET,这里把它去掉  
            if(area.trim().equals("CZ88.NET")){  
                this.area="本机或本网络";  
            }else{  
                this.area = area;  
            }  
        }  
    }  




一下是一个范围记录的类
Java代码  收藏代码

    package com.showtime.IPparse;  
    /** 
     * <pre> 
     * 一条IP范围记录,不仅包括国家和区域,也包括起始IP和结束IP 
     * </pre> 
     */  
    public class IPEntry {  
        public String beginIp;  
        public String endIp;  
        public String country;  
        public String area;  
          
        /** 
         * 构造函数 
         */  
        public IPEntry() {  
            beginIp = endIp = country = area = "";  
        }  
    }  



日志记录类
Java代码  收藏代码

    package com.showtime.util;  
      
    import org.apache.log4j.Level;  
    import org.apache.log4j.Logger;  
      
    /** 
     *  
     *  
     * 日志工厂 
     */  
    public class LogFactory {  
        private static final Logger logger;  
        static {  
            logger = Logger.getLogger("stdout");  
            logger.setLevel(Level.DEBUG);  
        }  
      
        public static void log(String info, Level level, Throwable ex) {  
            logger.log(level, info, ex);  
        }  
          
        public static Level  getLogLevel(){  
            return logger.getLevel();  
        }  
      
    }  



下面是测试类
Java代码  收藏代码

    package com.showtime.IPparse;  
      
    import junit.framework.TestCase;  
      
    public class IPtest extends TestCase {  
          
        public void testIp(){  
                    //指定纯真数据库的文件名,所在文件夹  
            IPSeeker ip=new IPSeeker("QQWry.Dat","f:/qqwry");  
             //测试IP 58.20.43.13  
    System.out.println(ip.getIPLocation("58.20.43.13").getCountry()+":"+ip.getIPLocation("58.20.43.13").getArea());  
        }  
    }  


当输出:湖南省长沙市:网通
 前几天看了下Ruby的IPParse,觉得很过瘾,上网查了下貌似很多IP数据库都要收费的,就下了个纯真QQIP地址库,发现还可以在线升级的,很适合咱做点小玩意。具体解析的纯真版IP地址库请详见http://lumaqq.linuxsir.org/article/qqwry_format_detail.html,这里就不多叙述了。
看下JAVA代码中怎么解析IP的吧。(代码参考至lumaQQ.谢谢开源作者luma) 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值