FUseTime := Now;
FUseTick := Windows.GetTickCount;
if FileExists(FileName) then
LoadFile(FileName)
else if Trim(sDoc) <> '' then
begin
FDocSize := Length(sDoc);
SetLength(FDocument, FDocSize);
System.Move(sDoc[1], FDocument[1], FDocSize);
end
else raise Exception.Create('没有发现可用文档内容或文件名。');
destructor TPartList.Destroy;
begin
SetLength(FDocument, 0)
//释放内存string
if FDivList <> nil then begin
FDivList.Clear;
FreeAndNil(FDivList)
//释放列表
end;
inherited Destroy;
end;
{$DEFINE NEW_PARSEDIV}
{$IFDEF NEW_PARSEDIV}
procedure TPartList.ParseDiv;
var
I: Integer;
s1: string;
begin
s1 := '';
try
for I := 1 to FDocSize do
if FDocument in ['a'..'z', 'A'..'Z', '0'..'9', '-', '_'] then
System.Continue
else FDocument := #13;
s1 := FDocument;
for I := 1 to Length(s1) do
if s1 in ['a'..'z', 'A'..'Z'] then
System.Continue
else s1 := #13;
{$ELSE}
procedure TPartList.ParseDiv;
function SubParse(const S: string): string;
var
I: Integer;
begin
Result := '';
for I := 1 to Length(S) do
if S in ['a'..'z'] then //到这儿只有小写了
Result := Result + S
else
Result := Result + #13;
//如果只是一个单词
if Result = S then Result := '';
if (Result <> '') and (Result[Length(Result)] <> #13)then
Result := Result + #13;
end;
var
I: Integer;
s1, s2: string;
begin
s1 := '';
s2 := '';
try
for I := 1 to FDocSize do
if FDocument in ['a'..'z', 'A'..'Z', '0'..'9', '-', '_'] then
s1 := s1 + lowercase(FDocument)
else if s1 <> '' then begin
s2 := s2 + s1 + #13;
//s2 := s2 + SubParse(s1);
s1 := '';
end;
SetLength(self.FDocument, FDocSize);
len := FileRead(hFile, Pointer(FDocument)^, FDocSize);
if len <> FDocSize then
begin
//读取文件数据失败,抛出错误
raise Exception.Create(SysUtils.SysErrorMessage(Windows.GetLastError));
end;
finally
FileClose(hFile);
end;
end;
for I := 1 to FDocSize do
if FDocument in ['a'..'z', 'A'..'Z', '0'..'9', '-', '_'] then
System.Continue
else FDocument := #13;
s1 := FDocument;
for I := 1 to Length(s1) do
if s1 in ['a'..'z', 'A'..'Z'] then
System.Continue
else s1 := #13;
处理两次干吗?
下面这次只是把 '0'..'9', '-', '_' 也改为 #13而已,把上面那个循环去掉,结果是完全一样的。
这样啊,那也不用处理两次啊,基于统计得知,含有-的单词毕竟是少数,可以这样做:
if ss in['a'..'z'] then
Continue
else if ss in ['A'..'Z'] then
Continue
else if ss in ['0'..'9'] then
Continue
else if ss in ['-'] then
begin
把当前的i值保存到一个数组
Continue
end else ss:= #13;
这样可以大幅减少判断的数量,因为小写字母多,可以很快跳过
我修改了一下你的GetHashValue函数
现在能返回结果 2521个,与原先的2564个相差不多了。
速度确实比我的方法快,1.77M 的文件处理时间在1秒以内。
现等待楼主用他自己的数据再测试一下看看单词纰漏情况如何,
修改后的函数如下:
function GetHashValue(const Buf
Len: Integer
HashSeed: Cardinal
IgnoreCase: Boolean = False): Cardinal;
var
P: PChar;
I: Integer;
CharByteArray: ^TCharToByteValue;
begin
Result := HashSeed;
P := @Buf;
CharByteArray := @CHAR_2_BYTEs[IgnoreCase];
for I := 1 to Len do
begin
result:=((Result shl 2) or (Result shr (SizeOf(Result) * 8 - 2))) xor
Ord(CharByteArray[P^]);
inc(p);
end;
end;
再次对errorcode的代码进行了画蛇添足,修改了AddHash函数内的语句,
errorcode应该是用了链地址抗冲突法,对冲突的判断只是简单的比较一下字符串长度和hash值,准确性有纰漏,我改为直接比对内存,代码如下:
//......................AddHash函数内
IsFind := False;
while Hash <> nil do
begin
IsFind := CompareMem(Hash.Str.buf, AStr.buf,AStr.len) and (Hash.HashData = HashData)
//修改了这句
if IsFind then break;
Hash := Hash.Next;
end;
//......................