4

假设我的应用程序名为mysoft,我要读取的文件是afile.bin. mysoft位于程序文件夹中。我们还假设 mysoft 没有以管理员权限执行。

procedure TForm1.Button1Click(Sender: TObject);
var 
  afile: File of Byte;
begin
  AssignFile(Infile, 'C:\Program Files\mysoft\afile.bin');
  Reset(afile);
  CloseFile(afile);
end;

afile.bin上面的简单代码将在兼容性文件文件夹中创建一个副本。

我的问题是:

  1. 为什么 ?我只看了该死的文件,我不想修改它。
  2. 除了将文件移动到另一个文件夹中之外,如何防止这种情况发生?

同样,我只读取数据文件,我不明白。

4

3 回答 3

5

调用Reset导致文件被打开以进行写入。那是因为默认System.FileMode值为fmOpenReadWrite. 由于您的应用程序运行虚拟化,并且由于您的用户令牌没有管理员权限,因此虚拟化层启动并在虚拟存储中创建文件的副本。

使用传统 Pascal I/O 可用的解决方案是设置FileModefmOpenRead. 然后Reset将打开文件进行读取,并且不会调用虚拟化层。

请记住,这FileMode是一个影响所有旧版 Pascal I/O 的全局变量。如果您有线程,或者忘记设置FileModefmOpenReadWrite何时需要写入文件,那么您会遇到麻烦。是不是很反感?处理广泛的全局标志来控制文件访问模式!好吧,这些东西早在应用程序有线程之前就发明了。早在 OOP 被发明之前。所以我可以理解为什么会这样。

从中吸取的教训是,是时候切换到一种现代的文件访问形式了。例如,TFileStream

事实上,也是时候在应用程序中禁用虚拟化了。近 6 年前,Vista 中引入了虚拟化。它旨在帮助尚未为 Vista 重新编译的旧程序。您的应用程序不应仍在使用它。

于 2012-10-10T16:25:23.877 回答
2

如果您有支持 TStreamReader 类的 Delphi 版本并且您的文件是文本,则可以使用以下代码:

procedure TForm1.btn1Click(Sender: TObject);
var
  SR : TStreamReader;
  line : string;
begin
  SR := TStreamReader.Create('C:\Program Files\mysoft\afile.bin');
  try
  while not SR.EndOfStream do
  begin
    line := SR.ReadLine;
  end;
  finally
  SR.Free;
  end;
end;

如果不是,我建议一种适用于任何文件的更经典的方法:

procedure TForm1.btn2Click(Sender: TObject);
var
  FS : TFileStream;
  mem : array of byte;
begin
  FS := TFileStream.Create('C:\Program Files\mysoft\afile.bin',fmOpenRead or fmShareDenyNone);
  try
  SetLength(mem,FS.Size);
  FS.Read(mem[0],FS.Size);
  finally
  FS.Free;
  end;
end;
于 2012-10-10T16:31:11.787 回答
0

我相信这是因为 Windows 7 的“新功能”不允许您直接访问文件系统区域中的文件(%programfiles%、%systemroot%、%systemdrive% 或 %programdata%)。

尝试更改您的代码以使用打开文件TFileStream,并将模式设置为fmOpenRead

我希望它有效。我没有7个可以尝试:)

于 2012-10-10T16:29:02.550 回答