Rewrite
是否清除现有文件的文件内容,还是删除它并创建一个新文件?
我的 app.exe 文件夹中有一个文本文件,我需要清除它。任何一个例子?
答案 0 :(得分:5)
从Delphi XE2文档中,主题Rewrite - 阅读最后引用的段落:
创建一个新文件并将其打开。
在Delphi代码中,Rewrite会创建一个名为F的新外部文件。
F是使用AssignFile与外部文件关联的任何文件类型的变量。 RecSize是一个可选表达式,只有在F是无类型文件时才能指定。如果F是无类型文件,则RecSize指定要在数据传输中使用的记录大小。如果省略RecSize,则假定默认记录大小为128字节。
如果已存在具有相同名称的外部文件,则会将其删除并在其位置创建新的空文件。
在同一文档中,链接到System.Rewrite
页面底部,修改为使用您应用的文件夹:
procedure TForm1.Button1Click(Sender: TObject);
var
F: TextFile;
AppDir: string;
begin
// Instead of ParamStr(0), you can use Application.ExeName
// if you prefer
AppDir := ExtractFilePath(ParamStr(0));
AssignFile(F, AppDir + 'NEWFILE.$$$');
Rewrite(F); // default record size is 128 bytes
Writeln(F, 'Just created file with this text in it...');
CloseFile(F);
MessageDlg('NEWFILE.$$$ has been created in the ' + AppDir + ' directory.',
mtInformation, [mbOk], 0, mbOK);
end;
但是,您应该知道Rewrite
已过时且不支持Unicode。您应该使用更现代的方法来读取和写入TFileStream或TStringWriter等文件(甚至是TStringList的简单解决方案)。
var
SL: TStringList;
AppDir: string;
begin
AppDir := ExtractFilePath(ParamStr(0));
SL := TStringList.Create;
try
SL.Add('Just created file with this text in it...');
// Add more lines here if needed, and then only save once
SL.SaveToFile(AppDir + 'NEWFILE.$$$');
MessageDlg('NEWFILE.$$$ has been created in the ' + AppDir + ' directory.',
mtInformation, [mbOk], 0, mbOK);
finally
SL.Free;
end;
end;
请注意,您无法使用TStrings
;这是一个抽象的类。您需要使用其中一个后代(TStringList
是最常用的)。
答案 1 :(得分:3)
我做了一个实验并确定REWRITE会覆盖现有文件。 它不会删除然后重新创建该文件。 你将不得不学习一些关于文件隧道的知识,我开始时对此一无所知。
program RewriteTest;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows;
//========================================================================
// Will REWRITE delete an existing file and create a new file,
// or will it overwrite the existing file?
//------------------------------------------------------------------------
// According to the Delphi documentation, it will delete the old file and
// create a new one. But is this true?
// Internally, it calls the Windows API CreateFile function with the
// CREATE_ALWAYS option.
// The Microsoft documentation for CreateFile says this will overwrite the
// existing file.
// Let's perform an experiment to see what really happens.
// Here are the steps in the experiment:
//
// 1. Select a file name.
// 2. Delete that file if it exists.
// 3. Create a file with that name.
// 4. Determine the creation time of that file. Call it A.
//
// - - As with any experiment, we first need a control case.
// We will explicitly delete the file we just created
// and then recreate the file.
//
// 5. Wait a few seconds.
// 6. Delete the file that was just created.
// 7. Again, create a file with that same name.
// 8. Determine the creation time of this new file. Call it B.
//
// - - We would expect that since the first file was deleted,
// and a new file was created, that the creation times of
// these files would be different.
// I was quite surprised to find that this hypothesis
// is WRONG!
// This is why scientific experiments have controls!
//
// Two separate files created at distinct times had the same
// Creation Date according to the operating system.
//
// - - TUNNELING: It turns out our experimental results were gummed up
// by something I knew nothing about before, called file tunneling.
// The Windows operating system has this feature which will save the
// existing meta-information about a file for "a short time" after it
// is deleted or renamed.
// If another file is created with the same name, or renamed
// to that name, the new file will be assigned the same meta-data
// as the original.
// I won't go too far into this topic here. If you're interested you
// can research it yourself. I'll just say two things about it.
// There's a very good reason for it. And it can be turned off.
//
// To turn it off, you need to edit the registry.
// WARNING: Don't edit the registry unless you know what you are doing.
// You could damage your operating system.
//
// [a] Go to key:
// HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
//
// [b] Create a dword value named MaximumTunnelEntries and set it to zero.
//
// [c] Reboot.
//
// Remember to put everything back the way it was when you're done.
//
// - - Did it work? Rerun the experiment above and note that the file
// creation times are now different.
// Now to continue with our experiment.
// What will happen if we call REWRITE without first deleting the file?
// Will it delete the existing file and create a new one?
// Or will it overwrite the existing file?
//
// 9. Wait a few seconds.
// 10. Without first explicitly deleting the file,
// call REWRITE with the same file name.
// 11. Determine the creation time of this new file. Call it C.
//
// 12. Compare B to C. If they are the different, then the file must've
// been deleted. If they are the same, then the file was overwritten.
//
// - - CONCLUSION: The file creation times are the same. Calling rewrite
// did not delete the existing file. Rather it was overwritten.
//
//==============================================================================
{ 1. select a file name }
const
gFileName : string = 'rewrite-test.txt';
procedure DeleteFileIfItExists;
begin
if FileExists ( gFileName ) then
if not SysUtils.DeleteFile ( gFileName ) then
raise exception . create ( 'Cannot delete existing file.' );
end; // DeleteFileIfItExists
procedure CreateTheFile;
var
aTextFile : textfile;
begin
assignfile ( aTextFile, gFileName );
rewrite ( aTextFile );
try
// To make the experiment more realistic, write something to the file.
writeln ( aTextFile, 'Current time is: ', DateTimeToStr ( Now ) );
finally
closefile ( aTextFile );
end;
end; // CreateTheFile
function DetermineFileCreationDate : tDateTime;
var
aFileHandle : tHandle;
aCreationTime : tFileTime;
aSystemTime : tSystemTime;
begin
aFileHandle := CreateFile ( pchar(gFileName),
GENERIC_READ,
FILE_SHARE_READ,
nil,
OPEN_EXISTING,
0,
0 );
if aFileHandle = INVALID_HANDLE_VALUE then
raise exception . create ( 'Cannot open file' );
try
GetFileTime ( aFileHandle,
@ aCreationTime,
nil,
nil );
finally
CloseHandle ( aFileHandle );
end;
if not FileTimeToSystemTime ( aCreationTime, aSystemTime ) then
raise exception . create ( 'Cannot convert file time' );
Result := SysUtils . SystemTimeToDateTime ( aSystemTime );
end; // DetermineFileCreationDate
procedure WaitAFewSeconds;
begin
sleep ( 5000 ); // 5 seconds should be enough
end;
procedure RunExperiment;
var
A : tDateTime;
B : tDateTime;
C : tDateTime;
begin
{ 2.} DeleteFileIfItExists;
{ 3.} CreateTheFile;
{ 4.} A := DetermineFileCreationDate;
{ 5.} WaitAFewSeconds;
{ 6.} DeleteFileIfItExists;
{ 7.} CreateTheFile;
{ 8.} B := DetermineFileCreationDate;
if A = B then
raise exception . create ( 'The control file times are the same.'
+ #13'Turn off file tunneling.'
+ #13'See notes and warnings.' );
{ 9.} WaitAFewSeconds;
{10.} CreateTheFile;
{11.} C := DetermineFileCreationDate;
writeln ( 'The original creation time was ', DateTimeToStr ( B ) );
writeln ( 'The new creation time is ', DateTimeToStr ( C ) );
if B = C then
begin
// This is the one
writeln ( 'The file creation times are not the same.' );
writeln ( 'REWRITE overwrites the existing file.' );
end
else
begin
// This is not run
writeln ( 'The file creation times are the same.' );
writeln ( 'REWRITE deletes and recreates the file.' );
end;
end; // RunExperiment
begin
try
writeln ( 'The test will take about 10 seconds. Please wait.' );
RunExperiment;
// Give user a chance to see the answer
writeln ( 'Press Enter to continue' );
readln;
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
答案 2 :(得分:0)
最糟糕的情况我在使用重置和重写时注意到了:
try
ShowMessage('1');
Reset(MyFile);
ShowMessage('2');
except
ShowMessage('3');
Reset(MyFile);
ShowMessage('4');
end;
我从未想过的输出是可能的:1 3 4
是的,是的,你正确阅读,这不是一个错误:第一次调用失败(尝试部分中的那个)和第二个调用(除了部分之外的那个)。
请注意:Rewrite也是如此。
这并非总是发生,但如果你只让一次重置或重写,当发生这种情况时,你会得到一个I / O错误103.
我曾经看过,如果我重新尝试重置/重写...除了...如果第一个失败则结束第二个不会失败。
当然,考虑到我所说的一个单一呼叫不能失败的情况。
仅在Windows 7和8 / 8.1上发生这种情况(或者至少是我所看到的)...我从未在WindowsXP上看到它们失败。
你被告知......我觉得这很奇怪!现在我将所有调用替换为Reset / Rewrite,以包含这样的双重调用(如果第一次调用失败,则重新尝试第二次)。
这样的伎俩有效!至少对于我来说!这样的第二次通话永远不会失败。
重要提示:我说的是第一次电话不能失败的情况......我不会考虑任何其他情况。
以另一种方式说:
在线性控制台代码上测试...运行乘以相同代码(相同的EXE),得到不同的结果。
正如我所说的那样有点奇怪...解决方案正如我所说:重做重置/重写尝试除了结束。
用人的话说:
当然,如果没有任何已知的理由让第一个失败,除了O.S.小故障!!!我不能用另一种形式来称呼它!