Solved

Newbie Alert - Working with strings and files

Posted on 2004-04-05
16
134 Views
Last Modified: 2010-04-05
As the title suggest I am new to delphi or programming in general (only been doing it for like 2 weeks now) so please bear with me as I do my best to explain my questions.

I need to write some text from a memo to a text file like this.

Starting Point: memo text here :Ending Point

where "Starting Point:" is the text from an edit box and ":Ending Point" is the literal phrase ":Ending Point"

In the file I will have lots of different blocks like the one above  but each should begin with "Starting Point:" and end with ":Ending Point" so my first question is if there is an easy/efficent way to do this ?

My next question is now that I have all those blocks in the text file how can I extract just one of them from the file and show it back on my memo ?

And finally how can I delete one of the above blocks including the Starting Point: and :Ending Point stuff.

I hope 200 points is enough for this question because it's all I have left :)
0
Comment
Question by:EE_Newguy
  • 4
  • 3
  • 2
  • +2
16 Comments
 
LVL 2

Expert Comment

by:ferhad
ID: 10756822
I understood the part of your question and will answer to this part. You can load file into Memo component using following code:

Memo1.Lines.LoadFromFile(FileName);

Hope it will help you
Regards Ferhad
0
 
LVL 2

Expert Comment

by:ferhad
ID: 10756864
I will tell you what i have understood from your question. You want to add some text from some EditBox into file than insert text of Memo component to this text file and finally to insert text of another EditBox to this file. The text of Memo will be in center. The text of Edit1 at the top and the text of Edit2 at bottom. If i am wrong explain me a little bit what you exactly want.
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10756919
If each block starts with "Starting Point:" and ends with "Ending Point:" then you have nothing that is unique to search for when attempting to extract a certain block. Unless of course they were uniquely identified. Expecially if your looking for a particular block. If you want all those blocks, then its not a problem. However, wanting one particular block out of them all, it becomes a problem of identifying the block. If they were uniquely identified,

Example:

"Starting Point 1"

<Some Text>

 "Ending Point 1"

OR

"1 Starting Point"

<Some Text>

 "1 Ending Point "

OR

"Starting Point A"

<Some Text>

 "Ending Point A"

An other way would be if you knew the exact Start Line number and End Line number of the block of text in the memo.

Example: Deleting the block

For I:= EndLine downto StartLine
 Memo1.Lines.Delete(I);


Example: extracting the block

MyBlock: TStringList.Create;

For I:= StartLine to EndLine do
 MyBlock.Lines.Add(Memo1.Lines[I]);


Hope this helps!

SHane
0
 
LVL 17

Expert Comment

by:mokule
ID: 10756998
Here is one of the possible solutions.
Procedure ReadMemo reads selected block from a file

unit Main;

interface

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

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  procedure ReadMemo(Desired: integer);
  public
    { Public declarations }
  end;

const
  START_TXT = 'Starting Point:';
  END_TXT = ':Ending Point';
var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  F: TextFile;
  I: integer;
begin
  AssignFile(F,'file.txt');
  if FileExists('file.txt') then
    Append(F)
  else
    Rewrite(F);

  Writeln(F,START_TXT);
  for I := 0 to Memo1.Lines.Count-1 do
    Writeln(F,Memo1.Lines[I]);
  Writeln(F,END_TXT);

  CloseFile(F);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ReadMemo(2);  // for example 2 block - must be something wiser
end;

procedure TForm1.ReadMemo(Desired: integer);
var
  F: TextFile;
  I: integer;
  str: string;
begin
  if FileExists('file.txt') then
    begin
    AssignFile(F,'file.txt');
    FileMode := 0;
    Reset(F);

    I := 0;
    while not Eof(F) do
      begin
      Readln(F,str);
      if str = START_TXT then
        begin
        Inc(I);
        if I = Desired then
          break;
        end;
      end;
    Memo1.Clear;
    while not Eof(F) do
      begin
      Readln(F,str);
      if str <> END_TXT then
        Memo1.Lines.Add(str)
      else
        break;
      end;

    CloseFile(F);
    end;
end;

end.
0
 

Author Comment

by:EE_Newguy
ID: 10757278
=====================================
To ferhad
=====================================

You pretty much understand what I am getting at except the last edit box will not be need because I will be using the contstant ":Ending Point" for the last part.


=====================================
To shaneholmes
=====================================

 I think you missed this part of what I said above so I will repost it here.

where "Starting Point:" is the text from an edit box and ":Ending Point" is the literal phrase ":Ending Point"

So as you can "Starting Point:" is not what it will be in the file but I had to put it in the example to show the layout of the blocks. Maybe it would have been better to say it like this "Edit1.Text:" memo text ":Ending Point"


===================================
To mokule
===================================

 Haven't tried your solution yet but I think you also missed the part where I will be using the text from an edit box as the "Starting Point:" value. Like I said to shaneholmes I only put "Starting Point:" to show the layout of the blocks.
0
 
LVL 17

Accepted Solution

by:
mokule earned 68 total points
ID: 10757410
As to me You are right, but corrections are not big

In place of
  Writeln(F,START_TXT);
should be
  Writeln(F,Edit1.Text);
-------------
    I := 1;
    while (not Eof(F)) and (I < Desired) do
      begin
      Readln(F,str);
      if str = END_TXT  then
        Inc(I);
      end;
    Memo1.Clear;
-------------
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 11

Assisted Solution

by:shaneholmes
shaneholmes earned 66 total points
ID: 10757417
var
 I: Integer;
 LineList: TStringList;
 StartLine: Integer = -1;
 EndLine: Integer = -1;

for I:= 0 to Memo1.Lines.Count - 1 do
begin
 if Pos(edit1.Text, Memo1.Lines[I]) <> 0 then
   StartLine:= I;
 if Pos('End Point:', Memo1.Lines[I]) <> 0 then
    EndLine:= I;
 if (StartLine <> -1)  AND (EndLine <> -1) then
 break;
end;

For I:= StartLine to EndLine do
 LineList.Add(Memo1.Lines[I]);

LineList.SaveToFile('MyFile.Txt');

Shane
0
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10757434
TO delete, do the following

For I:= EndLine Downto StartLine do
Memo1.Lines.Delete(I);

Shane
0
 

Author Comment

by:EE_Newguy
ID: 10757600
Thank you all for your comments I will let you all know how it goes after I wake up cuz right now I am exhausted and need sleep
0
 
LVL 17

Expert Comment

by:geobul
ID: 10758057
Hi,

My version (not fully tested):

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Memo1: TMemo;
    btnLoad: TButton;
    btnSave: TButton;
    btnDelete: TButton;
    procedure btnLoadClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

const
  Filename = 'c:\memos.txt';
  MemoEnd = ':Ending Point';

var
  sl: TStringList;

function DeleteBlock(title: string): boolean;
var
  i, k: integer;
  s: string;
begin
  result := true;
  try
    sl.LoadFromFile(Filename);
    i := Pos(title, sl.Text);
    if i > 0 then begin
      s := Copy(sl.Text,1, i -1);
      sl.Text := Copy(sl.Text, i, Length(sl.Text));
      k := Pos(MemoEnd, sl.Text);
      if k > 0 then begin
        s := s + Copy(sl.Text, k + 13, Length(sl.Text));
        sl.Text := s;
        sl.SaveToFile(Filename);
      end;
    end;
  except
    result := false;
  end;
end;

function ReadBlock(title: string; body: TStrings): boolean;
var
  i: integer;
begin
  result := true;
  try
    body.Clear;
    sl.LoadFromFile(Filename);
    i := Pos(title, sl.Text);
    if i > 0 then begin
      body.Text := Copy(sl.Text, i, Length(sl.Text));
      i := Pos(MemoEnd, body.Text);
      if i > 0 then begin
        body.Text := Copy(body.Text, 1, i + 12);
      end;
    end;
  except
    result := false;
  end;
end;

function WriteBlock(title: string; body: TStrings): boolean;
var
  i: integer;
begin
  result := true;
  try
    // delete the block first
    if FileExists(Filename) then begin
      sl.LoadFromFile(Filename);
      i := Pos(title, sl.Text);
      if i > 0 then begin
        DeleteBlock(title);
        sl.LoadFromFile(Filename);
      end;
    end;
    sl.Add(title);
    sl.Add(body.Text);
    sl.Add(MemoEnd);
    sl.SaveToFile(Filename);
  except
    result := false;
  end;
end;

procedure TForm1.btnLoadClick(Sender: TObject);
begin
  if not ReadBlock(Edit1.Text, Memo1.Lines) then
    ShowMessage('Error reading the block');
end;

procedure TForm1.btnSaveClick(Sender: TObject);
begin
  if not WriteBlock(Edit1.Text, Memo1.Lines) then
    ShowMessage('Error writing the block');
end;

procedure TForm1.btnDeleteClick(Sender: TObject);
begin
  if not DeleteBlock(Edit1.Text) then
    ShowMessage('Error deleting the block');
end;

initialization
  sl := TStringList.Create;

finalization
  sl.Free;

end.

Regards, Geo
0
 

Author Comment

by:EE_Newguy
ID: 10762211
Thanks Geo for your comments and your solution is the most complete of the three and would work great except one thing.

when reading the text back into the memo I want to remove the "Starting Point:" and ":Ending Point" phrases so what do I need to do to remove them or better yet not include them in the first place.

In other words if I have in the file a block that goes like this.

Everybody: eat your dinner :Ending Point

all I want to read back to the memo is "eat your dinner" not the Everybody: and :Ending Point stuff.
0
 

Author Comment

by:EE_Newguy
ID: 10762442
Geo
=====================================

 I know you said your comment was not fully tested so I just thought I would point out a couple of bugs I found.

If I add an block with the title of "test3" and then add another one with the title of "test33" and  if i put "test3" into the edit box and press the delete button it will delete "test3" (which it's supposed to do) but if i press the delete button again it will delete "test33" as well (which it should not do)

The same thing goes for loading... If i delete "test3" and press the load button it will load "test33" even though "test3" is in the edit box

Finally If I save a title of "gone fishing" to the file and then delete the file and save the title "gone fishing" again it adds it twice to the file. Thank you for your time.

======================================


Shaneholmes
======================================
 Where do I put the last code(s) you posted and not sure but I don't see anything about the reading of the text back to the memo. Thank you for your time



======================================
mokule

 Your code would also work I think but the ReadMemo Procedure needs to be changed so it will work with the edit1.text instead of a number and not sure but I did not see a method to delete a block so if you can add that as well it would be great. Thank you for your time.
0
 
LVL 17

Assisted Solution

by:geobul
geobul earned 66 total points
ID: 10767900
Hi,

1. removing both points:

function ReadBlock(title: string; body: TStrings): boolean;
var
  i: integer;
begin
  result := true;
  try
    body.Clear;
    sl.LoadFromFile(Filename);
    i := Pos(title, sl.Text);
    if i > 0 then begin
      body.Text := Copy(sl.Text, i+Length(title), Length(sl.Text));
      i := Pos(MemoEnd, body.Text);
      if i > 0 then begin
        body.Text := Copy(body.Text, 1, i-1);
      end;
    end;
  except
    result := false;
  end;
end;

2. If you have no clear rule where a starting point ends it's not possible to solve the second issue. For instance: you must use ':' at the end of a starting point. Only following this rule 'test3:' could be distinguished from 'test33:'. This was your example actually. Is that clear enough?

Regards, Geo
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now