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

📄 unttqqwry.pas

📁 参照上兴、鸽子等源码编写编写出来的。 编译环境:Delphi7+SP+DP+indy9等控件
💻 PAS
📖 第 1 页 / 共 2 页
字号:
Var
  RedirectMode:byte;
  pSplit:PChar;
  CountryFirstOffset,CountrySecondOffset:int64;
  IPCountryLen:integer;
  IPArea:PChar;
  ///**
  //* 给定一个地区信息偏移值,返回在数据文件中该偏移量下的地区信息
  //* @param  (AreaOffset, IPArea) (地区信息在文件中的偏移值, 返回的地区信息)
  //* @return
  //*/

  Procedure ReadIPAreaByAreaOffset(AreaOffset:int64;Var IPArea:PChar);
  Var
    ModeByte:byte;
    ReadAreaOffset:int64;
  Begin
    Try
      ModeByte:=0;
      ReadAreaOffset:=0;

      //取内存文件映射首地址
      pQQWryPos:=pQQWryMapFile;
      //移到偏移处
      Inc(pQQWryPos,AreaOffset);
      //读模式
      CopyMemory(@ModeByte,pQQWryPos,1);
      //模式1或2,后3字节为偏移
      If (ModeByte=REDIRECT_MODE_1)Or(ModeByte=REDIRECT_MODE_2) Then Begin
        //读偏移
        Inc(pQQWryPos);
        CopyMemory(@ReadAreaOffset,pQQWryPos,3);
        //若偏移为0,则为未知地区,对于以前的数据库有这个错误
        If ReadAreaOffset=0 Then IPArea:='未知地区'
        Else Begin//去偏移处读字符串
          pQQWryPos:=pQQWryMapFile;
          Inc(pQQWryPos,ReadAreaOffset);
          CopyMemory(IPArea,PChar(pQQWryPos),StrLen(PChar(pQQWryPos)));
        End;
      //没有模式,直接读字符串
      End Else Begin
        pQQWryPos:=pQQWryMapFile;
        Inc(pQQWryPos,AreaOffset);
        CopyMemory(IPArea,PChar(pQQWryPos),StrLen(PChar(pQQWryPos)));
      End;
    Except
      On E:Exception Do Begin
        Raise Exception.Create(E.Message);
        Exit;
      End;
    End;
  End;
Begin
  Try
    RedirectMode:=0;
    pSplit:=' ';
    CountryFirstOffset:=0;
    CountrySecondOffset:=0;

    //取内存文件映射首地址
    pQQWryPos:=pQQWryMapFile;
    //根据记录ID号移到该记录号的索引处
    Inc(pQQWryPos,EndIPOffset+4);

    CopyMemory(@RedirectMode,pQQWryPos,1);
    //重定向模式1的处理
    If RedirectMode=REDIRECT_MODE_1 Then Begin
      Inc(pQQWryPos);
      //模式值为1,则后3个字节的内容为国家信息的偏移值
      CopyMemory(@CountryFirstOffset,pQQWryPos,3);
      //进行重定向
      pQQWryPos:=pQQWryMapFile;
      Inc(pQQWryPos,CountryFirstOffset);
      //第二次读取国家信息的重定向模式
      CopyMemory(@RedirectMode,pQQWryPos,1);
      //第二次重定向模式为模式2的处理
      If RedirectMode=REDIRECT_MODE_2 Then Begin
          //后3字节的内容即为第二次重定向偏移值
        Inc(pQQWryPos);
        CopyMemory(@CountrySecondOffset,pQQWryPos,3);
          //读取第二次重定向偏移值下的字符串值,即为国家信息
        pQQWryPos:=pQQWryMapFile;
        Inc(pQQWryPos,CountrySecondOffset);
        IPCountryLen:=StrLen(PChar(pQQWryPos));
        CopyMemory(IPLocation,PChar(pQQWryPos),IPCountryLen);
          //用空格分割国家和地区
        CopyMemory(@IPLocation[IPCountryLen],pSplit,1);

          //若第一次重定向模式为1,进行重定向后读取的第二次重定向模式为2,
          //则地区信息存放在第一次国家信息偏移值的后面
        IPArea:=PChar(@IPLocation[IPCountryLen+1]);
        ReadIPAreaByAreaOffset(CountryFirstOffset+4,IPArea);

      //第二次重定向模式不是模式2的处理
      End Else Begin
        IPCountryLen:=StrLen(PChar(pQQWryPos));
        CopyMemory(IPLocation,PChar(pQQWryPos),IPCountryLen);
          //用空格分割国家和地区
        CopyMemory(@IPLocation[IPCountryLen],pSplit,1);
          //读地区信息
        IPArea:=PChar(@IPLocation[IPCountryLen+1]);
        ReadIPAreaByAreaOffset(CountryFirstOffset+IPCountryLen+1,IPArea);
      End;

    //重定向模式2的处理
    End Else
      If RedirectMode=REDIRECT_MODE_2 Then Begin
      Inc(pQQWryPos);
      //模式值为2,则后3个字节的内容为国家信息的偏移值
      CopyMemory(@CountrySecondOffset,pQQWryPos,3);
      //进行重定向
      pQQWryPos:=pQQWryMapFile;
      Inc(pQQWryPos,CountrySecondOffset);
      //国家信息
      IPCountryLen:=StrLen(PChar(pQQWryPos));
      CopyMemory(IPLocation,PChar(pQQWryPos),IPCountryLen);
      //用空格分割国家和地区
      CopyMemory(@IPLocation[IPCountryLen],pSplit,1);

      //地区信息
      IPArea:=PChar(@IPLocation[IPCountryLen+1]);
      ReadIPAreaByAreaOffset(EndIPOffset+8,IPArea);
    //不是重定向模式的处理,存放的即是IP地址信息
    End Else Begin
      //国家信息
      IPCountryLen:=StrLen(PChar(pQQWryPos));
      CopyMemory(IPLocation,PChar(pQQWryPos),IPCountryLen);
      //用空格分割国家和地区
      CopyMemory(@IPLocation[IPCountryLen],pSplit,1);

      //地区信息
      IPArea:=PChar(@IPLocation[IPCountryLen+1]);
      ReadIPAreaByAreaOffset(EndIPOffset+4+IPCountryLen+1,IPArea);
    End;
  Except
    On E:Exception Do Begin
      Raise Exception.Create(E.Message);
      Exit;
    End;
  End;
End;

///**
//* 给定一个IP地址信息记录号,返回该项记录的信息,用Stringlist接收该条信息,效率较低
//* @param  (IPRecordID, IPData) (IP地址信息记录号, 返回的该条信息:①起始IP ②结束IP ③国家 ④地区)
//* @return 无
//*/

Procedure TQQWry.GetIPDataByIPRecordID(IPRecordID:int64;Var IPData:TStringlist);
Var
  aryIPData:Array[0..254] Of char;
  pIPData:PChar;
  i:integer;
Begin
  Try
    FillChar(aryIPData,SizeOf(aryIPData),#0);
    pIPData:=PChar(@aryIPData[0]);

    GetIPDataByIPRecordID(IPRecordID,pIPData);
    //去掉结尾的回车符
    pIPData[StrLen(pIPData)-2]:=#0;
    IPData.CommaText:=StrPas(pIPData);
    //有可能地区为空,也有可能地区中含有空格
    For i:=1 To 4-IPData.Count Do
      IPData.Add('无');
    For i:=5 To IPData.Count Do
      IPData[3]:=IPData[3]+' '+IPData[i-1];
  Except
    On E:Exception Do Begin
      Raise Exception.Create(E.Message);
      Exit;
    End;
  End;
End;

///**
//* 给定一个IP地址(四段点分字符串形式),返回该IP的数值
//* @param  (IP)  (IP地址,四段点分字符串形式)
//* @return 该IP的数值
//*/

Function TQQWry.GetIPValue(IP:String):int64;
Var
  slIP:TStringlist;
  i:integer;

  Function SplitStringToStringlist(aString:String;aSplitChar:String):TStringlist;
  Begin
    result:=TStringlist.Create;
    While Pos(aSplitChar,aString)>0 Do Begin
      result.Add(Copy(aString,1,Pos(aSplitChar,aString)-1));
      aString:=Copy(aString,Pos(aSplitChar,aString)+1,Length(aString)-Pos(aSplitChar,aString));
    End;
    result.Add(aString);
  End;
Begin
  Try
    slIP:=SplitStringToStringlist(IP,'.');
    result:=0;
    For i:=3 Downto 0 Do Begin
      result:=result+StrToInt(slIP[i])*Trunc(power(256,3-i));
    End;
  Except
    On E:Exception Do Begin
      Raise Exception.Create('无效的IP地址!');
      Exit;
    End;
  End;
End;

///**
//* 给定一个IP地址(四段点分字符串形式),返回该IP地址所在的记录号
//* @param  IP  IP地址(四段点分字符串形式)  string
//* @return 该IP地址所在的记录号  Cardinal
//*/

Function TQQWry.GetIPDataID(IP:String):int64;

  Function SearchIPDataID(IPRecordFrom,IPRecordTo,IPValue:int64):int64;
  Var
    CompareIPValue1,CompareIPValue2:int64;
  Begin
    result:=0;
    CompareIPValue1:=0;
    CompareIPValue2:=0;

    pQQWryPos:=pQQWryMapFile;
    Inc(pQQWryPos,FirstIPIndexOffset+((IPRecordTo-IPRecordFrom)Div 2+IPRecordFrom-1)*7);
    CopyMemory(@CompareIPValue1,pQQWryPos,4);
    pQQWryPos:=pQQWryMapFile;
    Inc(pQQWryPos,FirstIPIndexOffset+((IPRecordTo-IPRecordFrom)Div 2+IPRecordFrom)*7);
    CopyMemory(@CompareIPValue2,pQQWryPos,4);
    //找到了
    If (IPRecordFrom=IPRecordTo)Or((IPValue>=CompareIPValue1)And(IPValue<CompareIPValue2)) Then Begin
      result:=(IPRecordTo-IPRecordFrom)Div 2+IPRecordFrom;
    End Else
      //后半段找
      If IPValue>CompareIPValue1 Then Begin
      result:=SearchIPDataID((IPRecordTo-IPRecordFrom)Div 2+IPRecordFrom+1,IPRecordTo,IPValue);
    End Else
        //前半段找
      If IPValue<CompareIPValue1 Then Begin
      result:=SearchIPDataID(IPRecordFrom,(IPRecordTo-IPRecordFrom)Div 2+IPRecordFrom-1,IPValue);
    End;
  End;
Begin
  Try
    result:=SearchIPDataID(1,GetIPDataNum,GetIPValue(IP));
  Except
    On E:Exception Do Begin
      Destroy;
      Raise Exception.Create(E.Message);
      Exit;
    End;
  End;
End;

///**
//* 将IP地址数据库解压成文本文件
//* @param  (ATxtFileName) (解压后的文本文件全名)
//* @return -1为解压失败,非-1值为解压所耗时间,单位毫秒
//*/

Function TQQWry.ExtractIPDataToTxtFile(ATxtFileName:String):integer;
Var
  QQWryMemoryStream:TMemoryStream;
  i:integer;
  IPData,NowPos:PChar;
  TimeCounter:DWORD;
  pReturn:PChar;
Begin
  Try
    IPData:=StrAlloc(41943040);
    NowPos:=IPData;
    TimeCounter:=GetTickCount;
    For i:=1 To GetIPDataNum Do Begin
      GetIPDataByIPRecordID(i,NowPos);
      Inc(NowPos,StrLen(NowPos));
    End;
    pReturn:=#13#10;
    NowPos:=StrECopy(NowPos,pReturn);
    NowPos:=StrECopy(NowPos,pReturn);
    NowPos:=StrECopy(NowPos,PChar(Format('IP数据库共有数据 : %d 条', [GetIPDataNum])));
    NowPos:=StrECopy(NowPos,pReturn);
    QQWryMemoryStream:=TMemoryStream.Create;
    QQWryMemoryStream.SetSize(NowPos-IPData);
    QQWryMemoryStream.WriteBuffer(IPData^,NowPos-IPData);
    QQWryMemoryStream.SaveToFile(ATxtFileName);
    StrDispose(IPData);
    QQWryMemoryStream.Destroy;
    result:=GetTickCount-TimeCounter;
  Except
    On E:Exception Do Begin
      Raise Exception.Create(E.Message);
      Exit;
    End;
  End;
End;
End.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -