📄 unttqqwry.pas
字号:
Unit untTQQWry;
Interface
Uses
Windows,SysUtils,Classes,StrUtils,Controls,Math;
Const//用于内存文件映射标志
QQWryMapFileTag='QQWryMapFile';
Type
TQQWry=Class(TObject)
Public
Constructor Create(AQQWryFileName:String);
Destructor Destroy; Override;
Function GetQQWryFileName:String;
Function GetQQWryFileSize:int64;
Function GetIPDataNum:int64;
Function GetQQWryDate:TDate;
Function GetQQWryDataFrom:String;
Procedure GetIPDataByIPRecordID(IPRecordID:int64;Var IPData:PChar); Overload;
Procedure GetIPLocationByEndIPOffset(EndIPOffset:int64;Var IPLocation:PChar);
Procedure GetIPDataByIPRecordID(IPRecordID:int64;Var IPData:TStringlist); Overload;
Function GetIPValue(IP:String):int64;
Function GetIPDataID(IP:String):int64;
Function ExtractIPDataToTxtFile(ATxtFileName:String):integer;
Private
QQWryFileName:String;
QQWryFileSize:int64;
IPDataNum:int64;
FirstIPIndexOffset,LastIPIndexOffset:integer;
hQQWryFile,hQQWryMapFile:THandle;
pQQWryMapFile:Pointer;
pQQWryPos:PByte;
Function GetFileSize(AFileName:String):int64;
End;
Implementation
///**
//* 获取文件大小
//* @param (AFileName) (文件全名)
//* @return (文件大小)
//*/
Function TQQWry.GetFileSize(AFileName:String):int64;
Var
FromF:File Of byte;
Begin
Try
AssignFile(FromF,AFileName);
FileMode:=0;
Reset(FromF);
Seek(FromF,0);
result:=FileSize(FromF);
Except
result:=0;
End;
End;
///**
//* 构造函数,构造一个TQQWry即纯真IP数据库处理对象
//* @param (AQQWryFileName) (纯真IP数据库文件的全文件名)
//* @return 无
//*/
Constructor TQQWry.Create(AQQWryFileName:String);
Var
Buffer:TOFStruct;
Begin
Inherited Create;
Try
QQWryFileName:=AQQWryFileName;
//测文件存在
If Not FileExists(QQWryFileName) Then
Raise Exception.Create(Format('文件 %s 不存在!', [QQWryFileName]));
//测文件大小
QQWryFileSize:=GetFileSize(QQWryFileName);
If QQWryFileSize=0 Then
Raise Exception.Create(Format('文件 %s 大小为空!', [QQWryFileName]));
//打开文件句柄
hQQWryFile:=OpenFile(PChar(QQWryFileName),
Buffer,
OF_READWRITE);
If hQQWryFile=0 Then
Raise Exception.Create(Format('文件 %s 不能打开!', [QQWryFileName]));
//创建文件映像对象
hQQWryMapFile:=CreateFileMapping(hQQWryFile,Nil,PAGE_READWRITE,0,QQWryFileSize,PChar(QQWryMapFileTag));
If hQQWryMapFile=0 Then Begin
CloseHandle(hQQWryFile);
Raise Exception.Create('不能创建内存映象文件!');
End;
//获取映象文件映射地址
pQQWryMapFile:=MapViewOfFile(hQQWryMapFile,FILE_MAP_ALL_ACCESS,0,0,0);
If pQQWryMapFile=Nil Then Begin
CloseHandle(hQQWryFile);
CloseHandle(hQQWryMapFile);
Raise Exception.Create('不能获取文件映射地址!');
End;
pQQWryPos:=pQQWryMapFile;
FirstIPIndexOffset:=PInteger(pQQWryPos)^;
Inc(pQQWryPos,4);
LastIPIndexOffset:=PInteger(pQQWryPos)^;
IPDataNum:=(LastIPIndexOffset-FirstIPIndexOffset)Div 7+1;
Except
On E:Exception Do Begin
Raise Exception.Create(E.Message);
Exit;
End;
End;
End;
///**
//* 析构函数 (释放TQQWry对象,关闭文件映射,关闭文件映像对象句柄,关闭文件句柄)
//* @param 无
//* @return 无
//*/
Destructor TQQWry.Destroy;
Begin
If pQQWryMapFile<>Nil Then UnmapViewOfFile(pQQWryMapFile);//关闭文件映射
If hQQWryMapFile<>0 Then CloseHandle(hQQWryMapFile);//关闭文件映像对象句柄
If hQQWryFile<>0 Then CloseHandle(hQQWryFile);//关闭文件句柄
Inherited Destroy;
End;
///**
//* 获取纯真IP数据库文件的全文件名
//* @param 无
//* @return (纯真IP数据库文件的全文件名)
//*/
Function TQQWry.GetQQWryFileName:String;
Begin
result:=QQWryFileName;
End;
///**
//* 获取纯真IP数据库文件大小
//* @param 无
//* @return (纯真IP数据库文件大小)
//*/
Function TQQWry.GetQQWryFileSize:int64;
Begin
result:=QQWryFileSize;
End;
///**
//* 获取纯真IP数据库内含有的IP地址信息记录数
//* @param 无
//* @return (纯真IP数据库记录数)
//*/
Function TQQWry.GetIPDataNum:int64;
Begin
result:=IPDataNum;
End;
///**
//* 获取当前QQIP数据库的更新日期
//* @param 无
//* @return QQIP当前数据库的更新日期 TDate
//*/
Function TQQWry.GetQQWryDate:TDate;
Var
DateString:String;
IPData:TStringlist;
Begin
IPData:=TStringlist.Create;
GetIPDataByIPRecordID(GetIPDataNum,IPData);
DateString:=IPData[3];
IPData.Free;
DateString:=Copy(DateString,1,Pos('IP数据',DateString)-1);
DateString:=StringReplace(DateString,'年','-', [rfReplaceAll,rfIgnoreCase]);
DateString:=StringReplace(DateString,'月','-', [rfReplaceAll,rfIgnoreCase]);
DateString:=StringReplace(DateString,'日','-', [rfReplaceAll,rfIgnoreCase]);
result:=StrToDate(DateString);
End;
///**
//* 获取当前QQIP数据库的来源信息
//* @param 无
//* @return 当前QQIP数据库的来源信息 string
//*/
Function TQQWry.GetQQWryDataFrom:String;
Var
FromString:String;
IPData:TStringlist;
Begin
IPData:=TStringlist.Create;
GetIPDataByIPRecordID(GetIPDataNum,IPData);
FromString:=IPData[2];
IPData.Free;
result:=FromString;
End;
///**
//* 给定一个IP地址信息记录号,返回该项记录的信息
//* @param (IPRecordID, IPData) (IP地址信息记录号, 返回的该条信息:①起始IP 15字节 ②结束IP 15字节 ③国家 ④地区 ⑤回车键2字节)
//* @return 无
//*/
Procedure TQQWry.GetIPDataByIPRecordID(IPRecordID:int64;Var IPData:PChar);
Var
EndIPOffset:integer;
i:integer;
pBlank,pReturn:PChar;
IPByteStr:String;
IPByteStrLen:integer;
IPDataPos:integer;
IPLocation:PChar;
Begin
Try
If (IPRecordID<=0)Or(IPRecordID>GetIPDataNum) Then
Raise Exception.Create('IP信息记录号过小或越界!');
pBlank:=' ';
pReturn:=#13#10;
EndIPOffset:=0;
//取内存文件映射首地址
pQQWryPos:=pQQWryMapFile;
//根据记录的ID号移到该记录号的索引处,因为高位在后所以从后往前读
Inc(pQQWryPos,FirstIPIndexOffset+(IPRecordID-1)*7+3);
//取始末IP地址
//索引的前4个字节为该条记录的起始IP地址
IPDataPos:=0;
For i:=0 To 3 Do Begin
IPByteStr:=IntToStr(pQQWryPos^);
IPByteStrLen:=Length(IPByteStr);
CopyMemory(@IPData[IPDataPos],PChar(IPByteStr),IPByteStrLen);
Inc(IPDataPos,IPByteStrLen);
If i<>3 Then Begin
IPData[IPDataPos]:='.';
Inc(IPDataPos);
End;
Dec(pQQWryPos);
End;
//填充空格至16位
CopyMemory(@IPData[IPDataPos],pBlank,16-IPDataPos);
IPDataPos:=16;
Inc(pQQWryPos,5);
//后3个字节是该条记录的内容区域的偏移值,内容区域的前4个字节为该条记录的结束IP地址
CopyMemory(@EndIPOffset,pQQWryPos,3);
//取该条记录的结束IP地址
pQQWryPos:=pQQWryMapFile;
Inc(pQQWryPos,EndIPOffset+3);
For i:=0 To 3 Do Begin
IPByteStr:=IntToStr(pQQWryPos^);
IPByteStrLen:=Length(IPByteStr);
CopyMemory(@IPData[IPDataPos],PChar(IPByteStr),IPByteStrLen);
Inc(IPDataPos,IPByteStrLen);
If i<>3 Then Begin
IPData[IPDataPos]:='.';
Inc(IPDataPos);
End;
Dec(pQQWryPos);
End;
//填充空格至16位
CopyMemory(@IPData[IPDataPos],pBlank,32-IPDataPos);
IPDataPos:=32;
//取该条记录的国家地区信息
IPLocation:=PChar(@IPData[IPDataPos]);
GetIPLocationByEndIPOffset(EndIPOffset,IPLocation);
//结尾的回车
If IPLocation[StrLen(IPLocation)-1]<>' ' Then
Inc(IPDataPos,StrLen(IPLocation))
Else
Inc(IPDataPos,StrLen(IPLocation)-1);
CopyMemory(@IPData[IPDataPos],pReturn,2);
Except
On E:Exception Do Begin
Destroy;
Raise Exception.Create(E.Message);
Exit;
End;
End;
End;
///**
//* 给定一条记录的结束IP地址的偏移,返回该条记录的国家地区信息
//* @param (EndIPOffset, IPLocation) (该条记录的结束IP地址偏移, 该条记录的国家地区信息)
//* @return 无
//*/
Procedure TQQWry.GetIPLocationByEndIPOffset(EndIPOffset:int64;Var IPLocation:PChar);
Const
//实际信息字串存放位置的重定向模式
REDIRECT_MODE_1=1;
REDIRECT_MODE_2=2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -