假设我的应用名为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
的副本。
我的问题是:
我再次只阅读数据文件,我不明白。
答案 0 :(得分:5)
对Reset
的调用导致文件被打开以进行写入。那是因为System.FileMode
的默认值是fmOpenReadWrite
。由于您的应用程序是虚拟化的,并且由于您的用户令牌没有管理员权限,因此虚拟化层会启动并在虚拟商店中创建该文件的副本。
使用旧版Pascal I / O提供的解决方案是将FileMode
设置为fmOpenRead
。然后Reset
将打开文件进行读取,并且不会调用虚拟化层。
请记住,FileMode
是一个影响所有传统Pascal I / O的全局变量。如果你有线程,或者忘记在需要写文件时忘记将FileMode
设置回fmOpenReadWrite
,那么你会感到很遗憾。反叛不是吗?处理广泛的全局标志以控制文件访问模式!好吧,这些东西是在应用程序有线程之前发明的。早在OOP发明之前。所以我可以理解为什么会这样。
要从中汲取的教训是,现在是时候切换到一种现代形式的文件访问。例如,TFileStream
。
确实,您也应该在应用程序中禁用虚拟化。近6年前,Vista中引入了虚拟化。这对于尚未针对Vista进行重新编译的旧程序来说是一种帮助。您的应用程序不应该仍在使用它。
答案 1 :(得分:2)
如果您的Delphi版本支持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;
答案 2 :(得分:0)
我认为这是因为Windows 7“新功能”,它禁止您直接访问文件系统区域中的文件(%programfiles%,%systemroot%,%systemdrive%,或%programdata%)。
尝试使用TFileStream
将代码更改为打开文件,并将模式设置为fmOpenRead
。
我希望它有效。 我没有7尝试:)