⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unttqqwry.pas

📁 参照上兴、鸽子等源码编写编写出来的。 编译环境:Delphi7+SP+DP+indy9等控件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
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 + -