1
votes

I'm implementing a local cache to speed up DNS lookups (IP->hostname). The cache is loaded from a CSV file("1.1.1.1host.example.com") into a TStringList with two fields:

TStringList[0] := IPAddress;
TStringList[1] := HostName;

Since I will be querying TStringList via the IP, I obliously want the first field to be sorted:

TStringList.sorted := True;

Will that take care of it so that I can find faster with

IPResolved:=TStringList[TStringList.IndexOf('1.1.1.1'),1];

?

Thanks!

1
Obviously the CSV file has a space (which was cut) between IP and Hostnameasg2012
TStringList is absolutely the wrong data type. You want a record with two string fields, IPAddress and HostName. Then you want to use TList<T> to hold these records.David Heffernan
@David, better use a dictionary, since OP wants to search by IP, what would be the key.TLama
You can use IndexOfName with such Name=Value paired string list. Or use generics' TDictionary instead of string list like I've posted below...TLama
TDictionary sounds good. Sorted TList with binary search was what I had in mind. Dictionary probably better. Idea of using assembler is simply terrible. Boo hiss!David Heffernan

1 Answers

12
votes

Disclaimer:

This won't answer you how to sort a string list or how to load your data into a string list. It will offer you to use a hash table, which is more efficient than using a string list for your purpose (40k name, value pairs with the search by name).

Alternative:

Since you have Delphi XE2, you can use generics TDictionary class. It will contain IP address as the key and host name as the value. In the following code is shown, how to fill a dictionary and how to search for the value (host name) by a given key (IP address):

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Generics.Collections;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    IPList: TDictionary<string, string>;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  // create the TDictionary instance
  IPList := TDictionary<string, string>.Create;
  // here you will read your CSV file and add the items in a loop
  // I've used here some of the major IP addresses for Sweden
  IPList.Add('77.244.224.0', 'Insat Net AB');
  IPList.Add('79.138.128.0', 'Hi3G Access AB');
  IPList.Add('62.181.192.0', 'DGC Access AB');
  IPList.Add('81.216.128.0', 'TDC Swerige AB');
  IPList.Add('80.252.176.0', 'Phonera Networks AB');
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // release a dictionary instance
  IPList.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  HostName: string;
begin
  // and how to search by the IP address and get the host name if found
  if IPList.TryGetValue('81.216.128.0', HostName) then
    ShowMessage(HostName)
  else
    ShowMessage('IP address not found!');
end;

end.

Extension:

The above solution you can then simply extend to use a structure to store more than only a host name, e.g. also a host location:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Generics.Collections;

type
  TIPData = record
    HostName: string;
    HostLocation: string;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    IPList: TDictionary<string, TIPData>;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  IPData: TIPData;
begin
  IPList := TDictionary<string, TIPData>.Create;

  IPData.HostName := 'Broadnet Europe France';
  IPData.HostLocation := 'France';
  IPList.Add('78.155.128.0', IPData);

  IPData.HostName := 'DNA Palvelut Oy';
  IPData.HostLocation := 'Finland';
  IPList.Add('62.113.160.0', IPData);

  IPData.HostName := 'CD-Telematika a.s.';
  IPData.HostLocation := 'Czech republic';
  IPList.Add('89.203.128.0', IPData);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  IPList.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  IPData: TIPData;
begin
  if IPList.TryGetValue('89.203.128.0', IPData) then
    ShowMessage('Provider ' + IPData.HostName + ' from ' + IPData.HostLocation)
  else
    ShowMessage('IP address not found!');
end;

end.