Конструктор на основе имени файла
TFileStream
использует вызов API WIndows CreateFile для создания дескриптора файла, который будет использоваться для доступа к файлу. Сам API имеет несколько параметров, и особенно интересным для вас является Создать расположение : если вы укажете CREATE_NEW
, функция завершится ошибкой, если файл уже существует. Вы можете воспользоваться этим, вызвав CreateFile
самостоятельно, а затем используя возвращенный дескриптор для создания TFileStream
. Вы можете сделать это, потому что TFileStream
наследует от THandleStream
, наследует свой конструктор на основе дескриптора и владеет дескриптором (вызывает CloseHandle
на дескрипторе, который вы передаете конструктору).
Поскольку это зависит от предоставляемой ОС функции CreateFile
, она будет безопасна с точки зрения безопасности (без условия гонки между 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);