C#读取QQ纯真IP数据库QQWry.Dat的代码

2016-02-19 11:57 47 1 收藏

最近很多朋友喜欢上设计,但是大家却不知道如何去做,别担心有图老师给你解答,史上最全最棒的详细解说让你一看就懂。

【 tulaoshi.com - 编程语言 】

纯真版QQ IP数据库
代码如下:

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
///returns0:相等,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;
}
}
}

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

来源:http://www.tulaoshi.com/n/20160219/1599278.html

延伸阅读
什么是数据库事务 数据库事务是指作为单个逻辑工作单元执行的一系列操作。 牐犐柘胪上购物的一次交易,其付款过程至少包括以下几步数据库操作: 更新客户所购商品的库存信息 保存客户付款信息--可能包括与银行系统的交互 生成订单并且保存到数据库中 更新用户相关信息,例如购物数量等等 牐犝常的...
最近这个项目中用到是ACCESS的数据库,开始没有使用密码进行连接: String connectionString = "Provider=Microsoft.Jet.OleDb.4.0;Data Source="; connectionString += @"c:datadbdb.mdb"; OleDbConnection con = new OleDbConnection(connectionString); con.Open(); 是没有任何问题。 为了要使数据库安全一点,不能被用户直接打开编辑,...
介绍 下面这段C# 代码可以用来压缩和修复Access数据库,不管它是一个简单的".mdb"ACCESS数据库还是一个".mdw"网络共享数据库,这个过程和你在用MS Access应用程序中使用的"工具-数据库实用工具-压缩和修复"时执行的操作完全一样.实例代码使用了"迟绑定"(运行中在内存中建立COM对象),这样就不需要在工程中加入COM引用了,也不需要在PC上安装MS Acc...
Visual C#作是微软极力推荐的下一代程序开发语言,他有一个非常重要伴侣--.Net Framework SDK,在他的里面封装了许多Class Library (类库)。Visual C#要实现很多拓展功能,就必须借助于他的这个伴侣。在Visual C#中对数据库的处理是其功能的一个重要表现。Visual C#在进行数据库处理的时候,经常用到.Net FrameWork SDK中的一个名称空间 ...
数据库的 sql 参数封装类的编写 代码如下: using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System...

经验教程

19

收藏

27
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部