如何从缓存中卸载文件?

时间:2009-06-11 21:50:25

标签: delphi

有人知道如何从缓存中卸载文件吗? 我写了一个文件到磁盘,然后我想读回来。但是,Windows正在从缓存中提供该文件。

begin
...

 {-- Write file --}
 AssignFile(F, FileName);
 Rewrite(F, 1);
 BlockWrite(F, Buf[0], Chunk);
 CloseFile(F);             { FLUSH }

some code...
then.....

 {-- Read file --}
 AssignFile(F, FileName);
 Reset(F, 1);                                                              
 BlockRead(F, Buf[0], Chunk);       <----------- getting file from cache
 CloseFile(F);
end;

- 我正在尝试确定驱动器的写入/读取速度。

5 个答案:

答案 0 :(得分:4)

我认为你误解了刷新文件的概念。

刷新文件不会将其从磁盘缓存中删除,而是会将文件流缓冲区的内容写入文件。

(当你关闭它时,流会自动刷新。打开一个文件并在不写任何内容的情况下将其刷新它对以前没有任何影响。)

您可以查看FILE_FLAG_NO_BUFFERING标志来读取文件,但从文档中可以看出它对硬盘驱动器上的文件没有影响。

MSDN: CreateFile

答案 1 :(得分:4)

您需要直接使用Win32 API,特别是使用FILE_FLAG_NO_BUFFERING标志的CreateFile。它强制操作系统从磁盘而不是缓存中读取,并且副作用是它还清除了该文件的缓存,因此没有该标志的下一次读取也会触及磁盘,尽管它会将其读入缓存然后

答案 2 :(得分:4)

一些代码用于演示FILE_FLAG_NO_BUFFERING的使用并测试它如何影响您的阅读时间:

uses
  MMSystem;

function GetTimeForRead(ABuffered: boolean): single;
const
  FileToRead = // name of file with maybe 500 MByte size
var
  FlagsAndAttributes: DWORD;
  FileHandle: THandle;
  SrcStream, DestStream: TStream;
  Ticks: DWord;
begin
  if ABuffered then
    FlagsAndAttributes := FILE_ATTRIBUTE_NORMAL
  else
    FlagsAndAttributes := FILE_FLAG_NO_BUFFERING;
  FileHandle := CreateFile(FileToRead, GENERIC_READ, FILE_SHARE_READ, nil,
    OPEN_EXISTING, FlagsAndAttributes, 0);
  if FileHandle = INVALID_HANDLE_VALUE then begin
    Result := 0.0;
    exit;
  end;

  SrcStream := THandleStream.Create(FileHandle);
  try
    DestStream := TMemoryStream.Create;
    try
      DestStream.Size := SrcStream.Size;

      Sleep(0);
      Ticks := timeGetTime;
      DestStream.CopyFrom(SrcStream, SrcStream.Size);
      Result := 0.001 * (timeGetTime - Ticks);

    finally
      DestStream.Free;
    end;
  finally
    SrcStream.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: integer;
begin
  Button1.Enabled := FALSE;
  try
    Update;
    Memo1.Lines.Clear;
    for i := 1 to 5 do begin
      Memo1.Lines.Add(Format('Time for buffered file read: %.3f s',
        [GetTimeForRead(TRUE)]));
    end;
    for i := 1 to 5 do begin
      Memo1.Lines.Add(Format('Time for unbuffered file read: %.3f s',
        [GetTimeForRead(FALSE)]));
    end;
  finally
    Button1.Enabled := TRUE;
  end;
end;

在我的系统上运行带有420 MB大小文件的代码:

  

缓冲文件读取时间:3,974 s
  缓冲文件读取时间:0,922 s
  缓冲文件读取时间:0,937 s
  缓冲文件读取时间:0,937 s
  缓冲文件读取时间:0,938 s
  无缓冲文件读取时间:3,922 s
  无缓冲文件读取时间:4,000 s
  无缓冲文件读取时间:4,016 s
  无缓冲文件读取时间:4,062 s
  无缓冲文件读取时间:3,985 s

答案 3 :(得分:2)

文件缓存是一种操作系统级别的操作,因此与您使用Delphi还是其他任何语言无关。

如果您想知道为什么,您希望确保不是从缓存中读取,那么可能更容易提供帮助。

答案 4 :(得分:0)

代码应该没问题,除非您对Chunk变量使用无效值。例如,如果chunk = 0则它不会将任何数据读入缓冲区,因此缓冲区将保持其旧值。 (这可能与您刚写入磁盘的数据相同。)