有没有办法验证文件名?

时间:2010-09-23 23:24:53

标签: delphi filenames

我认为这必须在RTL的某个地方,但我看了,我找不到它。

function IsValidFilename(filename: string): boolean;
//returns True if it would be possible to create or open a file with
//this name, without modifying the current directory structure

换句话说,它必须指向有效本地或网络驱动器上的现有文件夹,并且不包含任何无效字符。我们有类似的东西吗? (如果它检查当前用户的访问权限以确保您可以访问相关文件夹,则会获得奖励。)

10 个答案:

答案 0 :(得分:11)

所以,这个问题有点陈旧但是如果您正在寻找:使用XE和更新版本,您可以使用TPath中的System.IOUtils类。

Result := TPath.HasValidFileNameChars(AFileName, UseWildcards); 

答案 1 :(得分:10)

据我所知,没有RTL或Windows API函数来验证文件名,因此您必须在Windows File Naming Conventions之后编写自己的函数:

  

以下基本规则启用   应用程序来创建和处理   文件和目录的有效名称,   无论文件系统如何:

     
      
  • 使用句点将基本文件名与目录或文件名称中的扩展名分开。
  •   
  • 使用反斜杠()分隔路径的组件。反斜杠将文件名与路径中的文件名分开,并从路径中的另一个目录名中分隔一个目录名。您不能在名称中为实际文件或目录使用反斜杠,因为它是将名称分隔为组件的保留字符。
  •   
  • 根据需要使用反斜杠作为卷名的一部分,例如,“C:\ path \ file”中的“C:\”或“\ server \ share \ path \ file”中的“\ server \ share” “对于通用命名公约(UNC)的名称。有关UNC名称的更多信息,请参阅最大路径长度限制部分。
  •   
  • 不要假设区分大小写。例如,考虑名称OSCAR,Oscar和oscar是相同的,即使某些文件系统(例如符合POSIX的文件系统)可能认为它们不同。请注意,NTFS支持区分大小写的POSIX语义,但这不是默认行为。有关更多信息,请参阅CreateFile。
  •   
  • 卷标识符(驱动器号)同样不区分大小写。例如,“D:\”和“d:\”表示相同的卷。
  •   
  • 使用当前代码页中的任何字符作为名称,包括扩展字符集(128-255)中的Unicode字符和字符,但以下情况除外:

         
        
    • 以下保留字符:      
          
      • < (小于)
      •   
      • > (大于)
      •   
      • :(冒号)
      •   
      • “(双引号)
      •   
      • /(正斜线)
      •   
      • \(反斜杠)
      •   
      • | (竖杆或竖管)
      •   
      • ? (问号)
      •   
      • *(星号)
      •   
    •   
    • 整数值为零,有时也称为ASCII NUL字符。
    •   
    • 整数表示形式在1到31范围内的字符,但允许使用这些字符的备用流除外。有关文件流的更多信息,请参阅文件流。
    •   
    • 目标文件系统不允许的任何其他字符。
    •   
  •   
  • 使用句点作为路径中的目录组件来表示当前目录,例如“。\ temp.txt”。有关更多信息,请参阅路径。
  •   
  • 使用两个连续句点(..)作为路径中的目录组件来表示当前目录的父目录,例如“.. \ temp.txt”。有关更多信息,请参阅路径。
  •   
  • 请勿将以下保留的设备名称用作文件名:

         

    CON,PRN,AUX,NUL,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8和LPT9。同时避免使用这些名称后立即进行扩展;例如,不建议使用NUL.txt。有关更多信息,请参阅命名空间。

  •   
  • 不要使用空格或句点结束文件或目录名称。虽然底层文件系统可能支持此类名称,但Windows shell和用户界面却不支持。但是,可以将句点指定为名称的第一个字符。例如,“。temp”。
  •   

您可以查看此C ++文章Validating file names以获取验证Windows文件名的完整示例函数。

答案 2 :(得分:5)

这太粗糙了吗,梅森?

function CanCreateFile(const FileName: string): Boolean;
var
  H: THandle;
begin
  H := CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE, 0, nil,
       CREATE_NEW, FILE_ATTRIBUTE_TEMPORARY or FILE_FLAG_DELETE_ON_CLOSE, 0);

  Result := H <> INVALID_HANDLE_VALUE;

  DeleteFile(FileName);
end;

答案 3 :(得分:4)

我现在无法访问Delphi编译器,但您可以尝试

function IsValidFilename(const FileName: string): boolean;
begin
  result := DirectoryExists(ExtractFilePath(FileName)) and TPath.HasValidFileNameChars(ExtractFileName(FileName), false);
end;

答案 4 :(得分:3)

要查看它是否存在,请使用DirectoryExists()FileExists()。要查看是否可以创建/编辑文件,请将FileOpen()与ReadWrite一起使用,看看是否成功。

答案 5 :(得分:3)

尝试此代码(取自delphi faq

const
  { for short 8.3 file names }
  ShortForbiddenChars : set of Char = [';', '=', '+', '<', '>', '|',
                                       '"', '[', ']', '\', '/', ''''];
  { for long file names }
  LongForbiddenChars  : set of Char = ['<', '>', '|', '"', '\', '/', ':', '*', '?'];

function TestFilename(Filename: String; islong: Boolean) : Boolean;
var
  I: integer;
begin
  Result := Filename <> '';
  if islong then
  begin
    for I := 1 to Length(Filename) do
      Result := Result and not (Filename[I] in LongForbiddenChars);
  end
  else
  begin
    for I := 1 to Length(Filename) do
      Result := Result and not (Filename[I] in ShortForbiddenChars);
  end;
end;

答案 6 :(得分:2)

检查目录是否存在:

在SysUtils中,您有:DirectoryExists

检查文件名:

无效的文件名字符为:\ / : * ? " < > | 所以你可以像这样检查文件名:

for c in AFileName do
begin
  OK := NOT (C in ['\', '/', ':', '*', '?', '"', '<', '>', '|']);
  if not OK then Break;
end;

检查文件夹是否可写:

重复: How can I use Delphi to test if a Directory is writeable?

答案 7 :(得分:1)

您还可以使用SysUtils.CharInSet功能:

function isFileNameValid(fileNameToCheck : String) : Boolean;
var
  invalidChars : Boolean;
  ch : Char;
begin
  invalidChars := False;
  for ch in fileNameToCheck do begin
    invalidChars := SysUtils.CharInSet(ch, ['\', '/', ':', '*', '?', '"', '<', '>', '|']);
    if invalidChars then
      Break;
  end;
  Result := not invalidChars;
end;

答案 8 :(得分:0)

这是我的解决方法:

function ValidFileName(const FileName: String): Boolean;
const InvalidChar: array[0..8] of Char = ('\', '/', ':', '*', '?', '"', '<', '>', '|');
var I, J, L: Integer;
begin
 Result:= False;
 L:= Length(FileName);
 if (FileName = '') or (FileName[L] = '.') or (FileName[L] = ' ') then Exit;
 for I:= 1 to L do begin
  if (FileName[I] < ' ') then Exit;
  for J:= 0 to 8 do
   if FileName[I] = InvalidChar[J] then Exit;
 end;
 Result:= True;
end;

答案 9 :(得分:0)

这是我的版本:

function MExtractFileName(const Name: String): String;
var I: Integer;
begin
 I:= Length(Name);
 while (I > 0) and (Name[I] <> '.') do Dec(I);
 if I = 0 then Result:= Name else Result:= Copy(Name, 1, I-1);
end;

function MValidFileName(AFileName: String): Boolean;
const InvalidChar: array[0..8] of Char = ('\', '/', ':', '*', '?', '"', '<', '>', '|');
      InvalidWords: array[0..21] of String = ('CON', 'PRN', 'AUX', 'NUL', 'COM1',
       'COM2', 'COM3', 'COM4', 'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2',
       'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9');
var I, J, L: Integer;
begin
 Result:= False;
 L:= Length(AFileName);
 if (L = 0) or (L > 255) or (AFileName[L] = '.') or (AFileName[L] = ' ') then Exit;
 for I:= 1 to L do begin
  if (AFileName[I] < ' ') then Exit;
  for J:= 0 to 8 do
   if AFileName[I] = InvalidChar[J] then Exit;
 end;
 AFileName:= UpperCase(TrimRight(MExtractFileName(AFileName)));
 for I:= 0 to 21 do if AFileName = InvalidWords[I] then Exit;
 Result:= True;
end;