Heute habe ich keine Fragestellung, sondern das Ergebnis meiner heutigen Bastelei: In Dateinamen unerlaubte Zeichen durch ähnliche Unicode-Zeichen ersetzen. (Nachtrag: nur für den puren Dateinamen ohne Pfadangabe.)
Vielleicht hat jemand Verwendung dafür.
Die Absicht hinter meiner Function war nicht, eine Benutzereingabe für einen Dateinamen heimlich durch ähnliche Zeichen ersetzen, sondern eine frühere Titel-Eingabe, die noch nicht für einen Dateinamen gedacht war, nun als Dateinamen in einem SaveDialog vorzuschlagen.
Dazu wollte ich nicht einfach alle nicht erlaubten Zeichen radikal rauslöschen, sondern dem Benutzer eine erlaubte und lesbare Alternative für einen Dateinamen anbieten.
Code: Alles auswählen
function replaceReservedCharactersByUnicode(const aTextForFileName: UnicodeString; aMaxChar16Len: Integer=255): UnicodeString;
var i: SizeInt;
w, Replace: Word;
begin
Result:=Trim(aTextForFileName);
for i:=1 to Length(Result) do
begin
w:=Word(Result[i]);
if Hi(w)<>0 then Continue;
case AnsiChar(Lo(w)) of
#0..#31: Replace:=32; // see below: remove double spaces
'<': Replace:=$FE64;
'>': Replace:=$FE65;
':': Replace:=$02D0;
'"': Replace:=$201C; // or simply a single quote instead?
'/': Replace:=$2044;
'|': Replace:=$2F01;
'?': Replace:=$FE56;
'*': Replace:=$FE61;
'\': Replace:=$2216;
else Continue;
end;
Result[i]:=WideChar(Replace);
end;
Result:=UnicodeStringReplace(Result,' ',' ',[rfReplaceAll]); // remove double spaces
if (aMaxChar16Len>0) and (Length(Result)>aMaxChar16Len) then
begin
w:=Word(Result[aMaxChar16Len]);
if (w>=$D800) and (w<=$DBFF) // a high surrogate starting a 32 bit codepoint
then SetLength(Result,aMaxChar16Len-1)
else SetLength(Result,aMaxChar16Len);
Result:=TrimRight(Result);
end;
end;
Meine Default-Begrenzung auf 255 Zeichen entspricht dem Maximum unter Windows, wo bis zu 255 UTF-16-Zeichen erlaubt sind.
Man findet zu Windows auch die Angaben max. 260 oder 256 Zeichen, wenn jedoch lange Pfade verwendet werden, sollen effektiv doch nur 255 UTF-16-Zeichen möglich sein. Das reicht ja auch.
In der Realität wird es dem Benutzer besser gefallen, wenn man ihm maximal 30 oder 40 Zeichen als Vorschlag anbietet.
Wer die Function mal testen möchte, kann es mit zwei Edit-Feldern ausprobieren:
Code: Alles auswählen
procedure TForm1.Edit1Change(Sender: TObject);
begin
Edit2.Text := Utf8Encode( replaceReservedCharactersByUnicode(Edit1.Text, 20) );
end;