Code
unit UStaMissSoff;
interface
uses
Windows, Classes, IniFiles, Forms, SysUtils;
type
TMissResult = array[1..3] of Integer;
PMissSoft = ^TMissSoft;
TMissSoft = packed record
MissSoft: string[10];
Date: string[11];
Pid: string[16];
Index: Integer;
end;
TCMissSoftSta = class
private
FStringHash: TStringHash;
Flist: TList;
FFileStream: TFileStream;
FRTLCriticalSection: TRTLCriticalSection;
protected
procedure Lock;
procedure UnLock;
procedure AppendFileStream(const Data: TMissSoft);
procedure UppFileStream(const Data: TMissSoft);
public
constructor Create(HashMax: Integer = 20000; FileName: string = 'StatisticsDate');
destructor Destroy; override;
procedure Add(const Pid, MissSoft: string);
procedure GetMissSoft(var MissResult: TMissResult; DateStr: String);
end;
implementation
{ TCMissSoftSta }
procedure TCMissSoftSta.Add(const Pid, MissSoft: string);
var
PMissSoft1: PMissSoft;
AMissSoft: TMissSoft;
begin
Lock;
if Length(Pid) = 0 then Exit;
if FStringHash.ValueOf(Pid) = -1 then
begin
New(PMissSoft1);
PMissSoft1.MissSoft := Trim(MissSoft);
PMissSoft1.Date := FormatDateTime('YYYY-MM-DD', Now);
PMissSoft1.Pid := Trim(Pid);
PMissSoft1.Index := Flist.Count;
FStringHash.Add(PMissSoft1.Pid, Flist.Count);
Flist.Add(PMissSoft1);
AppendFileStream(PMissSoft1^);
end
else
begin
AMissSoft.MissSoft := MissSoft;
AMissSoft.Date := FormatDateTime('YYYY-MM-DD', Now);
AMissSoft.Pid := Pid;
AMissSoft.Index := PMissSoft(Flist[FStringHash.ValueOf(Pid)]).Index;
PMissSoft(Flist[FStringHash.ValueOf(Pid)]).MissSoft := MissSoft;
PMissSoft(Flist[FStringHash.ValueOf(Pid)]).Date := FormatDateTime('YYYY-MM-DD', Now);
UppFileStream(AMissSoft);
end;
UnLock;
end;
constructor TCMissSoftSta.Create(HashMax: Integer = 20000; FileName: string = 'StatisticsDate');
var
Dir, StatisticsDataName: string;
PMissSoft1: PMissSoft;
Index: Integer;
begin
Flist := TList.Create;
InitializeCriticalSection(FRTLCriticalSection);
FStringHash := TStringHash.Create(HashMax);
Dir := ExtractFilePath(Application.ExeName) + 'StatisticsMissSoft\';
StatisticsDataName := Dir + FileName + '.dat';
if not DirectoryExists(Dir) then
ForceDirectories(Dir);
try
if FileExists(StatisticsDataName) then
begin
FFileStream := TFileStream.Create(StatisticsDataName, fmOpenReadWrite);
FFileStream.Position := 0;
while FFileStream.Position < FFileStream.Size do
begin
New(PMissSoft1);
Index := FFileStream.Position div SizeOf(TMissSoft(PMissSoft1^));
FFileStream.Read(PMissSoft1^, SizeOf(TMissSoft(PMissSoft1^)));
Flist.Add(PMissSoft1);
FStringHash.Add(PMissSoft(Flist[index])^.Pid, PMissSoft(Flist[index])^.Index);
end;
end
else
FFileStream := TFileStream.Create(StatisticsDataName, fmCreate);
except
end;
end;
destructor TCMissSoftSta.Destroy;
begin
while FList.Count > 0 do
begin
Dispose(PMissSoft(FList[FList.Count - 1]));
FList.Delete(FList.Count - 1);
end;
FFileStream.Free;
FStringHash.Free;
DeleteCriticalSection(FRTLCriticalSection);
inherited;
end;
procedure TCMissSoftSta.Lock;
begin
EnterCriticalSection(FRTLCriticalSection);
end;
procedure TCMissSoftSta.UnLock;
begin
LeaveCriticalSection(FRTLCriticalSection);
end;
procedure TCMissSoftSta.AppendFileStream(const Data: TMissSoft);
begin
if not Assigned(FFileStream) then Exit;
Lock;
FFileStream.Position := FFileStream.Size;
FFileStream.Write(Data, SizeOf(Data));
UnLock;
end;
procedure TCMissSoftSta.UppFileStream(const Data: TMissSoft);
begin
if not Assigned(FFileStream) then Exit;
Lock;
FFileStream.Position := SizeOf(Data) * (Data.Index );
FFileStream.Write(Data, SizeOf(Data));
UnLock;
end;
procedure TCMissSoftSta.GetMissSoft(var MissResult: TMissResult; DateStr: String);
var
I, J: Integer;
begin
Lock;
ZeroMemory(@MissResult, SizeOf(MissResult));
for I := 0 to Flist.Count - 1 do
begin
if (CompareStr(UpperCase(PMissSoft(Flist[I])^.Date), DateStr) = 0) and (Length(PMissSoft(Flist[I])^.MissSoft) > 0) then
begin
for J := 1 to 3 do
begin
if Pos(IntToStr(J), PMissSoft(Flist[I])^.MissSoft) > 0 then
MissResult[J] := MissResult[j] + 1;
end;
end;
end;
UnLock;
end;
end.
unit UStaMissSoff;
interface
uses
Windows, Classes, IniFiles, Forms, SysUtils;
type
TMissResult = array[1..3] of Integer;
PMissSoft = ^TMissSoft;
TMissSoft = packed record
MissSoft: string[10];
Date: string[11];
Pid: string[16];
Index: Integer;
end;
TCMissSoftSta = class
private
FStringHash: TStringHash;
Flist: TList;
FFileStream: TFileStream;
FRTLCriticalSection: TRTLCriticalSection;
protected
procedure Lock;
procedure UnLock;
procedure AppendFileStream(const Data: TMissSoft);
procedure UppFileStream(const Data: TMissSoft);
public
constructor Create(HashMax: Integer = 20000; FileName: string = 'StatisticsDate');
destructor Destroy; override;
procedure Add(const Pid, MissSoft: string);
procedure GetMissSoft(var MissResult: TMissResult; DateStr: String);
end;
implementation
{ TCMissSoftSta }
procedure TCMissSoftSta.Add(const Pid, MissSoft: string);
var
PMissSoft1: PMissSoft;
AMissSoft: TMissSoft;
begin
Lock;
if Length(Pid) = 0 then Exit;
if FStringHash.ValueOf(Pid) = -1 then
begin
New(PMissSoft1);
PMissSoft1.MissSoft := Trim(MissSoft);
PMissSoft1.Date := FormatDateTime('YYYY-MM-DD', Now);
PMissSoft1.Pid := Trim(Pid);
PMissSoft1.Index := Flist.Count;
FStringHash.Add(PMissSoft1.Pid, Flist.Count);
Flist.Add(PMissSoft1);
AppendFileStream(PMissSoft1^);
end
else
begin
AMissSoft.MissSoft := MissSoft;
AMissSoft.Date := FormatDateTime('YYYY-MM-DD', Now);
AMissSoft.Pid := Pid;
AMissSoft.Index := PMissSoft(Flist[FStringHash.ValueOf(Pid)]).Index;
PMissSoft(Flist[FStringHash.ValueOf(Pid)]).MissSoft := MissSoft;
PMissSoft(Flist[FStringHash.ValueOf(Pid)]).Date := FormatDateTime('YYYY-MM-DD', Now);
UppFileStream(AMissSoft);
end;
UnLock;
end;
constructor TCMissSoftSta.Create(HashMax: Integer = 20000; FileName: string = 'StatisticsDate');
var
Dir, StatisticsDataName: string;
PMissSoft1: PMissSoft;
Index: Integer;
begin
Flist := TList.Create;
InitializeCriticalSection(FRTLCriticalSection);
FStringHash := TStringHash.Create(HashMax);
Dir := ExtractFilePath(Application.ExeName) + 'StatisticsMissSoft\';
StatisticsDataName := Dir + FileName + '.dat';
if not DirectoryExists(Dir) then
ForceDirectories(Dir);
try
if FileExists(StatisticsDataName) then
begin
FFileStream := TFileStream.Create(StatisticsDataName, fmOpenReadWrite);
FFileStream.Position := 0;
while FFileStream.Position < FFileStream.Size do
begin
New(PMissSoft1);
Index := FFileStream.Position div SizeOf(TMissSoft(PMissSoft1^));
FFileStream.Read(PMissSoft1^, SizeOf(TMissSoft(PMissSoft1^)));
Flist.Add(PMissSoft1);
FStringHash.Add(PMissSoft(Flist[index])^.Pid, PMissSoft(Flist[index])^.Index);
end;
end
else
FFileStream := TFileStream.Create(StatisticsDataName, fmCreate);
except
end;
end;
destructor TCMissSoftSta.Destroy;
begin
while FList.Count > 0 do
begin
Dispose(PMissSoft(FList[FList.Count - 1]));
FList.Delete(FList.Count - 1);
end;
FFileStream.Free;
FStringHash.Free;
DeleteCriticalSection(FRTLCriticalSection);
inherited;
end;
procedure TCMissSoftSta.Lock;
begin
EnterCriticalSection(FRTLCriticalSection);
end;
procedure TCMissSoftSta.UnLock;
begin
LeaveCriticalSection(FRTLCriticalSection);
end;
procedure TCMissSoftSta.AppendFileStream(const Data: TMissSoft);
begin
if not Assigned(FFileStream) then Exit;
Lock;
FFileStream.Position := FFileStream.Size;
FFileStream.Write(Data, SizeOf(Data));
UnLock;
end;
procedure TCMissSoftSta.UppFileStream(const Data: TMissSoft);
begin
if not Assigned(FFileStream) then Exit;
Lock;
FFileStream.Position := SizeOf(Data) * (Data.Index );
FFileStream.Write(Data, SizeOf(Data));
UnLock;
end;
procedure TCMissSoftSta.GetMissSoft(var MissResult: TMissResult; DateStr: String);
var
I, J: Integer;
begin
Lock;
ZeroMemory(@MissResult, SizeOf(MissResult));
for I := 0 to Flist.Count - 1 do
begin
if (CompareStr(UpperCase(PMissSoft(Flist[I])^.Date), DateStr) = 0) and (Length(PMissSoft(Flist[I])^.MissSoft) > 0) then
begin
for J := 1 to 3 do
begin
if Pos(IntToStr(J), PMissSoft(Flist[I])^.MissSoft) > 0 then
MissResult[J] := MissResult[j] + 1;
end;
end;
end;
UnLock;
end;
end.
程序思路主要目的,哈希 和LIST 和流文件同步操作,避免在数据很大时在单性列表中做A[0]到A[MAXA]做单循环,只需要在哈希中的桶里做单循环就可以,然后取出VALUE在LIST和文件流中定位 (另外哈希+ 双向链表效果更好)
根据传递进来的硬件PID加载到哈希中,然后根据硬件PID在哈希中是否存在,如果PID存在,则取出哈希中对应的VALUE,因为加载到哈希中的时候,将结构指针中的INDEX 定为它在LIST中的位置,同时也是它在哈希中的VALUE,所以就能快速根据取出的VALUE,直接在LIST定位(同时也是该结构指针在流文件中的位置,所以读写流文件也能直接定位),然后再操作修改