Newsgroup: it.comp.lang.delphi
Titolo: Attributi file, errore dovuto a cosa?

Ciao a tutti,
come da oggetto, ho quanto segue:
   Function GetAttrib (FileName: String): String;
     Var Attr: DWord;   Mask: String;
     Begin
       Attr := FileGetAttr (FileName);   Mask := '00000000';
         If Attr And faReadOnly > 0 Then Mask [2] := '1';
         If Attr And faHidden > 0 Then Mask [3] := '1';
         If Attr And faSysFile > 0 Then Mask [4] := '1';
         If Attr And faVolumeID > 0 Then Mask [5] := '1';
         If Attr And faDirectory > 0 Then Mask [6] := '1';
         If Attr And faArchive > 0 Then Mask [7] := '1';
         If Attr And faSymLink > 0 Then Mask [8] := '1';
       Result := Mask;
     End;
Questa funzione mi restituisce correttamente una stringa in cui mi evidenzia 
gli attributi attivi mediante una sequenza binaria ponendo a 1 in caso di 
attributo attivo su filename.
Fin qui niente di strano.
La funzione seguente invece:
   Procedure InitAttrib (FileName: String);
     Begin
       FileSetAttr (FileName, not faReadOnly);
       FileSetAttr (FileName, not faHidden);
       FileSetAttr (FileName, not faSysFile);
       FileSetAttr (FileName, not faVolumeID);
       FileSetAttr (FileName, not faDirectory);
       FileSetAttr (FileName, not faArchive);
       FileSetAttr (FileName, not faSymLink);
     End;
Ha lo scopo di inizializzare gli attributi del file in esame, e anche qui 
nessun problema.... mentre la funzione:
   Procedure SetAttrib (FileName: String; Mask: String);
     Begin
       InitAttrib (FileName);
         If (Mask [2] = '1') Then FileSetAttr (FileName, faReadOnly);
         If (Mask [3] = '1') Then FileSetAttr (FileName, faHidden);
         If (Mask [4] = '1') Then FileSetAttr (FileName, faSysFile);
         If (Mask [5] = '1') Then FileSetAttr (FileName, faVolumeID);
         If (Mask [6] = '1') Then FileSetAttr (FileName, faDirectory);
         If (Mask [7] = '1') Then FileSetAttr (FileName, faArchive);
         If (Mask [8] = '1') Then FileSetAttr (FileName, faSymLink);
     End;
DOVREBBE ripristinarmi gli attributi del file in base alla Mask ricevuta in 
origine. Questo non succede, l'unica cosa che viene svolta correttamente è 
la chiamata alla procedura initattrib.
Chi può spiegarmi per cortesia l'errore commesso e farmi comprendere il 
motivo per cui gli attributi non vengono impostati?
Premetto che:
 a) in tutte e tre le procedure/function FILENAME contiene il percorso 
completo del file,
 b) il file in esame esiste;
Grazie ancora,
Cooper.

 motivo per cui gli attributi non vengono impostati?
Perchè ogni volta che richiami la *SetFileAttr*, imposti sul file gli 
attributi specificati come parametro alla funzione, pertanto se 
specifichi solamente il flag "nascosto", l'unico flag che imposterai sul 
file sarà quello, nessun altro.
Devi richiamare la funzione *SetFileAttr* specificando i flag e 
ponendoli in *or* tra loro, oppure sommandoli con l'operatore "+", se 
preferisci.
Un esempio:
   FileSetAttr (FileName, faReadOnly or faHidden);
Ti era stato detto anche nella precedente discussione che hai aperto 
sull'argomento.
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)


Perfetto, fin qui è chiaro adesso, ma nel mio caso, come dovrei agire?
Considera che devo impostare i flag in base alla maschera data (true se 1, 0 
se false) posta in una stringa da 8 byte; come specifico questo in una sola 
chiamata alla funzione filesetattr?
Grazie ancora, Cooper. 

 chiamata alla funzione filesetattr?
Inizializzi a zero la variabile che conterrà il valore dell'attributo da 
utilizzare.
In seguito, scandisci il vettore (o la struttura dati che preferisci) in 
cui sono contenuti i flag da attivare.
Quando un flag è attivo, poni la variabile che conterrà il set di flag 
finale uguale a se stessa e in *or* con il flag in corso di esame.
Per esemplificare quest'ultima parte
   if UseHiddenFlag then
     FileAttrFlags := FileAttrFlags or faHidden;
Alla fine del ciclo, otterrai nella variabile il valore intero che 
corrisponde alla maschera di bit da utilizzare, ove ciascun bit vale 1 
se l'attributo del file ad esso associato deve essere impostato oppure no.


 ha scritto nel messaggio 
news:444cce7d$1...@newsgate.x-privat.org...

Provando a seguire il suggerimento dato ho scritto:
   Procedure SetAttrib (FileName: String; Mask: String);
     Var Attr, XCount, YCount: DWord;
     Begin
       Attr := 0;   YCount := 1;
       For XCount := 1 To 8 Do
         Begin
           YCount := YCount * 2;
           If Mask [8 - Succ(XCount)] = '1' Then Attr := Attr + YCount Div 
2;
         End;
       FileSetAttr (FileName, Attr);
     End;
In sostanza alla fine del ciclo Attr corrisponderà al valore decimale della 
stringa binaria passata in input tramite Mask; esempio:   Mask = '00100001' 
=> Attr = 33.
Quindi ho passato mask a FileSetAttr, ma non ottengo ancora il risultato 
voluto. Eppure stavolta mi sembra che il valore Attr da passare a 
FileSetAttr sia corretto.
Dove ho sbagliato?
Grazie ancora, Cooper. 


[...]
Se cerchi un convertitore da intero a binario e viceversa perché non provi a 
cercare con Google, ne esistono già tanti.
Te ne scrivo due al volo qui. A te controllarli, modificarli, isolare gli 
errori, usarli, sempre se vuoi.
Function IntToBin(value: integer): string;
var
a: integer;
begin
result:= '';
for a:= 1 to sizeof(value)*8 do
begin
if value and 1 = 1
then result:= '1' + result
else result:= '0' + result;
value:= value shr 1;
End;
end;
Function bintoint(value: string): integer;
var
a: integer;
begin
result:= 0;
for a:= 1 to length(value) do
begin
if value[a] = '1' then result:= result or 1;
result:= result shl 1;
end;
end;

 [...]
Non capisco perché introdurre così tante e disparate complessità, come 
quella della conversione dei flag in stringa e viceversa, per risolvere 
un esigenza così semplice.
E' possibile lavorare sempre su una singola variabile intera portando ad 
1 e a 0 i bit di cui è composta, usando le costanti che corrispondono ai 
vari attributi applicabili ad un file e adoperando correttamente gli 
operatori logici *and* e *or*, nonché quelli di spostamento come *shl* 
per accendere e spegnere un determinato bit all'interno della maschera.
Convertire la maschera in stringa e viceversa, usare un ciclo 
all'interno di un altro ciclo (non so il perché) moltiplicando uno degli 
indici per due e dividendolo nuovamente (o meglio, inspiegabilmente) 
ogni volta che viene usato non ha - almeno per me - alcun senso apparente.
Secondo me, dovresti innanzitutto prendere conoscenza del funzionamento 
di base della logica binaria e di come sfruttarla all'interno di Delphi.
Inoltre, dovresti approfondire anche le problematiche relative al 
"debugging": esegui il tuo programma passo per passo, metti dei 
breakpoint sulle varie istruzioni, osserva il valore delle variabili e 
verifica che il percorso eseguito da Delphi sia quello che ti aspetti e 
che hai precedentemente ideato quando hai scritto al codice, prima di 
tutto, e in seguito verifica che le variabili assumano i valori che 
desideri quando subentri in un caso specifico preso a modello per 
testare l'algoritmo.
In caso contrario, sei sempre fermo, rischi di scrivere codice non 
funzionante, a volte forse non necessario e poco ottimizzato, perdendo 
tempo poiché sei continuamente fermo e rimanendo bloccato di fronte a 
esigenze relativamente semplici come quella corrente in cui, in fondo, 
si tratta di alzare un bit, nulla di più.
L'accanimento sulla revisione di una parte di codice criptica quando non 
risultano chiari i concetti e i principi di funzionamento degli 
strumenti utilizzati è controproducente.


 ha scritto nel messaggio 
news:444cf235$0$29723$4faf...@reader2.news.tin.it...

Ok grazie mille, trovo questa soluzione piu interessante :)
Ho risolto anche il problema degli attributi :)
Cooper.