zoukankan      html  css  js  c++  java
  • 读取QQWry.Dat的IP信息操作类

    2008-09-16 09:25

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO;
    using System.Web;
    using System.Configuration;

    namespace BLL
    {
        public class IPLocationSearch
        {
            private static readonly QQWry qq = new QQWry(ConfigurationManager.AppSettings["ip"] + "qqwry.dat");

            public static IPLocation GetIPLocation(string ip)
            {
                return qq.SearchIPLocation(ip);
            }
        }

        /*
        使用方法:

        例子:
        BDQQ.Data.QQWry qq=new BDQQ.Data.QQWry("d:""QQWry.Dat");
        BDQQ.Data.IPLocation ip=qq.SearchIPLocation("127.0.0.1");//这里添写IP地址
        Console.WriteLine(ip.country);//国家
        Console.WriteLine(ip.area);//地区
        */

        //以下是类文件
        //根据LumaQQ改写而成.

        /**/
        ///<summary>
        /// QQWry 的摘要说明。
        ///</summary>
        public class QQWry
        {
            //第一种模式
            #region 第一种模式
            /**/
            ///<summary>
            ///第一种模式
            ///</summary>
            #endregion
            private const byte REDIRECT_MODE_1 = 0x01;

            //第二种模式
            #region 第二种模式
            /**/
            ///<summary>
            ///第二种模式
            ///</summary>
            #endregion
            private const byte REDIRECT_MODE_2 = 0x02;

            //每条记录长度
            #region 每条记录长度
            /**/
            ///<summary>
            ///每条记录长度
            ///</summary>
            #endregion
            private const int IP_RECORD_LENGTH = 7;

            //数据库文件
            #region 数据库文件
            /**/
            ///<summary>
            ///文件对象
            ///</summary>
            #endregion
            private FileStream ipFile;

            private const string unCountry = "未知国家";
            private const string unArea = "未知地区";

            //索引开始位置
            #region 索引开始位置
            /**/
            ///<summary>
            ///索引开始位置
            ///</summary>
            #endregion
            private long ipBegin;

            //索引结束位置
            #region 索引结束位置
            /**/
            ///<summary>
            ///索引结束位置
            ///</summary>
            #endregion
            private long ipEnd;

            //IP地址对象
            #region IP地址对象
            /**/
            ///<summary>
            /// IP对象
            ///</summary>
            #endregion
            private IPLocation loc;

            //存储文本内容
            #region 存储文本内容
            /**/
            ///<summary>
            ///存储文本内容
            ///</summary>
            #endregion
            private byte[] buf;

            //存储3字节
            #region 存储3字节
            /**/
            ///<summary>
            ///存储3字节
            ///</summary>
            #endregion
            private byte[] b3;

            //存储4字节
            #region 存储4字节
            /**/
            ///<summary>
            ///存储4字节IP地址
            ///</summary>
            #endregion
            private byte[] b4;

            //构造函数
            #region 构造函数
            /**/
            ///<summary>
            ///构造函数
            ///</summary>
            ///<param name="ipfile">IP数据库文件绝对路径</param>
            #endregion
            public QQWry(string ipfile)
            {

                buf = new byte[100];
                b3 = new byte[3];
                b4 = new byte[4];
                try
                {
                    ipFile = new FileStream(ipfile, FileMode.Open);
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
                ipBegin = readLong4(0);
                ipEnd = readLong4(4);
                loc = new IPLocation();
            }

            //根据IP地址搜索
            #region 根据IP地址搜索
            /**/
            ///<summary>
            ///搜索IP地址搜索
            ///</summary>
            ///<param name="ip"></param>
            ///<returns></returns>
            #endregion
            public IPLocation SearchIPLocation(string ip)
            {
                //将字符IP转换为字节
                string[] ipSp = ip.Split('.');
                if (ipSp.Length != 4)
                {
                    throw new ArgumentOutOfRangeException("不是合法的IP地址!");
                }
                byte[] IP = new byte[4];
                for (int i = 0; i < IP.Length; i++)
                {
                    IP[i] = (byte)(Int32.Parse(ipSp[i]) & 0xFF);
                }

                IPLocation local = null;
                long offset = locateIP(IP);

                if (offset != -1)
                {
                    local = getIPLocation(offset);
                }

                if (local == null)
                {
                    local = new IPLocation();
                    local.area = unArea;
                    local.country = unCountry;
                }
                return local;
            }

            //取得具体信息
            #region 取得具体信息
            /**/
            ///<summary>
            ///取得具体信息
            ///</summary>
            ///<param name="offset"></param>
            ///<returns></returns>
            #endregion
            private IPLocation getIPLocation(long offset)
            {
                ipFile.Position = offset + 4;
                //读取第一个字节判断是否是标志字节
                byte one = (byte)ipFile.ReadByte();
                if (one == REDIRECT_MODE_1)
                {
                    //第一种模式
                    //读取国家偏移
                    long countryOffset = readLong3();
                    //转至偏移处
                    ipFile.Position = countryOffset;
                    //再次检查标志字节
                    byte b = (byte)ipFile.ReadByte();
                    if (b == REDIRECT_MODE_2)
                    {
                        loc.country = readString(readLong3());
                        ipFile.Position = countryOffset + 4;
                    }
                    else
                        loc.country = readString(countryOffset);

                    //读取地区标志
                    loc.area = readArea(ipFile.Position);

                }
                else if (one == REDIRECT_MODE_2)
                {
                    //第二种模式
                    loc.country = readString(readLong3());
                    loc.area = readArea(offset + 8);
                }
                else
                {
                    //普通模式
                    loc.country = readString(--ipFile.Position);
                    loc.area = readString(ipFile.Position);
                }
                return loc;
            }

            //取得地区信息
            #region 取得地区信息
            /**/
            ///<summary>
            ///读取地区名称
            ///</summary>
            ///<param name="offset"></param>
            ///<returns></returns>
            #endregion
            private string readArea(long offset)
            {
                ipFile.Position = offset;
                byte one = (byte)ipFile.ReadByte();
                if (one == REDIRECT_MODE_1 || one == REDIRECT_MODE_2)
                {
                    long areaOffset = readLong3(offset + 1);
                    if (areaOffset == 0)
                        return unArea;
                    else
                    {
                        return readString(areaOffset);
                    }
                }
                else
                {
                    return readString(offset);
                }
            }

            //读取字符串
            #region 读取字符串
            /**/
            ///<summary>
            ///读取字符串
            ///</summary>
            ///<param name="offset"></param>
            ///<returns></returns>
            #endregion
            private string readString(long offset)
            {
                ipFile.Position = offset;
                int i = 0;
                for (i = 0, buf[i] = (byte)ipFile.ReadByte(); buf[i] != (byte)(0); buf[++i] = (byte)ipFile.ReadByte()) ;

                if (i > 0)
                    return Encoding.Default.GetString(buf, 0, i);
                else
                    return "";
            }

            //查找IP地址所在的绝对偏移量
            #region 查找IP地址所在的绝对偏移量
            /**/
            ///<summary>
            ///查找IP地址所在的绝对偏移量
            ///</summary>
            ///<param name="ip"></param>
            ///<returns></returns>
            #endregion
            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 = this.getMiddleOffset(i, j);
                    readIP(m, b4);
                    r = compareIP(ip, b4);
                    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);
                }
                m = readLong3(m + 4);
                readIP(m, b4);
                r = compareIP(ip, b4);
                if (r <= 0)
                    return m;
                else
                    return -1;
            }

            //读出4字节的IP地址
            #region 读出4字节的IP地址
            /**/
            ///<summary>
            ///从当前位置读取四字节,此四字节是IP地址
            ///</summary>
            ///<param name="offset"></param>
            ///<param name="ip"></param>
            #endregion
            private void readIP(long offset, byte[] ip)
            {
                ipFile.Position = offset;
                ipFile.Read(ip, 0, ip.Length);
                byte tmp = ip[0];
                ip[0] = ip[3];
                ip[3] = tmp;
                tmp = ip[1];
                ip[1] = ip[2];
                ip[2] = tmp;
            }

            //比较IP地址是否相同
            #region 比较IP地址是否相同
            /**/
            ///<summary>
            ///比较IP地址是否相同
            ///</summary>
            ///<param name="ip"></param>
            ///<param name="beginIP"></param>
            ///<returns>0:相等,1:ip大于beginIP,-1:小于</returns>
            #endregion
            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;
            }

            //比较两个字节是否相等
            #region 比较两个字节是否相等
            /**/
            ///<summary>
            ///比较两个字节是否相等
            ///</summary>
            ///<param name="bsrc"></param>
            ///<param name="bdst"></param>
            ///<returns></returns>
            #endregion
            private int compareByte(byte bsrc, byte bdst)
            {
                if ((bsrc & 0xFF) > (bdst & 0xFF))
                    return 1;
                else if ((bsrc ^ bdst) == 0)
                    return 0;
                else
                    return -1;
            }

            //根据当前位置读取4字节
            #region 根据当前位置读取4字节
            /**/
            ///<summary>
            ///从当前位置读取4字节,转换为长整型
            ///</summary>
            ///<param name="offset"></param>
            ///<returns></returns>
            #endregion
            private long readLong4(long offset)
            {
                long ret = 0;
                ipFile.Position = offset;
                ret |= (ipFile.ReadByte() & 0xFF);
                ret |= ((ipFile.ReadByte() << 8) & 0xFF00);
                ret |= ((ipFile.ReadByte() << 16) & 0xFF0000);
                ret |= ((ipFile.ReadByte() << 24) & 0xFF000000);
                return ret;
            }

            //根据当前位置,读取3字节
            #region 根据当前位置,读取3字节
            /**/
            ///<summary>
            ///根据当前位置,读取3字节
            ///</summary>
            ///<param name="offset"></param>
            ///<returns></returns>
            #endregion
            private long readLong3(long offset)
            {
                long ret = 0;
                ipFile.Position = offset;
                ret |= (ipFile.ReadByte() & 0xFF);
                ret |= ((ipFile.ReadByte() << 8) & 0xFF00);
                ret |= ((ipFile.ReadByte() << 16) & 0xFF0000);
                return ret;
            }

            //从当前位置读取3字节
            #region 从当前位置读取3字节
            /**/
            ///<summary>
            ///从当前位置读取3字节
            ///</summary>
            ///<returns></returns>
            #endregion
            private long readLong3()
            {
                long ret = 0;
                ret |= (ipFile.ReadByte() & 0xFF);
                ret |= ((ipFile.ReadByte() << 8) & 0xFF00);
                ret |= ((ipFile.ReadByte() << 16) & 0xFF0000);
                return ret;
            }

            //取得begin和end之间的偏移量
            #region 取得begin和end之间的偏移量
            /**/
            ///<summary>
            ///取得begin和end中间的偏移
            ///</summary>
            ///<param name="begin"></param>
            ///<param name="end"></param>
            ///<returns></returns>
            #endregion
            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;
            }
        } //class QQWry

        public class IPLocation
        {
            public String country;
            public String area;

            public IPLocation()
            {
                country = area = "";
            }

            public IPLocation getCopy()
            {
                IPLocation ret = new IPLocation();
                ret.country = country;
                ret.area = area;
                return ret;
            }
        }

    }

    2008年04月23日 星期三 17:11

    /******************************************************************
    ** File Name:IPExport.cs
    ** Copyright (c) 2004-2005 PPTech Studio(PPTech.Net)
    ** Creater:Rexsp(MSN:yubo@x263.net)
    ** Create Date:2004-12-29 20:10:28
    ** Modifier:
    ** Modify Date:
    ** Description:to export the ip location from qqwry.dat
    ** Version: IPExport 1.0.0
    ******************************************************************/
    using System;
    using System.Collections;
    using System.Data;
    using System.IO;

    namespace PPTech.ESP.Component
    {
    /// <summary>
    /// ExportData 的摘要说明。
    /// </summary>
    public class IPExport
    {
       #region 私有成员
       private string country;
       private string local;
       private FileStream objfs = null;
       private long startIp=0;
       private long endIp=0;
       private int countryFlag=0;
       private long endIpOff=0;
       #endregion
      
       #region 构造函数
       public IPExport()
       {
        //
        // TODO: 在此处添加构造函数逻辑
        //
       }
       #endregion

       #region 导出数据
       public void SaveToText(string toFilePath,string fromFilePath)
       {
        objfs = new FileStream(fromFilePath, FileMode.Open, FileAccess.Read);
        objfs.Position=0;
        byte[] buff1 = new Byte[8] ;
        objfs.Read(buff1,0,8);
        int firstStartIp=buff1[0]+buff1[1]*256+buff1[2]*256*256+buff1[3]*256*256*256;
        int lastStartIp=buff1[4]*1+buff1[5]*256+buff1[6]*256*256+buff1[7]*256*256*256;
        long recordCount=Convert.ToInt64((lastStartIp-firstStartIp)/7.0);
        if(recordCount<=1)
        {
         country="FileDataError";
         objfs.Close();
        }
        long rangE=recordCount;
        StreamWriter writer=File.AppendText(toFilePath);
        for(int i=0;i<=recordCount;i++)
        {
         long offSet = firstStartIp+i*7;
         objfs.Position=offSet;
       
         byte [] buff = new Byte[7];
         objfs.Read(buff,0,7);

         endIpOff=Convert.ToInt64(buff[4].ToString())+Convert.ToInt64(buff[5].ToString())*256+Convert.ToInt64(buff[6].ToString())*256*256;
         startIp=Convert.ToInt64(buff[0].ToString())+Convert.ToInt64(buff[1].ToString())*256+Convert.ToInt64(buff[2].ToString())*256*256+Convert.ToInt64(buff[3].ToString())*256*256*256;
        
         objfs.Position=endIpOff;
         byte [] buff3 = new Byte[5];
         objfs.Read(buff3,0,5);
         this.endIp=Convert.ToInt64(buff3[0].ToString())+Convert.ToInt64(buff3[1].ToString())*256+Convert.ToInt64(buff3[2].ToString())*256*256+Convert.ToInt64(buff3[3].ToString())*256*256*256;
         this.countryFlag=buff3[4];
         string showIP=this.IntToIP(startIp);
         this.GetCountry();
         writer.WriteLine(showIP+" "+this.country+this.local);
        }
        writer.Close();

       }
    #endregion

       #region int转换成IP
       private string IntToIP(long ip_Int)
       {
        long seg1=(ip_Int&0xff000000)>>24;
        if(seg1<0)
         seg1+=0x100;
        long seg2=(ip_Int&0x00ff0000)>>16;
        if(seg2<0)
         seg2+=0x100;
        long seg3=(ip_Int&0x0000ff00)>>8;
        if(seg3<0)
         seg3+=0x100;
        long seg4=(ip_Int&0x000000ff);
        if(seg4<0)
         seg4+=0x100;
        string ip=seg1.ToString()+"."+seg2.ToString()+"."+seg3.ToString()+"."+seg4.ToString();

        return ip;
       }
       #endregion
      
       #region 获取国家/区域偏移量
       private string GetCountry()
       {
        switch(this.countryFlag)
        {
         case 1:
         case 2:
          this.country=GetFlagStr(this.endIpOff+4);
          this.local=( 1 == this.countryFlag )?" ":this.GetFlagStr(this.endIpOff+8);
          break;
         default:
          this.country=this.GetFlagStr(this.endIpOff+4);
          this.local=this.GetFlagStr(objfs.Position);
          break;
        }
        return " ";
       }
       #endregion

       #region 获取国家/区域字符串
       private string GetFlagStr(long offSet)
       {
        int flag=0;
        byte [] buff = new Byte[3];
        while(1==1)
        {
         //objfs.Seek(offSet,SeekOrigin.Begin);
         objfs.Position=offSet;
         flag = objfs.ReadByte();
         if(flag==1||flag==2)
         {
          objfs.Read(buff,0,3);
          if(flag==2)
          {
           this.countryFlag=2;
           this.endIpOff=offSet-4;
          }
          offSet=Convert.ToInt64(buff[0].ToString())+Convert.ToInt64(buff[1].ToString())*256+Convert.ToInt64(buff[2].ToString())*256*256;
         }
         else
         {
          break;
         }
        }
        if(offSet<12)
         return " ";
        objfs.Position=offSet;
        return GetStr();
       }
       #endregion

       #region GetStr
       private string GetStr()
       {
        byte lowC=0;
        byte upC=0;
        string str="";
        byte[] buff = new byte[2];
        while(1==1)
        {
         lowC= (Byte)objfs.ReadByte();
         if(lowC==0)
          break;
         if(lowC>127)
         {
          upC=(byte)objfs.ReadByte();
          buff[0]=lowC;
          buff[1]=upC;
          System.Text.Encoding enc = System.Text.Encoding.GetEncoding("GB2312");
          str+=enc.GetString(buff);
         }
         else
         {
          str+=(char)lowC;
         }
        }
        return str;
       }
       #endregion
    }
    }

    调用方式:

                #region 测试导出IP地址库
                IPExport exp = new IPExport();
                string toFile = @""D:""Work""PPTechStudio""ip.txt"";
                string fromFile=@""E:""个人资料""IMTools""QQwryUpdate""QQWry.Dat"";
                exp.SaveToText(toFile,fromFile);
               #endregion

  • 相关阅读:
    oracle 10g 免安装客户端在windows下配置
    sql2005 sa密码
    使用windows live writer 有感
    windows xp SNMP安装包提取
    汉化groove2007
    迁移SQL server 2005 Reporting Services到SQL server 2008 Reporting Services全程截图操作指南
    foxmail 6在使用中的问题
    AGPM客户端连接不上服务器解决一例
    SpringSource Tool Suite add CloudFoundry service
    Java 之 SWing
  • 原文地址:https://www.cnblogs.com/leeolevis/p/1383163.html
Copyright © 2011-2022 走看看