Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

load text file into Tsringlist 2

Status
Not open for further replies.

LEICJDN1

Technical User
Nov 27, 2002
201
GB
Need to search a text file for a particular string to ensure no duplicates written to text file at end.

Is the best way to load the strings (comma seperated) into a stringlist, manipulate there, then save back to the text file with / without duplicates?

If so, how do i load from a text file which would look like this:

111001,123,2344,5455,6,6676

Into a TStringlist?

Thanks.
 
Can you provide a more complete example of a test file, say with 5-10 records that contains the type of duplicate you want to catch? You example shows only one record and no duplicate.

Also, how do you want the results. Is ShowMessage() sufficient?

 
Sorry, more detail needed!

A typical example would be:

10001, 6556.7, 768.78, 9765.98, 7687.9897, 675.98
10002, 5656.67, 6546.78, 643.89, 89876.78, 986.689
10003, 6564.89, 6759.98, 34532.78, 3424.56, 5658.78
10004, 6779.56, 4532.98, 124354.65, 6438.898, 1326.87

For each time the program runs, I need to check whether that particular analysis has already been done. The first figure is the unique identifier, the rest are just data for that analysis.
If the file was as above, and the user analysed picture 10002 again, when writing to output to the file at the end, I would want it to recognise 10002 as a duplicate, and ask the user whether to carry on and have 2 entries, overwrite the previous entry or cancel.

I therefore need to be able to search, as well as accurately overwrite if needed. The number of data entries for each analysis is the same.

Any help much appreciated!
 
Here is one way.

Note that if there are more than two lines with the same number, the request is ambiguous. What this routine does is show only the first match, whether or not you keep the entry. When the second one is reached it is matched with the third and so on. If you want to display ALL matches before continuing, then a different approach will be needed.

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const
  CRLF = #13 + #10;

procedure ProcessDuplicate(AList:TStringList; x,y:integer;
            var bCancel,bContinue:boolean);
var
  sText:string;
  nReply:integer;
begin
  bCancel := False;
  bContinue := False;
  sText := 'Duplicate analysis found:' + CRLF + CRLF
        + '(' + IntToStr( x+1 ) + '): ' + AList[x] + CRLF
        + '(' + IntToStr( y+1 ) + '): ' + Alist[y] + CRLF + CRLF
        + 'Do you want to keep both entries?' + CRLF + CRLF
        + '  Yes - Keep' + CRLF
        + '  No - Delete (' + IntToStr( x+1 )
                 + ') and keep (' + IntToStr( y+1 ) + ')' + CRLF
        + '  Cancel - Stop immediately and do not update the file.';
  nReply := Application.MessageBox( PChar(sText), 'Duplicate Found',
             MB_ICONEXCLAMATION + MB_YESNOCANCEL );
  if nReply = IDYES then bContinue := True;
  if nReply = IDNO then AList.Strings[x] := '';
  if nReply = IDCANCEL then bCancel := True;
end;

procedure RemoveNullStrings( AList:TStringList; var Removed:integer );
var
  i:integer;
begin
  Removed := 0;
  i := AList.IndexOf('');
  while i >= 0 do
    begin
      AList.Delete(i);
      i := AList.IndexOf('');
      Removed := Removed + 1;
    end;
end;

procedure CheckForDuplicates( AFileName:string );
var
  List:TStringList;
  i,j:integer;
  sCurrent,sCompare:string;
  bCancel,bContinue:boolean;
  nCount:integer;
begin
  List := TStringList.Create;
  try
    with List do
      begin
        LoadFromFile(AFileName);
        for i := 0 to Count - 2 do
          if Strings[i] <> '' then
          begin
            sCurrent := Trim(Copy(Strings[i], 1, Pos(',',Strings[i]) - 1));
            for j := i + 1 to Count - 1 do
              if Strings[j] <> '' then
              begin
                sCompare := Trim(Copy(Strings[j], 1, Pos(',',Strings[j]) - 1));
                if sCompare = sCurrent then
                  begin
                    ProcessDuplicate( List, i, j, bCancel, bContinue );
                    if bCancel then Exit;
                    if not bContinue then Break;
                  end; // if
              end; // for j
          end; // for i
        RemoveNullStrings( List, nCount );
        SaveToFile( AFileName );
      end; // with
  finally
    List.Free;
  end;
  ShowMessage('Check complete.  ' + IntToStr( nCount ) + ' duplicates removed');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  CheckForDuplicates( 'c:\analysis.txt' );
end;

end.
 
Wow!

Was expecting a few pointers not the complete solution.

Very generous of you Zathras.

Will implement and check, but after a quick read through it looks spot on!

Thanks again,

JDN
 
Hello!

Please try,

Code:
var
i : Integer;
MyStringList : TStringList;
begin


MyStringList := TStringList.Create;
MyStringList.LoadFromFile('c:\test.txt');

MyStringList.Delimiter := ',';
MyStringList.DelimitedText := MyStringList.Text;

//remove duplicates
MyStringList.Sorted := True;
 for i:=MyStringList.Count-1 downto 1 do 
 begin
   if CompareText(MyStringList.Strings[i],MyStringList.Strings[i-1])=0 then
   MyStringList.Delete(i);
 end;

//Just for show, load the end result into a TMemo
Memo1.Lines.Assign(MyStringList);

MyStringList.Free;

end;
 
What version of Delphi? I don't have .Delimiter or .DelimitedText in D5.
 
Hi Zathras.

Delphi6 has it.

Here is the info from the D6 Help file

TStringList Properties

In TStringList

Capacity
CaseSensitive
Count
Duplicates
Objects
Sorted
Strings

Derived from TStrings

CommaText
DelimitedText
Delimiter
Names
QuoteChar
StringsAdapter
Text
Values


TStrings.Delimiter

Specifies the delimiter used by the DelimitedText property.

property Delimiter: Char;

Description

Use Delimiter to get or set the delimiter used by the DelimitedText property. DelimitedText represents all of the strings in the TStrings object as a single string, with individual strings separated by the character that is the value of Delimiter.

---------------------------------------------------------
TStrings.DelimitedText

Represents all the strings in the TStrings object as a single delimited string.

property DelimitedText: string;

Description

Use DelimitedText to get or set all the strings in the TStrings object in a single string.

When reading DelimitedText, the resulting value delimits individual strings in two ways: each string is surrounded (before and after) by the quote character specified by the QuoteChar property. In addition, individual strings are separated by the character specified by the Delimiter property.

When writing DelimitedText, individual strings must be separated using QuoteChar at both ends, using Delimiter as a separator, or using both these methods.

Note: CommaText is the same as the DelimitedText property when Delimiter is ‘,’ and QuoteChar is ‘”’.
 
Thanks, BTecho. Nice to know. If they ever get around to upgrading here that might come in handy.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top