VS.NET讀取純真IP數(shù)據庫(C#)

2010-08-28 10:50:35來源:西部e網作者:

使用方法:

例子:
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);//地區(qū)

以下是類文件



//根據LumaQQ改寫而成.

using System;
using System.IO;
using System.Text;
 
namespace BDQQ.Data
{
    /**//// 
    /// QQWry 的摘要說明。
    /// 

    public class QQWry
    {
        //第一種模式
        #region 第一種模式
            /**//// 
            /// 第一種模式
            /// 

            #endregion
            private const byte REDIRECT_MODE_1        = 0x01;
 
        //第二種模式
        #region 第二種模式
            /**//// 
            /// 第二種模式
            /// 

            #endregion
            private const byte REDIRECT_MODE_2        = 0x02;
 
        //每條記錄長度
        #region 每條記錄長度
            /**//// 
            /// 每條記錄長度
            /// 

            #endregion        
            private const int IP_RECORD_LENGTH        = 7;
 
        //數(shù)據庫文件
        #region 數(shù)據庫文件
            /**//// 
            /// 文件對象
            /// 

            #endregion        
            private FileStream ipFile;
 
        private const string unCountry = "未知國家";
        private const string unArea    = "未知地區(qū)";
 
        //索引開始位置
        #region 索引開始位置
            /**//// 
            /// 索引開始位置
            /// 

            #endregion
            private long ipBegin;
 
        //索引結束位置
        #region 索引結束位置
            /**//// 
            /// 索引結束位置
            /// 

            #endregion
            private long ipEnd;
 
        //IP地址對象
        #region IP地址對象
            /**//// 
            /// IP對象
            /// 

            #endregion
            private IPLocation loc;
 
        //存儲文本內容
        #region 存儲文本內容
            /**//// 
            /// 存儲文本內容
            /// 

            #endregion
            private byte[] buf;
 
        //存儲3字節(jié)
        #region 存儲3字節(jié)
            /**//// 
            /// 存儲3字節(jié)
            /// 

            #endregion
            private byte[] b3;
 
        //存儲4字節(jié)
        #region 存儲4字節(jié)
            /**//// 
            /// 存儲4字節(jié)IP地址
            /// 

            #endregion
            private byte[] b4;
 
        //構造函數(shù)
        #region 構造函數(shù)
            /**//// 
            /// 構造函數(shù)
            /// 

            /// IP數(shù)據庫文件絕對路徑
            #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地址搜索
            /**//// 
            /// 搜索IP地址搜索
            /// 

            /// 
            /// 
            #endregion
            public IPLocation SearchIPLocation( string ip )
            {
                //將字符IP轉換為字節(jié)
                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 取得具體信息
            /**//// 
            /// 取得具體信息
            /// 

            /// 
            /// 
            #endregion
            private IPLocation getIPLocation( long offset )
            {
                ipFile.Position = offset + 4;
                //讀取第一個字節(jié)判斷是否是標志字節(jié)
                byte one = (byte)ipFile.ReadByte();
                if( one == REDIRECT_MODE_1 )
                {
                    //第一種模式
                    //讀取國家偏移
                    long countryOffset = readLong3();
                    //轉至偏移處
                    ipFile.Position = countryOffset;
                    //再次檢查標志字節(jié)
                    byte b = (byte)ipFile.ReadByte();
                    if( b == REDIRECT_MODE_2 )
                    {
                        loc.country = readString( readLong3() );
                        ipFile.Position = countryOffset + 4;
                    }
                    else
                        loc.country = readString( countryOffset );

                    //讀取地區(qū)標志
                    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;
            }


        //取得地區(qū)信息
        #region 取得地區(qū)信息
            /**//// 
            /// 讀取地區(qū)名稱
            /// 

            /// 
            /// 
            #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 讀取字符串
            /**//// 
            /// 讀取字符串
            /// 

            /// 
            /// 
            #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地址所在的絕對偏移量
            /**//// 
            /// 查找IP地址所在的絕對偏移量
            /// 

            /// 
            /// 
            #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字節(jié)的IP地址
        #region 讀出4字節(jié)的IP地址
            /**//// 
            /// 從當前位置讀取四字節(jié),此四字節(jié)是IP地址
            /// 

            /// 
            /// 
            #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地址是否相同
            /**//// 
            /// 比較IP地址是否相同
            /// 

            /// 
            /// 
            /// 0:相等,1:ip大于beginIP,-1:小于
            #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;
            }


        //比較兩個字節(jié)是否相等
        #region 比較兩個字節(jié)是否相等
            /**//// 
            /// 比較兩個字節(jié)是否相等
            /// 

            /// 
            /// 
            /// 
            #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字節(jié)
        #region 根據當前位置讀取4字節(jié)
            /**//// 
            /// 從當前位置讀取4字節(jié),轉換為長整型
            /// 

            /// 
            /// 
            #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字節(jié)
        #region 根據當前位置,讀取3字節(jié)
                   /**//// 
                   /// 根據當前位置,讀取3字節(jié)
                   /// 

                   /// 
                   /// 
                   #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字節(jié)
        #region 從當前位置讀取3字節(jié)
            /**//// 
            /// 從當前位置讀取3字節(jié)
            /// 

            /// 
            #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之間的偏移量
            /**//// 
            /// 取得begin和end中間的偏移
            /// 

            /// 
            /// 
            /// 
            #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;
        }
    }
}

原文地址:http://www.yaosansi.com/blog/article.asp?id=278
關鍵詞:VS.NET