until now, whenever I wanted to create a file without overwriting an existing one, I've done something like this:
if not FileExists(filename) then
stream := TFileStream.Create(filename, fmCreate);
But that's not threadsafe. So now I am looking for a threadsafe version.
Perhaps I can combine some modes so that TFileStream.Create(filename, fmCreate +fm???);
fails if the file exists?
I need this to communicate directory-locks with old DOS programs. But the DOS programs don't hold the files opened. :-(
TFileStream
's file-name based constructor relies on the WIndows API call CreateFile to create the file handle that'll be used to access the file. The API itself has multiple parameters, and especially interesting for you is the Create Disposition: if you specify CREATE_NEW
, the function fails if the file already exists. You can take advantage of that by calling CreateFile
yourself, then using the returned handle to create the TFileStream
. You can do that because TFileStream
inherits from THandleStream
, inherits it's handle-based constructor and owns the handle (calls CloseHandle
on the handle you pass to the constructor).
Since this relies on the OS-provided function CreateFile
, it'll be trehad-safe (no race condition between FileExists()
and actually creating the file. It also blocks the old application from accessing the newly crearted file until you actually close the handle.
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With