Pracuję nad kawałkiem kodu, który sprawdza czy na liście znajduje się zadana ścieżka do pliku dyskowego; Metoda pobiera na wejściu dowolną ścieżkę, względną lub bezwzględną i ma ją porównać z listą ścieżek, względnych lub bezwzględnych; Całość musi opierać się o UTF-8 (to konieczne) oraz musi być niezależna od platformy;
I teraz tak - każdą ścieżkę przed porównaniem przepuszczam przez metodę ExpandFileNameUTF8, aby przerobić je na ścieżki absolutne, bo tylko wtedy jest sens je porównywać;
Jak teraz porównać te dwie ścieżki?
Mogę użyć funkcji SameFileName, jednak używa ona funkcji AnsiCompareFileName i za bardzo nie nadaje się do UTF-8; Z kolei ona sprawdza stan stałej FileNameCaseSensitive i na jej podstawie wywołuje albo funkcję AnsiCompareStr, albo AnsiCompareText; Kod wyglądałby tak:
if SameFileName(strFullInputFileName, strFullLinkedFileName) then
Exit(False);
Kolejna rzecz to istnienie specjalnych funkcji porównujących łańcuchy kodowane w UTF-8 - UTF8CompareStr i UTF8CompareText; Skoro one przeznaczone są dla wymaganego kodowania to można by ich użyć w tym przypadku;
Mogę posłużyć się wymienioną stałą i na jej podstawie wywołać jedną z dwóch metod porównujących:
if FileNameCaseSensitive then
Result := UTF8CompareStr(strFullInputFileName, strFullLinkedFileName) = 0
else
Result := UTF8CompareText(strFullInputFileName, strFullLinkedFileName) = 0;
if Result then
Exit(False);
a mogę też skorzystać z dyrektyw kompilatora i wkompilować jedynie wymaganą funkcję, np.:
{$IFDEF WINDOWS}
if UTF8CompareText(strFullInputFileName, strFullLinkedFileName) = 0 then
Exit(False);
{$ELSE}
if UTF8CompareStr(strFullInputFileName, strFullLinkedFileName) = 0 then
Exit(False);
{$ENDIF}
albo coś na ten kształt; Tyle że to ostatnie rozwiązanie ma ograniczenia - jakoś ten hardkodowany WINDOWS
nie wygląda dobrze, a i nie wiem czy jest jeszcze jakiś system, który tak samo jak Windows nie dba o wielkość znaków;
W jaki sposób poprawnie porównywać relatywne i absolutne ścieżki, aby porównanie współgrało z UTF-8 oraz było niezależne od systemu operacyjnego? Będę wdzięczny za jakieś porady;
W razie czego obecny kod metody wygląda tak:
function TTSInfoLinkedTreesList.LinkedFileNotYetBeenProcessed(const AFileName: UTF8String): Boolean;
var
pliLink: PListItem;
strFullInputFileName, strFullLinkedFileName: UTF8String;
begin
if FCount > 0 then
begin
strFullInputFileName := ExpandFileNameUTF8(AFileName);
pliLink := FFirstItem;
while pliLink <> nil do
begin
strFullLinkedFileName := ExpandFileNameUTF8((pliLink^.Element as TTSInfoLink).FileName);
if SameFileName(strFullInputFileName, strFullLinkedFileName) then
Exit(False)
else
pliLink := pliLink^.NextItem;
end;
end;
Result := True;
end;
PS: Jest jeszcze funkcja ExpandFileNameCase w razie czego...
PPS: Funckja SameFileName
w rezultacie korzysta z metody z menedżera stringów, więc może i nada się..?