Delphi: 文件访问和兼容性文件 (Windows 7)

4
假设我的应用程序名为mysoft,我想要读取的文件是afile.binmysoft位于程序文件夹中。同时假设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. 除了将文件移动到另一个文件夹外,如何防止这种情况发生?
再次强调,我只是读取数据文件,不理解。
3个回答

5
调用Reset会导致文件打开以进行写入。这是因为System.FileMode的默认值是fmOpenReadWrite。由于您的应用程序在虚拟化运行,并且您的用户令牌没有管理员权限,因此虚拟化层会启动并在虚拟存储中创建文件的副本。
使用传统的Pascal I/O可用的解决方案是将FileMode设置为fmOpenRead。然后Reset将打开该文件以进行读取,虚拟化层将不会被调用。
请记住,FileMode是一个全局变量,影响所有传统的Pascal I/O。如果您有线程或忘记在需要写入文件时将FileMode设置回fmOpenReadWrite,那么您会很糟糕。进程范围全局标志来控制文件访问模式!这很令人反感吧?这些东西是在应用程序拥有线程之前发明的。在面向对象编程(OOP)发明之前很久。所以我能理解为什么会这样。
从中可以得出的教训是,现在是时候切换到现代形式的文件访问了。例如TFileStream
确实,现在是你禁用应用程序中的虚拟化的时间了。虚拟化是在将近6年前的Vista中引入的。它旨在帮助还没有为Vista重新编译的旧程序。您的应用程序不应仍在使用它。

1
我最终将代码转换为使用tfilestream,并且问题已经解决。谢谢。 - Jim S
1
不要忘记为您的应用程序禁用虚拟化。 - David Heffernan
大卫,你能详细说明如何禁用虚拟化吗?是在编译器的某个开关上吗? - Chris Thornton
1
@Chris 在应用清单中指定 requestedExecutionLevel。 - David Heffernan

2
如果您有支持TStreamReader类的Delphi版本,并且您的文件是文本文件,则可以使用以下代码:
```delphi var sr: TStreamReader; begin sr := TStreamReader.Create('yourfile.txt'); try // Do something with the contents of the file finally sr.Free; end; end; ```
该代码将创建一个TStreamReader对象,用于读取指定的文本文件。在try块中,您可以处理文件内容。最后,在finally块中,释放TStreamReader对象以避免内存泄漏。
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;

0

我认为这是因为Windows 7的"新功能",它禁止您直接访问文件系统区域(%programfiles%,%systemroot%,%systemdrive或%programdata%)。

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

希望它能正常工作。我没有7去尝试它 :)


1
标准用户在XP中也无法访问这些区域。UAC和虚拟化是Vista而不是7中引入的。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接