下面是详细的攻略。
1. 下载QQ纯真IP数据库QQWry.Dat
首先,我们需要先下载QQ纯真IP数据库QQWry.Dat,可以从官网下载(http://www.cz88.net/),也可以搜索下载链接。
2. 使用C#读取QQ纯真IP数据库
读取QQ纯真IP数据库QQWry.Dat,我们需要用到二进制读取和文件指针的知识。以下是读取QQWry.Dat的代码示例:
示例1
using System;
using System.IO;
using System.Text;
public class IPHelper
{
private static FileStream fs;
private static BinaryReader br;
private static long left;
private static long right;
private static long middle;
private static uint countryOffset;
private static uint recordOffset;
private static byte[] buffer = new byte[8];
private static byte[] recordBuffer = new byte[40];
public static void Init(string fileName)
{
if (File.Exists(fileName))
{
fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
br = new BinaryReader(fs);
left = br.ReadInt32();
right = br.ReadInt32();
countryOffset = br.ReadUInt32();
recordOffset = ReadUInt32();
}
else
{
throw new Exception(string.Format("文件 {0} 不存在。", fileName));
}
}
public static void Query(string ip)
{
uint ipValue = IP2Long(ip);
while (left <= right)
{
middle = (left + right) / 2;
long offset = countryOffset + middle * 7;
fs.Seek(offset, SeekOrigin.Begin);
br.Read(buffer, 0, 4);
uint startIP = GetUInt32(buffer, 0);
if (ipValue < startIP)
{
right = middle - 1;
}
else
{
offset += 4;
fs.Seek(offset, SeekOrigin.Begin);
br.Read(buffer, 0, 3);
uint endIP = GetUInt32(buffer, 0);
if (ipValue > endIP)
{
left = middle + 1;
}
else
{
offset += 1;
fs.Seek(offset, SeekOrigin.Begin);
recordOffset = ReadUInt32();
fs.Seek(recordOffset, SeekOrigin.Begin);
br.Read(recordBuffer, 0, 40);
string country = GetLocation(recordBuffer);
country = Encoding.Default.GetString(Encoding.Default.GetBytes(country));
string[] locationArray = country.Split('\t');
}
}
}
}
private static uint ReadUInt32()
{
br.Read(buffer, 0, 4);
return GetUInt32(buffer, 0);
}
private static uint GetUInt32(byte[] value, int startIndex)
{
uint result = (uint)value[startIndex];
result |= (uint)value[startIndex + 1] << 8;
result |= (uint)value[startIndex + 2] << 16;
result |= (uint)value[startIndex + 3] << 24;
return result;
}
private static uint IP2Long(string ip)
{
string[] ips = ip.Split('.');
uint ipValue = 0;
if (ips.Length == 4)
{
try
{
ipValue = (uint.Parse(ips[0]) << 24) |
(uint.Parse(ips[1]) << 16) |
(uint.Parse(ips[2]) << 8) |
(uint.Parse(ips[3]));
}
catch (Exception ex)
{
throw new Exception(string.Format("Wrong IP format : {0}", ex.Message));
}
}
else
{
throw new Exception(string.Format("Wrong IP format : {0}", ip));
}
return ipValue;
}
private static string GetLocation(byte[] recordBuffer)
{
uint countryOffset = GetUInt32(recordBuffer, 0);
if (countryOffset == 0x01)
{
countryOffset = GetUInt32(recordBuffer, 4);
}
int length = (int)countryOffset - 0x01;
byte[] location = new byte[length];
Array.Copy(recordBuffer, 8, location, 0, length);
return Encoding.Default.GetString(location);
}
}
示例2
public class IPInfo
{
public string Country { get; set; }
public string Area { get; set; }
}
public class IPHelper2
{
private static uint startPos = 0;
private static FileStream fs = null;
private static byte[] buf = null;
private static byte[] IPHeadArr = null; //数据头
private static uint EndPos = 0; //最后的位置
public static void Init(string IpFilePath)
{
buf = new byte[4];
IPHeadArr = new byte[256];
fs = new FileStream(IpFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
EndPos = ReadUInt32(0);
fs.Seek(0x100, SeekOrigin.Begin);
fs.Read(IPHeadArr, 0, 256);
}
//返回的IPInfo
public static IPInfo ReadIP(string ip)
{
uint ipNum = IP2UInt(ip);
uint pointVal = SearchIPData(ipNum);
if (pointVal == 0)
return null;
else
{
int offset = 0;
if (ReadUInt8(pointVal + 4) == 0x02)
{
offset = ReadToUInt24(pointVal + 5);
pointVal = SearchIPData(ReadUInt32(pointVal + 8));
}
else
{
offset = 4;
}
string country = ReadString(offset + pointVal);
if (country[country.Length - 1] == '\0')
country = country.Substring(0, country.Length - 1);
if (ReadUInt8(pointVal + offset + 1) == 0x02)
{
offset = ReadToUInt24(pointVal + offset + 2);
pointVal = ReadUInt32(pointVal + offset + 4);
}
else
{
pointVal += ReadUInt8(pointVal + offset + 1) + 1;
}
string province = ReadString(offset + pointVal);
if (province[province.Length - 1] == '\0')
province = province.Substring(0, province.Length - 1);
var ipinfo = new IPInfo() { Country = country, Area = province };
return ipinfo;
}
}
//找到数据
private static uint SearchIPData(uint ipNum)
{
uint part1 = (ipNum & 0xFF000000) >> 24;
if (IPHeadArr[part1] == 0) return 0;
if (IPHeadArr[part1] == 1)
{
return ReadUInt32((part1 << 8) + 0x100);
}
uint part2 = (ipNum & 0x00FF0000) >> 16;
uint pointVal = ReadUInt32(((uint)(IPHeadArr[part1]) << 8) + part2);
if (pointVal == 0) return 0;
if (ReadUInt8(pointVal + 4) == 0x01)
return pointVal;
if (ReadUInt8(pointVal + 4) == 0x02)
return ReadUInt32(pointVal + 8) ;
return 0;
}
//将192.168.15.12形式的IP转换成UInt32
private static uint IP2UInt(string ip)
{
string[] nums = ip.Split('.');
uint ip0 = uint.Parse(nums[0]);
uint ip1 = uint.Parse(nums[1]);
uint ip2 = uint.Parse(nums[2]);
uint ip3 = uint.Parse(nums[3]);
return (ip0 << 24) | (ip1 << 16) | (ip2 << 8) | ip3;
}
//读取记录区中的标志字段
private static uint ReadFlag(uint offset)
{
fs.Position = offset;
fs.Read(buf, 0, 4);
return BitConverter.ToUInt32(buf, 0);
}
//读取记录区中的三个字节
private static int ReadToUInt24(uint offset)
{
byte[] b3 = new byte[4];
b3[0] = 0;
fs.Position = offset;
fs.Read(b3, 1, 3);
return BitConverter.ToInt32(b3, 0);
}
//读取记录区字符串
private static string ReadString(uint offset)
{
fs.Position = offset;
int len = 0;
while (fs.ReadByte() != 0) len++;
fs.Position = offset;
byte[] bytes = new byte[len];
fs.Read(bytes, 0, len);
return Encoding.GetEncoding("GB2312").GetString(bytes);
}
//读取指定偏移处的UInt32值
private static uint ReadUInt32(uint offset)
{
fs.Position = offset;
fs.Read(buf, 0, 4);
return BitConverter.ToUInt32(buf, 0);
}
//读取指定偏移处的Byte值
private static byte ReadUInt8(uint offset)
{
fs.Position = offset;
return (byte)fs.ReadByte();
}
}
3. 总结
以上是使用C#读取QQ纯真IP数据库QQWry.Dat的两个代码示例。虽然两个示例的实现方式不同,但实现的功能是一致的。我们还可以根据自己的需求进行相应的调整。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#读取QQ纯真IP数据库QQWry.Dat的代码 - Python技术站