goggle pink
goggle pink

Reputation: 132

Deleting all lines in text file with delphi

If I have already created text file, then I need to delete all line in text file for new fresh text. How we do it? Of course without deleting the text file first and then create a new one, just delete the text file content then add a new line text. To avoid error when a person in front of the monitor still opening that text file.

I'm using TextFile type, not TFileStream. Append, Rewrite, and closefile function to open file.

Just like

DeleteThisTextFileContent(ExtractFilePath(Application.Exename)+'log.txt');

Thanks !

Upvotes: 2

Views: 9004

Answers (2)

Arioch 'The
Arioch 'The

Reputation: 16065

It seems to me topicstarter is somewhat confused with what he wants and what would happen in the system.

The claim is: I need to delete ...content of ... file ... without deleting the file first and then creating a new one. To avoid error when a person in front of the monitor still opening that text file. Just delete the file content then add a new line text.

However, some other answer uses ReWrite which - since the eldest Turbo Pascal 1.0 - does exactly what the topicstarter claimed he wants to avoid - deleting the old file.

If an external file with the same name already exists, it is deleted and a new empty file is created in its place.
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Rewrite


Well, since erasing the file is okay for the topicstarter then i'd like to present few simpler ways to do it - few oneliners.

The one, using http://jcl.sf.net is

procedure DeleteThisFileContent(const FileToClear: TFileName);
begin
   JclStringList.SaveToFile(FileToClear);
end;

The one, using stock Delphi is

procedure DeleteThisFileContent(const FileToClear: TFileName);
begin
   TFileStream.Create( FileToClear, fmCreate ).Free;
end;

fmCreate: Create a file with the given name. If a file with the given name exists, override the existing file and open it in write mode.
http://docwiki.embarcadero.com/Libraries/XE2/en/System.Classes.TFileStream.Create

That is doing the same delete-create sequence as ReWrite but requires less boilerplate.

I believe the topicstarter can easily check file IO of his program using Process Monitor from www.SysInternals.com and check that those solutions, including some another answer there, are doing the same file delete action.


One also can really discard the content of the file without deleting it first, but that requires explicit opening the existing file and explicit discarding its content. Modifying some another answer to avoid deleting, that would be

procedure DeleteThisFileContent(const FileToClear: TFileName);
var 
  F: File;
begin
  FileMode := 2;
  AssignFile(F, FileToClear );
  ReSet(F, 1); 
  Truncate(F);
  CloseFile(F);
end;

based on old Pascal functions


Then maybe enters an issue of concurrent file access - that mentioned error when a person in front of the monitor still opening that text file.

1st of all, if the person reads a file in Notepad, that does not mean the file IS OPEN - that barely meant the file WAS OPENED, READ AND CLOSED. However if the person reads the file in Microsoft Word, then probably the file really IS OPEN RIGHT NOW. Since Windows makes little difference between the file and its name, in the last case the wished deleting of the file would be impossible using normal OS means.

But that is not all about FILE SHARING. The fact is that when some program opens the file it also specifies its demand on file sharing constraints for it. Even if the programmer did not asked for it explicitly, it just should declare its intentions to OS using some defaults. And one can check it in Delphi RTL sources. If we think about the aforementioned case when another user has the file opened in MS Word then by default the file would be opened in fmShareDenyWrite - Other applications can open the file for reading but not for writing. mode.

And that means the very attempt to open the file in reading+writing mode (the call to ReSet) would fail, it would be kind of Access Violation on filesystem level. Same would happen if the topicstarter would try to ReSet for reading+writing a file from CD-ROM or from some read-only network share. Of cause the topicstarter still is able to alter FileMode and to do a read-only ReSet of the file. However... however then the file would be opened in read-only mode, and that means that removing the file content (calling Truncate) would no more be possible.

Well, what would happen if some exotic Viewer application would have the file open, would read it up to line 1234 (and have its "cursor" there) and then suddenly our program cuts off all the content and makes the file consist of just 12 short lines ? then suddenly Viewer would have an invalid location in the file and would no more be able to read form it without some kind of error recovery path, that would re-open the file or at least re-read it from the beginning. However if the Viewer's developer did not coded this specific error recovery code, then the Viewer would just crash.

So all in all, the topicstarter should have a think about his approach toward concurrent file access (sharing):

  • Either ignore it, and hope that the program the user uses to read the file, closed that file long ago. Then he's free to delete the file and re-create it as some another answer suggests (or using one of those oneliners above). This would require thinking ahead and coding some plan what to do if it was not possible either to delete or to re-create the file.
  • Or try to actually set the file length to zero, and let any other program, a user uses to read the file, recover from this or crash and die. This however also would require the "not allowed" code path.
  • Or one may implement "round robin" scheme when the program keeps N last log files and always logs to a new one, and then tries to delete too old logs time to time. This way if delete failed it can just be logged and ignored. It would not prevent the application to log into a new file and the attempt to remove the locked outdated log would just be tried again a day or a week later.

Upvotes: 1

Ken White
Ken White

Reputation: 125747

If you're using AssignFile to open the file (as your edit makes it appear to be), you can use Rewrite:

procedure DeleteThisFileContent(const FileToClear: string);
var 
  F: TextFile;
begin
  AssignFile(F, FileToClear);
  Rewrite(F); 
  CloseFile(F);
end;

Upvotes: 8

Related Questions