?? uclass.cpp
字號:
//---------------------------------------------------------------------------
#pragma hdrstop
#include "uClass.h"
//---------------------------------------------------------------------------
// 實際信息字串存放位置的重定向模式
const REDIRECT_MODE_1 = 1;
const REDIRECT_MODE_2 = 2;
const char A_szSplitChar[] = "\r\n";
//---------------------------------------------------------------------------
// 構造一個TQQWry即QQIP地址數據庫的對象
// strWryFileName: QQIP數據庫文件的全名(包括路徑),請確認文件存在和可讀性
__fastcall TQQWry::TQQWry(String strWryFileName)
{
FFileName = strWryFileName;
FFileStream = new TFileStream(FFileName, fmOpenRead | fmShareDenyWrite, 0);
FFileSize = FFileStream->Size;
FFileStream->Seek(0, soFromBeginning);
FFileStream->Read(&FFirstIPOffset, 4);
FFileStream->Read(&FLastIPOffset, 4);
FIPRecordCount = (FLastIPOffset - FFirstIPOffset) / 7 + 1;
}
//---------------------------------------------------------------------------
// 析構函數,釋放TQQWry對象,釋放文件數據流對象
__fastcall TQQWry::~TQQWry()
{
delete FFileStream;
}
//---------------------------------------------------------------------------
// 獲取QQIP數據庫文件的全名(包括路徑)
String __fastcall TQQWry::GetWryFileName()
{
return FFileName;
}
//---------------------------------------------------------------------------
// 獲取QQIP數據庫文件大小
DWORD __fastcall TQQWry::GetWryFileSize()
{
return FFileSize;
}
//---------------------------------------------------------------------------
// 獲取QQIP數據庫內含有的IP地址信息記錄條數
DWORD __fastcall TQQWry::GetIPRecordCount()
{
return FIPRecordCount;
}
//---------------------------------------------------------------------------
// 獲取當前QQIP數據庫的更新日期
String __fastcall TQQWry::GetUpdateDate()
{
String strTemp = GetIPMsg(GetIPRecordCount());
String strDate = strTemp.SubString(strTemp.LastDelimiter(A_szSplitChar) + 1, strTemp.Length());
strDate = strDate.SubString(1, strDate.Pos("IP數據") - 1);
return strDate;
}
//---------------------------------------------------------------------------
// 獲取當前QQIP數據庫的來源信息
String __fastcall TQQWry::GetDataFrom()
{
String strTemp = GetIPMsg(GetIPRecordCount());
strTemp = strTemp.SubString(strTemp.Pos(A_szSplitChar) + 2, strTemp.Length());
strTemp = strTemp.SubString(strTemp.Pos(A_szSplitChar) + 2, strTemp.Length());
strTemp = strTemp.SubString(1, strTemp.Pos(A_szSplitChar) - 1);
return strTemp;
}
//---------------------------------------------------------------------------
// 給定一個文件偏移值,返回在數據文件中該偏移下的字符串,即讀取到0結尾的字符前
// dwStringOffset = 字符串在文件中的偏移值
String __fastcall TQQWry::ReadString(DWORD dwStringOffset)
{
char cReadByte = 0;
String strRet("");
FFileStream->Seek(dwStringOffset, soFromBeginning);
FFileStream->Read(&cReadByte, 1);
while(cReadByte != 0)
{
strRet += String(cReadByte);
FFileStream->Read(&cReadByte, 1);
}
return strRet;
}
//---------------------------------------------------------------------------
// 給定一個地區信息偏移值,返回在數據文件中該偏移量下的地區信息
// dwAreaOffset = 地區信息在文件中的偏移值
// 返回地區信息字符串
String __fastcall TQQWry::ReadArea(DWORD dwAreaOffset)
{
BYTE btMode = 0;
DWORD dwReadAreaOffset = 0;
FFileStream->Seek(dwAreaOffset, soFromBeginning);
FFileStream->Read(&btMode, 1);
if(btMode == REDIRECT_MODE_1 || btMode == REDIRECT_MODE_2)
{
FFileStream->Read(&dwReadAreaOffset, 3);
if(dwAreaOffset == 0)
return "未知地區";
else
return ReadString(dwReadAreaOffset);
}
else
return ReadString(dwAreaOffset);
}
//---------------------------------------------------------------------------
// 給定一個IP國家地區記錄的偏移,返回該IP地址的信息
// dwLocOffset = 國家記錄的偏移
// 返回IP地址信息(國家信息/地區信息)
String __fastcall TQQWry::GetIPLocation(DWORD dwLocOffset)
{
BYTE btRedirectMode = 0;
DWORD dwCountryFirstOffset = 0, dwCountrySecondOffset = 0;
String strCountryMsg(""), strAreaMsg("");
// 跳過4個字節,該4字節內容為該條IP信息里IP地址段中的終止IP值
FFileStream->Seek(dwLocOffset + 4, soFromBeginning);
// 讀取國家信息的重定向模式值
FFileStream->Read(&btRedirectMode, 1);
// 重定向模式1的處理
if(btRedirectMode == REDIRECT_MODE_1)
{
//模式值為1,則后3個字節的內容為國家信息的重定向偏移值
FFileStream->Read(&dwCountryFirstOffset, 3);
// 進行重定向
FFileStream->Seek(dwCountryFirstOffset, soFromBeginning);
// 第二次讀取國家信息的重定向模式
FFileStream->Read(&btRedirectMode, 1);
// 第二次重定向模式為模式2的處理
if(btRedirectMode == REDIRECT_MODE_2)
{
// 后3字節的內容即為第二次重定向偏移值
FFileStream->Read(&dwCountrySecondOffset, 3);
// 讀取第二次重定向偏移值下的字符串值,即為國家信息
strCountryMsg = ReadString(dwCountrySecondOffset);
// 若第一次重定向模式為1,進行重定向后讀取的第二次重定向模式為2,
// 則地區信息存放在第一次國家信息偏移值的后面
FFileStream->Seek(dwCountryFirstOffset + 4, soFromBeginning);
// 第二次重定向模式不是模式2的處理
}
else
strCountryMsg = ReadString(dwCountryFirstOffset);
// 在重定向模式1下讀地區信息值
strAreaMsg = ReadArea(FFileStream->Position);
}
// 重定向模式2的處理
else if(btRedirectMode == REDIRECT_MODE_2)
{
FFileStream->Read(&dwCountrySecondOffset, 3);
strCountryMsg = ReadString(dwCountrySecondOffset);
strAreaMsg = ReadArea(dwLocOffset + 8);
}
// 不是重定向模式的處理,存放的即是IP地址信息
else
{
strCountryMsg = ReadString(FFileStream->Position - 1);
strAreaMsg = ReadArea(FFileStream->Position);
}
return strCountryMsg + A_szSplitChar + strAreaMsg;
}
//---------------------------------------------------------------------------
// 給定一個IP地址信息記錄號,返回該項記錄的信息
// dwIPRecordID = IP地址信息記錄號
// 返回記錄號信息, 含3個部分:①起始IP地址 ②終止IP地址 ③國家信息/地區信息
String __fastcall TQQWry::GetIPMsg(DWORD dwIPRecordID)
{
if(dwIPRecordID == 0)
dwIPRecordID = 1;
if(dwIPRecordID > FIPRecordCount)
return "記錄越界";
BYTE A_btStartIP[4], A_btEndIP[4];
memset(&A_btStartIP, 0x00 ,4);
memset(&A_btEndIP, 0x00 ,4);
String strStartIP(""), strEndIP("");
DWORD dwEndIPOffset = 0;
// 根據記錄ID號移到該記錄號的索引處
FFileStream->Seek(FFirstIPOffset + (dwIPRecordID - 1) * 7, soFromBeginning);
// 索引的前4個字節為起始IP地址
FFileStream->Read(&A_btStartIP, 4);
// 后3個字節是內容區域的偏移值
FFileStream->Read(&dwEndIPOffset, 3);
// 移至內容區域
FFileStream->Seek(dwEndIPOffset, soFromBeginning);
// 內容區域的前4個字節為終止IP地址
FFileStream->Read(&A_btEndIP, 4);
// 將起止IP地址轉換為點分的形式
for(int i=3; i>-1; i--)
{
if(i != 0)
{
strStartIP += IntToStr(A_btStartIP[i]) + ".";
strEndIP += IntToStr(A_btEndIP[i]) + ".";
}
else
{
strStartIP += IntToStr(A_btStartIP[i]);
strEndIP += IntToStr(A_btEndIP[i]);
}
}
return strStartIP + A_szSplitChar + strEndIP + A_szSplitChar + GetIPLocation(dwEndIPOffset);
// 獲取該條記錄下的IP地址信息
// 以下三者是統一的:
// ①內容區域的偏移值 ②終止IP地址的存放位置 ③國家信息緊接在終止IP地址存放位置后
}
//---------------------------------------------------------------------------
// 給定一個IP地址(四段點分字符串形式),分解到TStrings中
void __fastcall SplitStringToStringList(String strSrc, String strSplitChar, TStringList *pList)
{
while(strSrc.Pos(strSplitChar))
{
pList->Add(strSrc.SubString(1, strSrc.Pos(strSplitChar) - 1));
strSrc = strSrc.SubString(strSrc.Pos(strSplitChar) + 1, strSrc.Length());
}
pList->Add(strSrc);
}
//---------------------------------------------------------------------------
DWORD __fastcall TQQWry::GetIPValue(String strIP)
{
TStringList *pList = new TStringList;
SplitStringToStringList(strIP, ".", pList);
DWORD dwRet = 0;
for(int i=3; i>-1; i--)
dwRet += pList->Strings[i].ToInt() * (pow(256, 3-i));
delete pList;
return dwRet;
}
//---------------------------------------------------------------------------
// 給定一個IP地址(四段點分字符串形式),返回該IP地址所在的記錄號
DWORD __fastcall TQQWry::SearchIPRecordID(DWORD dwIPRecordFrom,
DWORD dwIPRecordTo, DWORD dwIPValue)
{
DWORD dwCompareIPValue1 = 0, dwCompareIPValue2 = 0;
FFileStream->Seek(FFirstIPOffset + ((dwIPRecordTo - dwIPRecordFrom) / 2
+ dwIPRecordFrom - 1) * 7, soFromBeginning);
FFileStream->Read(&dwCompareIPValue1, 4);
FFileStream->Seek(FFirstIPOffset + ((dwIPRecordTo - dwIPRecordFrom) / 2
+ dwIPRecordFrom) * 7, soFromBeginning);
FFileStream->Read(&dwCompareIPValue2, 4);
// 找到了
if(dwIPValue >= dwCompareIPValue1 && dwIPValue < dwCompareIPValue2)
return (dwIPRecordTo - dwIPRecordFrom) / 2 + dwIPRecordFrom;
else
{
// 后半段找
if(dwIPValue > dwCompareIPValue1)
return SearchIPRecordID((dwIPRecordTo - dwIPRecordFrom) / 2
+ dwIPRecordFrom + 1, dwIPRecordTo, dwIPValue);
// 前半段找
else
{
if(dwIPValue < dwCompareIPValue1)
return SearchIPRecordID(dwIPRecordFrom,
(dwIPRecordTo - dwIPRecordFrom) / 2
+ dwIPRecordFrom - 1, dwIPValue);
}
}
return 0;
}
//---------------------------------------------------------------------------
DWORD __fastcall TQQWry::GetIPRecordID(String strIP)
{
if(strIP.Length() < 7 || strIP.Length() > 15)
return 1;
if(INADDR_NONE == inet_addr(strIP.c_str()))
return 1;
return SearchIPRecordID(1, GetIPRecordCount(), GetIPValue(strIP));
}
//---------------------------------------------------------------------------
bool CompactMDB(String strMdbFileName, String strPass1, String strPass2)
{
bool bReturn;
String strFileTemp = ChangeFileExt(strMdbFileName, ".Tmp");
String strProvider1 = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
strMdbFileName + ";Jet OLEDB:Database Password=" + strPass1;
String strProvider2 = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" +
strFileTemp + ";Jet OLEDB:Database Password=" + strPass2;
Variant AdoObj;
try
{
if(FileExists(strFileTemp))
DeleteFile(strFileTemp);
AdoObj = Variant::CreateObject("JRO.JetEngine");
AdoObj.OleProcedure("CompactDatabase",
WideString(strProvider1), WideString(strProvider2));
if(FileExists(strMdbFileName))
DeleteFile(strMdbFileName);
RenameFile(strFileTemp,strMdbFileName);
bReturn = true;
}
catch(...)
{
bReturn = false;
}
AdoObj.Clear();
return bReturn;
}
#pragma package(smart_init)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -