Как сохранить файл как «только для чтения» из Delphi? - PullRequest
1 голос
/ 03 февраля 2020

Я хотел бы сохранить файл как файл «только для чтения». Возможно ли это?

Ответы [ 2 ]

4 голосов
/ 03 февраля 2020

Это двухэтапный процесс, доступный только на платформе Windows.

  1. Сохранение файла.
  2. Добавление атрибута только для чтения к метаданным файла .

Предполагая, что вы уже знаете, как выполнить этап 1, давайте рассмотрим этап 2. Используя модуль System.IOUtils, вы установите этот атрибут следующим образом:

uses
  System.IOUtils;
....
var
  attributes: TFileAttributes;
....
attributes := TFile.GetAttributes(FileName);
Include(attributes, faReadOnly);
TFile.SetAttributes(FileName, attributes);

Если вы wi sh для удаления атрибута только для чтения, тогда вы используете точно такой же код, но замените Include на Exclude.

Для платформ, отличных от Windows, вы все равно можете использовать TFile.GetAttributes и TFile.SetAttributes, но доступные атрибуты очень разные, отражая различные модели файловых систем Windows и платформ POSIX.


К сожалению, RTL не может обеспечить какой-либо способ проверки ошибок в этом коде. Поэтому, если вы хотите проверить на наличие ошибок (вы должны это сделать), вам лучше всего напрямую вызвать функцию Windows API SetFileAttributes. Вы можете сделать это следующим образом:

function FileSetAttribute(const FileName: string; const Attr: DWORD; const Value: Boolean): Boolean;
var
  Flags, NewFlags: DWORD;
begin
  Flags := GetFileAttributes(PChar(FileName));
  if Flags=INVALID_FILE_ATTRIBUTES then begin
    Result := False;
  end else begin
    if Value then begin
      NewFlags := Flags or Attr
    end else begin
      NewFlags := Flags and not Attr;
    end;
    Result := (NewFlags=Flags) or SetFileAttributes(PChar(FileName), NewFlags);
  end;
end;

function FileSetReadOnly(const FileName: string; ReadOnly: Boolean): Boolean;
begin
  Result := FileSetAttribute(FileName, faReadOnly, ReadOnly);
end;

Как обсуждалось ранее, этот код предназначен только для Windows. Функция FileSetReadOnly возвращает логическое значение, указывающее, успешно ли оно выполнено. В случае сбоя вы можете позвонить GetLastError для получения расширенной информации об ошибке.

4 голосов
/ 03 февраля 2020

Сохранить как обычно, например через

VAR S : TFileStream;
.
S := TFileStream.Create(FileName,fmCreate);
<Write to stream>
S.Free;

Затем

USES SysUtils;

// Set R/O
IF FileSetAttr(FileName,FileGetAttr(FileName) or faReadOnly)<>NO_ERROR THEN
  RaiseLastOSError;

впоследствии, чтобы пометить его как «Только для чтения».

Если вы хотите обновить его позже, вам необходимо удалить сначала флаг Read / Only:

// Set R/W
IF FileSetAttr(FileName,FileGetAttr(FileName) AND NOT faReadOnly)<>NO_ERROR THEN
  RaiseLastOSError;

, затем обновите файл, затем снова пометьте его как Read / Only.

...