如何创建线程文件而不覆盖现有文件?

Hei*_* Z. 4 delphi thread-safety

到现在为止,每当我想创建一个文件而不覆盖现有文件时,我就做了这样的事情:

if not FileExists(filename) then
  stream := TFileStream.Create(filename, fmCreate);
Run Code Online (Sandbox Code Playgroud)

但这不是线程安全的.所以现在我正在寻找一个线程安全版本.

也许我可以组合一些模式,以便TFileStream.Create(filename, fmCreate +fm???);在文件存在时失败?

我需要这个与旧DOS程序通信目录锁.但是DOS程序没有打开文件.:-(

Cos*_*und 7

TFileStream基于文件名的构造函数依赖于WIndows API调用CreateFile来创建将用于访问文件的文件句柄.API本身有多个参数,特别感兴趣的是Create Disposition:如果指定CREATE_NEW,如果文件已经存在,则函数失败.您可以通过调用CreateFile自己来利用它,然后使用返回的句柄来创建TFileStream.你可以这样做,因为TFileStream继承自THandleStream,继承它的基于句柄的构造函数并拥有句柄(调用CloseHandle你传递给构造函数的句柄).

由于这依赖于OS提供的功能CreateFile,因此它将是trehad-safe(FileExists()实际创建文件之间没有竞争条件.它还会阻止旧应用程序访问新创建的文件,直到您实际关闭句柄.

var FH: NativeUInt;

// ...

  FH := CreateFile('FileName', GENERIC_READ or GENERIC_WRITE, 0, nil, CREATE_NEW, 0, 0);
  if FH = INVALID_HANDLE_VALUE then
  begin
    // Creating the new file failed! I'm raizing an exception, but you can do something
    // better-suited for your case, like trying a new file name.
    RaiseLastOSError;
  end;
  // Create the stream using the prepared Handle
  HS := TFileStram.Create(FH);
Run Code Online (Sandbox Code Playgroud)