例子:
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地址是否相同
///
///
///
///
#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