How to Replace Lines in Textfile

Stupid Question:
I've got a Textfile with 40 Lines.
I want to replace the 26th Line. How?
Do I have to read the whole File to a TStrings Object, do my Replacement there and replace the old file with a new one, containing the TStrings?

Regards, Oli
LVL 1
Oli2Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

JaymolCommented:
I'm afraid that the answer to that is....Yes. (In a way)

An easier one would be open the file to alter, create a new one, read a line, write a line, read a line, write a line etc.. until you get to the one to miss out.  Just don't write it.  Then, continue until done.  Delete the original and rename the new one.  (Put some error checking in it so it doesn't delete the original if it screwed up!)

That's about it I'm afraid.

John.
0
JaymolCommented:
Actually, what I meant to say was....

When you get to the one to replace, read a line, write the new one.  (Not miss it out.)
0
Oli2Author Commented:
It should be working with theWinAPI  WriteFile function, I guess. Anybody got some example-code to this?

Regards, Oli
0
C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

MadshiCommented:
You can map the file into memory (APIs CreateFile, CreateFileMapping, MapViewOfFile in this order), then you can manipulate the content directly by accessing the content as normal memory. That should be a lot faster with big text files.

Regards, Madshi.
0
Oli2Author Commented:
Hi, Madshi!

uuhmm...
"then you can manipulate the content directly by accessing the content as normal memory"
uuhhmm....

you would't happen to have some sourcecode around, do ya? ;-)

I don't really get the clue yet.

Regards, Oli
0
BatalfCommented:
Could something like this help you?


var FileList:TStringlist;
    loopint:integer;
 begin
   FileList:=Tstringlist.Create;
   FileList.LoadFromFile('yourfile.txt');
   for loopint:=Filelist.count-1 downto 0 do
   begin
     If loopint = 26 do
     begin
      filelist.delete(loopint);
      filelist.add('Whatever',26);
    end;

   end;
Filelist.SaveToFile('yourfile.txt');


end;

Batalf


0
BatalfCommented:
A minor error in the code above.

How about this?

var FileList:TStringlist;
    loopint:integer;
 begin
   FileList:=Tstringlist.Create;
   FileList.LoadFromFile('yourfile.txt');
      filelist.delete(26);
      filelist.add('Whatever',26);

   end;
Filelist.SaveToFile('yourfile.txt');


end;

Batalf




0
Oli2Author Commented:
Hi, Batalf,

sorry, but this is the "easy" way. I knew that one. I want to prevent saving the whole file again.

Regards, Oli
0
JoeBoothCommented:
Are the lines fixed length?  If so, you can compute an offset to where the 26th line starts (25* lineSize).  Then write your new line into the file and close the file.

VAR
   F    : TextFile;
   cNew : String;
BEGIN
   AssignFile(F, cFileName);
   Reset(F,nLineSize);
   Seek(F,25*nLineSize);
   WriteLn(F,cNew);
   CloseFile(F);
END;
   
0
Oli2Author Commented:
Sorry, JoeBooth,
the lines are not fixed length.
Also, as far as I know, you can only append lines to a textfile by using writeln. Isn't that true?

Regards, Oli

0
JoeBoothCommented:
Actually, I meant to use  Write() instead, but it doesn't answer your problem.  It is easy to write back just a portion of the file, but identifying the position in the file looks like it will be the problem you need to solve.

Good luck ...
0
rwilson032697Commented:
I have to ask: Is the file really just 40 lines long, or could it be really large?

If its going to be small, do it the easy way - save the heartbeats. The user is never going to notice!

Cheers,

Raymond.
0
MadshiCommented:
Yes, Raymond is right. The worry about optimized code is only worth the pain, if the files are quite long.

Well, here is some code:

interface

type TFileAsPtr = pointer;

function  OpenFileAsPtr  (file_         : string;
                          out size  : cardinal;
                          out buffer    : pointer   ) : TFileAsPtr;
procedure CloseFileAsPtr (var fileAsPtr : TFileAsPtr);

implementation

type
  TFileAsPtrEx = record
    fileHandle : cardinal;
    mapHandle  : cardinal;
    buffer_    : pointer;
  end;
  TPFileAsPtrEx = ^TFileAsPtrEx;

function OpenFileAsPtr(file_      : string;
                       out size   : cardinal;
                       out buffer : pointer) : TFileAsPtr;
var fap : TPFileAsPtrEx absolute result;
begin
  New(fap);
  with fap^ do begin
    fileHandle := CreateFile(pchar(file_), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
    if fileHandle <> INVALID_HANDLE_VALUE then begin
      size := GetFileSize(fileHandle, nil);
      mapHandle := CreateFileMapping(fileHandle, nil, PAGE_READONLY, 0, 0, nil);
      if mapHandle <> 0 then begin
        buffer_ := MapViewOfFile(mapHandle, FILE_MAP_READ, 0, 0, 0);
        if buffer_ <> nil then begin
          buffer := buffer_;
        end else begin
          CloseHandle(mapHandle);
          Dispose(fap);
          fap := nil;
        end;
      end else begin
        CloseHandle(fileHandle);
        Dispose(fap);
        fap := nil;
      end;
    end else begin
      Dispose(fap);
      fap := nil;
    end;
  end;
end;

procedure CloseFileAsPtr(var fileAsPtr: TFileAsPtr);
var fap : TPFileAsPtrEx absolute fileAsPtr;
begin
  if fap <> nil then begin
    with fap^ do begin
      UnmapViewOfFile(buffer_);
      CloseHandle(mapHandle);
      CloseHandle(fileHandle);
    end;
    Dispose(fap);
    fap := nil;
  end;
end;

You can call this stuff like this:

function ReadFileIntoStr(file_: string) : string;
var fap  : TFileAsPtr;
    buf  : pointer;
    size : cardinal;
begin
  fap := OpenFileAsPtr(file_, buf, size);
  if fap <> nil then
    try
      SetLength(result, size);
      Move(buf^, pointer(result)^, size);
    finally CloseFileAsPtr(fap) end;
end;

Of course this is only an example about how to use the functions. But you should get the idea.
Also I must say, these functions only open the file for read access. So will have to change some things to make it fit your needs.

Regards, Madshi.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Oli2Author Commented:
Great! Thanx, Madshi ! This will lead me into the right direction.
By the way: If my Textfile would have only 40 lines, I wouldn't have bothered you guys...  ;-)

Regards, Oli
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.