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