Poprawność nazwy pliku

0

Jak sprawdzić czy plik o podanej nazwie MOŻE (podkreślam) zostać utworzony.

Tworzenie pliku: np. Windows.CreateFile

Przykład:
Gdy jako nazwę pliku podamy "NAZWA: PLIKU.txt" gdzie w nazwie jest dwukropek (lub inny wadliwy znak) plik zostanie utworzony ale nie o podanej nazwie tylko o nazwie "NAZWA" i do tego bez rozszerzenia.

Jak można sprawdzić czy nazwa pliku jest poprawna (i taki plik zostanie utworzony w niezmienionej formie) ZANIM utworzymy plik (wywołamy funkcję CreateFile lub inną) :?:

0

czytasz folder i sprawdzasz czy istnieje, czytasz nazwe pliku i sprawdzasz czy jest taka jak powinna byc; jak jedno i drugie zwraca true to mozna zapisac

0
wotek napisał(a)

czytasz folder i sprawdzasz czy istnieje, czytasz nazwe pliku i sprawdzasz czy jest taka jak powinna byc; jak jedno i drugie zwraca true to mozna zapisac

Ale plik nie istnieje, ma dopiero być utworzony nowy plik! Ale jak ma zostać utworzony o innej nazwie niż podaję to żeby go nie tworzył

0
prgtw napisał(a)

Ale plik nie istnieje, ma dopiero być utworzony nowy plik! Ale jak ma zostać utworzony o innej nazwie niż podaję to żeby go nie tworzył

extrectfilepath, directoryexists <-- folder juz masz; sprawdzasz funkcja pos nazwe pliku wyciagnieta funkcja extrectfilename czy nie zawiera niedozwolonych znakow; mozesz dodatkowo sprawdzic czy starczy miejsca na hdd ;P
btw: to do newbie sie nadaje raczej :-/

0
wotek napisał(a)

sprawdzasz funkcja pos nazwe pliku wyciagnieta funkcja extrectfilename czy nie zawiera niedozwolonych znakow

Już sam na to wpadłem i zrobiłem, ale niepodoba mi się takie rozwiązanie, bo oprócz znaków typu /\ : * | < > w nazwie pliku nie może być znaku $0A a ten nie ma odpowiednika WYSIWYG bo ten znak to coś w styu entera

CRLF = #13#10 ($0D, $0A)

wotek napisał(a)

btw: to do newbie sie nadaje raczej :-/

W Delphi siedzę już ponad 7 lat ale jak widać są czasami pytania, które wydają się łatwe.

BTW: Na MSDN widziałem że W .NET jest klasa TPath i ona zawiera niedozwolone znaki jakie nie mogą się znaleźć w ścieżce ale nie wiem jak je zdobyć, a nie chce mi się instalować Delphi 2005 :/

0

A może spróbuj utworzyć plik o testowanej nazwie? Jeśli funkcja zwróci błąd - to mamy jakiś problem :)

0
function DelChar(s: String): String;
var i: Byte;
begin
  if Length(s) > 225 then s := Copy(s, 1, 225);
  Result := '';
  for i := 1 to Length(s) do
    if not (s[i] in [#9, '/', '\', '?', '|', '.', '"', '*', ':', '<', '>', ',']) then
      Result := Result + s[i];
end;

Ja rozwiązałem kiedyś to sobie tak, ale pomysł Brodnego wydaje się lepszy. :)

0
brodny napisał(a)

A może spróbuj utworzyć plik o testowanej nazwie? Jeśli funkcja zwróci błąd - to mamy jakiś problem

W tym problem że niskopoziomowa funkcja API o nazwie CreateFile jak podam jej plik o nazwie "abc : abc.txt" NIE ZWRACA BŁĘDU, tylko tworzy plik o nazwie "abc" bez rozszerzenia. GetLastError nie zwraca INVALID_HANDLE_VALUE bo plik został utworzony.

drumers napisał(a)
function DelChar(s: String): String;
var i: Byte;
begin
  if Length(s) > 225 then s := Copy(s, 1, 225);
  Result := '';
  for i := 1 to Length(s) do
    if not (s[i] in [#9, '/', '\', '?', '|', '.', '"', '*', ':', '<', '>', ',']) then
      Result := Result + s[i];
end;

Ja rozwiązałem kiedyś to sobie tak, ale pomysł Brodnego wydaje się lepszy. :)

Pomysł Brodnego niestety ale nie jest lepszy - sprawdzałem na różne sposoby :)

Twóje rozwiązanie to także moje rozwiązanie ;) Mam taką samą funkcję tylko w troszkę innej postaci :)

Ale kilka zastrzeżeń do tej funckcji
Kropka, przecinek w nazwie może wystąpić :/
' " ' - co to jest :/ zamień to na ' " ' bez ""
A o #9 nie miałem pojęcia ale dorzucę ten znaczek do niedozwolonych
Aha i te 225 :/ chyba 255 ale to by się zastąpiło stałą MAX_PATH

Chcę zrobić test przed zapisem bo jak podam nazwę pliku "abc : abc.txt" to tworzy plik "abc" ALE jak plik "abc" istnieje to zostanie nadpisany A TEGO NIE CHCĘ bo to błąd w programie.
BTW: Kurde, programista musi chyba wszystko przewidzieć ;)

0

Nie pamiętam, dlaczego znalazł się tam przecinek. Być może w Win 98 nie można było używać, ale nie wiem. Jakoś tam się znalazł, może niepotrzebnie.

0

Nie, w 98 może być przecinek (sprawdzałem przed chwilą). Tak przy okazji: w helpie do Win32 SDK jest pozycja Alphabetical List of Error Codes. I tam jest takie cuś:

ERROR_INVALID_NAME

The file name, directory name, or volume label is syntactically incorrect.

Nie wiem z czym i jak, ale może się przydać :)

0
brodny napisał(a)

ERROR_INVALID_NAME

The file name, directory name, or volume label is syntactically incorrect.

Nie wiem z czym i jak, ale może się przydać :)

Dzięki, zaraz zobaczę czego to się tyczy. Może na MSDN będzie, pokombinuję i najwyżej napiszę w tym poście jakby sprawa dalej była otwarta.

Dopisane:
Póki co widzę że te numer błędu odnosi się tylko do usług w systemie NT i połączeń RAS (modemowych)

0

Błąd ERROR_INVALID_NAME (123) generowany jest też przy próbie kopiowania lub przenoszenia pliku wtedy. Metoda nie za profesjonalna, ale sprawdza się :P

Copyfile('C:\ktos.txt','C:\ktos2?.txt');
IF GetLastError() = ERROR_INVALID_NAME then ShowMessage('Zła nazwa pliku');
0
Cool_Programming napisał(a)

Błąd ERROR_INVALID_NAME (123) generowany jest też przy próbie kopiowania lub przenoszenia pliku wtedy. Metoda nie za profesjonalna, ale sprawdza się :P

Może i się sprawdza ale masz rację - całkowicie nieprofesjonalna. Problem że dane do zapisu w pliku mam w pamięci i nie będę ich zapisywał do pliku TEMP a potem sprawdzał czy uda się skopiować. Raz że nieporfesjonalne, dwa że niepotrzebnie traci się na szybkości zapisu do wybranej lokalizacji i fragmentacja dysku (ale to już tak na wesoło) ;).

Zostaję przy własnej procedurce, która wydaje mi się jednak najlepsza

CONST
CInvalidPathChars: ARRAY[1..9] OF Char = (
    #9, '\', '/', ':', '*', '"', '<', '>', '|');
//Projekt COYOTE zamienia podwójny cudzysłów (") na \+podwójny cudzysłów (\"), także zamienić \" na " - komentarz głównie dla moderatorów ażeby poprawili

FUNCTION ReplaceIllegalPathCharacters(VAR FString: STRING): Boolean;
VAR
  FI: Integer;
  FTempString: STRING;
BEGIN
  FTempString := FString;
  FOR FI := Low(CInvalidPathChars) TO High(CInvalidPathChars) DO
    FString := StringReplace(FString, CInvalidPathChars[FI], '', [rfReplaceAll]);
  Result := FTempString <> FString;
END;

Podana powyżej funckja usuwa z parametru FString niedozwolone znaki, które nie mogą pojawić się w nazwie pliku

Wynik funckji jest prawdą (True) gdy funkcja znalazła i usunęła jakieś niedozwolone znaki, lub fałszem (False) gdy podany tekst FString jest poprawny i nie zawiera niedozwolonych znaków

0

Nie ma to jak myślenie na około......
Dlaczego używacie spisu znaków, które nie mogą być skoro łatwiej jest zrobić zestaw znaków prawidłowych? To raz... a dwa - pamiętać należy, że plik może mieć nazwę w unicode - i co wtedy?

Więc jeśli nie olać unicode, to można wykorzystać wyrażonko regularne do sprawdzenia nazwy - coś w stylu <font color="blue">/[-a-zA-Z0-9`~!@#$%^&()_+={}[].;',]{1,244}/</span>
(244 - tyle max znaków udało mi się wcisnąć w nazwę total commanderem - windows przyjmuje 199 - programowo nie miałem czasu sprawdzać)
Jeśli nie możesz z jakiś przyczyn użyć RegExp, to w pętli sprawdź, czy jest znak spoza tej grupy i czy ma prawidłową długość nazwy.

// 255 znaków razem ze ścieżką, lub w unicode ~32768 (razem ze ścieżką) - ŁF
//też tak myślałem, ale jak widać tak nie jest - 244 + "c:" daje 247 więc gdzieś ucieka 8 znaków - M

//Projekt COYOTE zamienia podwójny cudzysłów (") na +podwójny cudzysłów ("), także zamienić " na " - komentarz głównie dla moderatorów ażeby poprawili
Wiemy o tym - planowane jest zastosowanie całkowicie innego systemu kolorowania składni oparte o zewnętrzną klasę. Sprawa czeka an chętnego z wolnym czasem (ja mam to w zamyśle poprawić, ale po sesji...) - a moderatorzy nie mają z tym nic wspólnego - raczej ludzie z grupy Coyote.<font color="Domyślny"></span>

[<font color="blue">dopisane</span>]
do postu poniżej: w czystym Delphi nie ma wyrażeń regularnych, ale ten niewybaczalny błąd naprawia doskonały darmowy komponent wspomniany przeze mnie na łamach 4p - również jeśli używasz platformy .NET to masz obsługę regexp (ale z 3 postu wynika, że nie działasz na .NET)

0
Marooned napisał(a)

Więc jeśli nie olać unicode, to można wykorzystać wyrażonko regularne do sprawdzenia nazwy - coś w stylu <font color="blue">/[-a-zA-Z0-9`~!@#$%^&()_+={}[].;',]{1,244}/</span>

To w Delphi jest RegExp, nawet nie wiedziałem, chyba że nie ma a Ty się pomyliłeś bo wyrażeń regularnych to ja tylko używam w PHP na mojej stronie WWW :] ale jak
są w Delphi (czystym, nie w dodatkowych komponentach) to nawet nie wiedziałem.

A tak poza tym "co to jest Unicode" - bo cały czas myślę że to uniwersalne kodowanie coś jak ISO-8859-2 itp?

Marooned napisał(a)

Sprawa czeka an chętnego z wolnym czasem (ja mam to w zamyśle poprawić, ale po sesji...) - a moderatorzy nie mają z tym nic wspólnego - raczej ludzie z grupy Coyote.<font color="Domyślny"></span>

No to czekamy czekamy, ja niestety nie pomogę (nawet nie wiem czy ktoś by chciał mojej pomocy, bo Wy i tak wiecie pewnie dużo więcej) bo mam obronę pracy dyplomowej, w wakacje chciałem zarobić a potem początek studiów informatycznych i 0 wolnego czasu. BTW: Powodzenia na sesji

A odnośnie tematu to ja jednak pozostanę przy mojej funkcji ;) Nie będę robił już sobie problemów z takiego błahego problemu ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1