Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: AndreaM - Febbraio 15, 2017, 06:18:38 am

Titolo: funzione ExtractRelativePath
Inserito da: AndreaM - Febbraio 15, 2017, 06:18:38 am
Buongiorno a tutti,
Ho un applicazione che deve gestire alcuni file posizionati in cartelle che si trovano in determinate sottocartelle (rispetto all'eseguibile). Altri file invece si trovano in cartelle posizionate sopra al file eseguibile. Esempio
c:\aa\bb\cc<--cartella dove si trova l'eseguibile
c:\aa\bb\cc\ss1<-- sottocartella ss1
c:\aa\bb\xx <--cartella superiore all'eseguibile xx
La gestione dei file in tali cartelle può avvenire assegnando i percorsi assoluti (caso più semplice), oppure assegnando i percorsi relativi rispetto alla posizione dell'eseguibile. Questa seconda scelta è quella di mio interesse, pertanto nella selezione della cartella da memorizzare volevo usare la funzione ExtractRelativePath, ma il percorso che mi restituisce non sembra corretto!!
Se uso la funzione con la stessa cartella:
ExtractRelativePath('c:\aa\bb\cc','c:\aa\bb\cc')
Mi aspetterei che desse come risultato nulla. Visto che sia il percorso iniziale che quello di destinazione sono uguali!
Invece mi restituisce cc, che non posso passare alle funzioni tipo LoadFile(cc+'\'+nomefile) o SaveFile(cc+'\'+nomefile) che mi danno ovviamente errore!
Se uso la funzione con la sottocartella:
ExtractRelativePath('c:\aa\bb\cc','c:\aa\bb\cc\ss1')
Mi restituisce cc\ss1 che per lo stesso motivo non posso passare alle varie funzioni LoadFile e SaveFile
Grazie per la vostra attenzione
Andrea
Titolo: Re:funzione ExtractRelativePath
Inserito da: Stilgar - Febbraio 15, 2017, 10:46:44 am
Guarda se ti ritrovi con gli esempi.
http://www.freepascal.org/docs-html/rtl/sysutils/extractrelativepath.html
Titolo: Re:funzione ExtractRelativePath
Inserito da: AndreaM - Febbraio 15, 2017, 04:11:01 pm
Ho già visto la pagina Stilgar ;)
Ma non mi sembra molto esaustiva! ???
Titolo: Re:funzione ExtractRelativePath
Inserito da: Stilgar - Febbraio 15, 2017, 08:49:18 pm
Codice: [Seleziona]
function ExtractRelativepath (Const BaseName,DestName : PathStr): PathStr;

Var Source, Dest   : PathStr;
    Sc,Dc,I,J
{$ifndef SYSUTILSUNICODE}
    ,Len, NewLen
{$endif not SYSUTILSUNICODE}
                   : Longint;
    SD,DD          : Array[1..MaxDirs] of PathPChar;

Const OneLevelBack = '..'+DirectorySeparator;

begin
  If Uppercase(ExtractFileDrive(BaseName))<>Uppercase(ExtractFileDrive(DestName)) Then
    begin
    Result:=DestName;
    exit;
    end;
  Source:=ExcludeTrailingPathDelimiter(ExtractFilePath(BaseName));
  Dest:=ExcludeTrailingPathDelimiter(ExtractFilePath(DestName));
  SC:=GetDirs (Source,SD);
  DC:=GetDirs (Dest,DD);
  I:=1;
  While (I<=DC) and (I<=SC) do
    begin
    If StrIcomp(DD[i],SD[i])=0 then
      Inc(i)
    else
      Break;
    end;
  Result:='';
{$ifdef SYSUTILSUNICODE}
  For J:=I to SC do Result:=Result+OneLevelBack;
  For J:=I to DC do Result:=Result+DD[J]+DirectorySeparator;
{$else SYSUTILSUNICODE}
  { prevent conversion to DefaultSystemCodePage due to concatenation of
    constant string -- and optimise a little by reducing the numher of
    setlength cals }
  if SC>=I then
    begin
      Len:=Length(Result);
      SetLength(Result,Len+(SC-I+1)*Length(OneLevelBack));
      For J:=0 to SC-I do
        move(shortstring(OneLevelBack)[1],Result[Len+1+J*Length(OneLevelBack)],Length(OneLevelBack));
    end;

  if DC>=I then
    begin
      Len:=Length(Result);
      NewLen:=Len+(DC-I+1)*sizeof(ansichar);
      For J:=I to DC do
        Inc(NewLen,Length(DD[J]));
      SetLength(Result,NewLen);
      For J:=I to DC do
        begin
          NewLen:=Length(DD[J]);
          Move(DD[J][0],Result[Len+1],NewLen);
          inc(Len,NewLen);
          Result[Len+1]:=DirectorySeparator;
          Inc(Len);
        end;
    end;
{$endif SYSUTILSUNICODE}
  Result:=Result+ExtractFileName(DestName);
end;     


Forse ho trovato il modo di "imbrogliare" la funzione:
Codice: [Seleziona]
 Writeln(ExtractRelativepath(ExtractFilePath(ExpandFileName(Application.ExeName)), ExtractFilePath(ExpandFileName(Application.ExeName)) + '\ss1'));
Citazione
..\bin\\ss1

Effettivamente il comportamento non è esattamente quello che mi aspettavo leggendo la documentazione.