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

  • 相关阅读:
    2021.4.4(每周总结)
    2021.4.2
    2021.4.1
    2021.3.31
    2021.3.30
    2021.3.29
    2021.3.28(每周总结)
    2021.3.26
    C语言中指针与取地址符&详解
    使用JDBC连接、操作数据库、实现数据处理
  • 原文地址:https://www.cnblogs.com/leeolevis/p/1383163.html
Copyright © 2011-2022 走看看