File 如何从Delphi将文件保存为“只读”?

File 如何从Delphi将文件保存为“只读”?,file,delphi,save,File,Delphi,Save,我想将文件另存为只读文件。有可能吗?将其保存为正常,例如。通过 VAR S : TFileStream; . S := TFileStream.Create(FileName,fmCreate); <Write to stream> S.Free; 然后 之后,将其标记为只读 如果以后要更新,需要先删除只读标志: // Set R/W IF FileSetAttr(FileName,FileGetAttr(FileName) AND NOT faReadOnly)<>N

我想将文件另存为只读文件。有可能吗?

将其保存为正常,例如。通过

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

之后,将其标记为只读

如果以后要更新,需要先删除只读标志:

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

然后更新文件,然后再次将其标记为只读。

将其另存为普通文件,f.ex。通过

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

之后,将其标记为只读

如果以后要更新,需要先删除只读标志:

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

然后更新文件,然后再次将其标记为只读。

这是一个两阶段的过程,仅在Windows平台上可用

保存文件。 将只读属性添加到文件的元数据中。 假设你已经知道如何做第1阶段,让我们考虑第2阶段。使用System.IOUtils单元可以如下设置此属性:

uses
  System.IOUtils;
....
var
  attributes: TFileAttributes;
....
attributes := TFile.GetAttributes(FileName);
Include(attributes, faReadOnly);
TFile.SetAttributes(FileName, attributes);
如果希望删除只读属性,则使用完全相同的代码,但将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获取扩展错误信息。

这是一个两阶段的过程,仅在Windows平台上可用

保存文件。 将只读属性添加到文件的元数据中。 假设你已经知道如何做第1阶段,让我们考虑第2阶段。使用System.IOUtils单元可以如下设置此属性:

uses
  System.IOUtils;
....
var
  attributes: TFileAttributes;
....
attributes := TFile.GetAttributes(FileName);
Include(attributes, faReadOnly);
TFile.SetAttributes(FileName, attributes);
如果希望删除只读属性,则使用完全相同的代码,但将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获取扩展错误信息。

仅适用于具有TPath的现代Delphis。对于支持所有Delphi版本的版本,请参阅我的答案。@HeartWare是的,我假设IOUtils会正确地包装所有版本并引发异常。到现在为止,我应该知道不要相信IOUtils做任何正确的事情!仅适用于拥有TPath的现代Delphis。对于支持所有Delphi版本的版本,请参阅我的答案。@HeartWare是的,我假设IOUtils会正确地包装所有版本并引发异常。到现在为止,我应该知道不要相信IOUtils做任何正确的事情!您应该在此代码中添加一些错误检查。这样做的能力是使用filesetr而不是IOUtils的一个优势。该死的家伙!事实上,如果API调用失败但没有设置最后一个错误,您甚至不能可靠地为FileSettR添加错误检查。如果我这样做的话,我会直接调用winapi函数。FileGetAttr和FileSetAttr都会失败是的,但是如果FileGetAttr失败,FileSetAttr在我所看到的所有情况下都会失败…这可能是真的,但我个人不希望再猜测API了。你应该在代码中添加一些错误检查。这样做的能力是使用filesetr而不是IOUtils的一个优势。该死的家伙!事实上,如果API调用失败但没有设置最后一个错误,您甚至不能可靠地为FileSettR添加错误检查。如果我这样做的话,我会直接调用winapi函数。FileGetAttr和FileSetAttr都会失败是的,但是如果FileGetAttr失败,FileSetAttr在我所看到的所有情况下都会失败……这可能是真的,但我个人不希望不得不猜测api