[英]delphi- what does rewrite file actually do?
Does Rewrite
clear file contents of existing file or does it delete it and create a new one? Rewrite
清除现有文件的文件内容还是将其删除并创建一个新文件? I have a text file in my app.exe folder which I need to clear. 我的app.exe文件夹中有一个文本文件,需要清除。 Any example? 有什么例子吗?
From the Delphi XE2 documentation, topic Rewrite - read the last quoted paragraph: 在Delphi XE2文档中,主题为“ 重写 -阅读最后引用的段落”:
Creates a new file and opens it. 创建一个新文件并打开它。
In Delphi code, Rewrite creates a new external file with the name assigned to F. 在Delphi代码中,Rewrite创建一个新的外部文件,并将其名称分配给F。
F is a variable of any file type associated with an external file using AssignFile. F是使用AssignFile与外部文件关联的任何文件类型的变量。 RecSize is an optional expression that can be specified only if F is an untyped file. RecSize是一个可选表达式,仅当F为无类型文件时才可以指定。 If F is an untyped file, RecSize specifies the record size to be used in data transfers. 如果F是一个无类型的文件,则RecSize指定要在数据传输中使用的记录大小。 If RecSize is omitted, a default record size of 128 bytes is assumed. 如果省略RecSize,则假定默认记录大小为128字节。
If an external file with the same name already exists, it is deleted and a new empty file is created in its place. 如果已经存在相同名称的外部文件,则将其删除并在其位置创建一个新的空文件。
From the same documentation, link at the bottom of page for System.Rewrite
, modified to use your app's folder: 从同一文档中,页面底部的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;
You should know, though, that Rewrite
is outdated and doesn't support Unicode. 但是,您应该知道Rewrite
已经过时并且不支持Unicode。 You should be using more modern methods to read and write files like TFileStream or TStringWriter (or even the simple solution of TStringList ). 您应该使用更现代的方法来读写文件,例如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;
Note that you cannot use TStrings
; 注意您不能使用TStrings
; it's an abstract class. 这是一个抽象类。 You need to use one of it's descendants instead ( TStringList
is the one used most often). 您需要使用它的后代之一( TStringList
是最常用的后代)。
I did an experiment and determined that REWRITE overwrites an existing file. 我做了一个实验,确定REWRITE会覆盖现有文件。 It does not delete and then recreate the file. 它不会删除,然后重新创建文件。 You'll have to learn a little about file tunneling, something I knew nothing about when I began. 您将必须学习一些有关文件隧道的知识,而我刚开始时对此一无所知。
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.
Worst case i have noticed when working with Reset and Rewrite: 使用复位和重写时,我注意到最坏的情况:
try
ShowMessage('1');
Reset(MyFile);
ShowMessage('2');
except
ShowMessage('3');
Reset(MyFile);
ShowMessage('4');
end;
Output that i had never ever think it could be possible: 1 3 4 我从未想过的输出:1 3 4
Yes, yes, you are reading correctly, it is not a mistake: first call fails (the one in try part) and second one works (the one on except part). 是的,是的,您正在正确阅读,这不是一个错误:第一次调用失败(尝试部分中的一个),第二个调用成功(除去部分中的一个)。
Please note: Also happens the same with Rewrite. 请注意:重写也会发生同样的情况。
That not allways happen, but if you let only one Reset or Rewrite, when taht would happen you will get an I/O error 103. 并非总会发生这种情况,但是如果只允许进行一次“重置”或“重写”,那么在发生这种情况时,您将收到I / O错误103。
I had seen that if i re-do the Reset / Rewrite on a try...except...end if the first one fails the second one does not fail. 我已经看到,如果我尝试执行重设/重写操作...例外...结束,如果第一个失败,第二个也不会失败。
Of course, considering the fact that i am talking of cases where one single call must not fail. 当然,考虑到我所说的事实,即一个电话一定不会失败。
This happens (or at least is what i have seen) only on Windows 7 and 8/8.1 ... i had never see them to fail on WindowsXP. 仅在Windows 7和8 / 8.1上才发生(或至少是我所看到的)……我从未见过它们在WindowsXP上失败。
You're advised... i think it is weird! 建议您...我认为这很奇怪! Now i am replacing all calls to Reset / Rewrite so to include such double call (if first call fail re-try a second time). 现在,我将替换所有对“重置/重写”的调用,以便包括这样的双重调用(如果第一次调用失败,请再次尝试第二次)。
And such trick works! 这样的技巧行得通! At least for me! 至少对我来说! Such second call has never fail. 这样的第二次呼叫从未失败。
IMPORTANT: I am talking about cases where that first call must not fail... i am not considering any other cases. 重要提示:我说的是第一次通话一定不会失败的情况……我没有考虑其他任何情况。
Said in another way: 用另一种方式说:
Tested on linear console code... run multiply times same code (same EXE), got different results. 在线性控制台代码上进行了测试...将相同代码(相同EXE)相乘多次,得到不同的结果。
As i said it is kind weird... solution is as i said: Redo Reset / Rewrite on a try except end. 正如我说的那样,这很奇怪...解决方案就像我说的那样:重试重置/重写,但尝试结束。
Said in human words: 用人类的话说:
That of course if there is no known reason for first one to fail, except OS glitch !!! 当然,如果没有已知的原因导致第一个失败,除了操作系统故障之外!!! I can not call it in another form! 我不能用其他形式称呼它!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.