Parcourir un dossier ou un disque [résolu]

wiskywisky Membre
septembre 2005 modifié dans API AppKit #1
hello world,

je veut parcourir un dossier ou un volume.
Je doit utiliser [tt][NSFileManager defaultManager][/tt] c'est évident mais comment faire pour lancer la recherche dans les dossiers rencontrés.
Mon gros problème est que mon programme fuit si c'est mal gérer et comme il devient gros c'est plus dur a trouver les fuites. :-\\

j'ai donc les inconnues suivantes:
- lors du parcours du dossier racine doit-je relancer la fonction de scan pour chaque dossier rencontré?
- je risque de saturé le proc et faire planté mon appli?
- doit-je utilisé un NSTaks et comment on les utiliser?

merci d'avance pour vos réponces ;)

Réponses

  • wiskywisky Membre
    14:26 modifié #2
    voici ma fonction de parcour de disque:
    - (void)scanFolder:(NSString *)path<br />{<br />	NSArray *dos = [[NSArray alloc] initWithArray:[[NSFileManager defaultManager] directoryContentsAtPath:path]];<br />	NSString *npath;<br />	int i;<br />	BOOL isFold;<br />	for(i=0;i&lt;[dos count];i++)<br />	&nbsp; {<br />		npath = [[NSString stringWithString:path] stringByAppendingPathComponent:[dos objectAtIndex:i]];<br />		NSLog(@&quot;%@&quot;,npath);<br />		<br />		if ([[NSFileManager defaultManager] fileExistsAtPath:npath isDirectory:&amp;isFold] &amp;&amp; isFold &amp;&amp; [[NSFileManager defaultManager] isReadableFileAtPath:npath] &amp;&amp; ![[npath pathExtension] isEqualToString:@&quot;app&quot;] )<br />			[self scanFolder:npath];<br />		<br />	&nbsp; }<br />}
    


    il élimine automatiquement les applications des dossiers scanner. le problème est que je n'arrive pas à  indiquer de temps en temps le dossier en cours de scan dans un NSTextField. :'(
  • ChachaChacha Membre
    14:26 modifié #3
    dans 1125514778:

    voici ma fonction de parcour de disque

    C'est normal, ta fuite mémoire, tu ne libères jamais ton tableau "dos".
    Sinon, pour te simplifier la tâche, regarde un peu du côté de enumeratorAtPath. Tu devrais aimer !
    Pour ne pas explorer les applis, tu auras même la méthode skipDescendents.
    +
    Chacha
  • wiskywisky Membre
    14:26 modifié #4
    Merci beaucoup, j'ai réussi! <3 <3 <3 <3 <br />
    J'utilise des NSThread!

    //Lance la recherche dans le dossier utilisateur<br />[NSThread detachNewThreadSelector:@selector(scanFolder:) toTarget:self withObject:[[NSString stringWithString:@&quot;~&quot;] stringByExpandingTildeInPath]];
    


    initialisation de fin du traitement
    - (void)awakeFromNib<br />{<br />	[[NSNotificationCenter defaultCenter] addObserver:self<br />											 selector:@selector(endScan)<br />												 name:NSThreadWillExitNotification object:nil];<br />}
    



    le traitement du scan:
    - (void)scanFolder:(NSString *)path<br />{<br />	NSAutoreleasePool* threadAutoreleasePool = [[NSAutoreleasePool alloc] init];<br />	<br />	NSArray *dos = [[NSArray alloc] initWithArray:[[NSFileManager defaultManager] directoryContentsAtPath:path]];<br />	NSString *npath;<br />	int i;<br />	BOOL isFold;<br /><br />	for(i=0;i&lt;[dos count];i++)<br />	&nbsp; {<br />		npath = [[NSString stringWithString:path] stringByAppendingPathComponent:[dos objectAtIndex:i]];<br /><br />		if ([[NSFileManager defaultManager] fileExistsAtPath:npath isDirectory:&amp;isFold] &amp;&amp; isFold &amp;&amp; [[NSFileManager defaultManager] isReadableFileAtPath:npath] &amp;&amp; ![[npath pathExtension] isEqualToString:@&quot;app&quot;] )<br />			[self scanFolder:npath];<br />		//code de traitement des éléments du dossier en cours de scan<br />		<br />	&nbsp; }<br />	[dos release];<br />	[threadAutoreleasePool release];<br />}
    


    fin du traitement
    -(void)endScan<br />{<br />	//code de fin de traitement<br />}
    


    ça marche nikel et en plus il peut faire afficher l'état
    :kicking: :p :p :p :p :adios!: :adios!:
  • ChachaChacha Membre
    août 2005 modifié #5
    Avec un NSDirectoryEnumerator c'est un peu plus simple, mais bon, ta solution marche aussi.
    <br />-(void) scanFolder:(NSString*)path<br />{<br />  NSFileManager* fileManager = [NSFileManager defaultManager];<br />  NSDirectoryEnumerator* directoryEnumerator = [fileManager enumeratorAtPath:path];<br />  NSString* file = [directoryEnumerator nextObject];<br />  while(file)<br />  {<br />    file = [path stringByAppendingPathComponent:file];//remettre le prefixe au chemin courant<br />    BOOL isFolder = NO;<br />&nbsp; &nbsp; BOOL fileExists = [fileManager fileExistsAtPath:file isDirectory:&amp;isFolder];<br />&nbsp; &nbsp; if (fileExists &amp;&amp; !isFolder)<br />    {<br />      //code de traitement des éléments du dossier en cours de scan<br />    }<br />&nbsp; &nbsp; else if (isFolder &amp;&amp; [[file pathExtension] isEqualToString:@&quot;app&quot;])<br />      [directoryEnumerator skipDescendents]; //sauter les applications <br />    file = [directoryEnumerator nextObject];<br />  }<br />}<br />
    
  • AliGatorAliGator Membre, Modérateur
    14:26 modifié #6
    Juste une remarque stupide :

    au lieu de faire un nextEnumerator avant le début du while, et un à  la fin du while avant d'en sortir ou de reboucler, tu peux le mettre directement dans la condition du while
    NSString* file;<br />while(file = [directoryEnumerator nextObject])<br />{<br />    // ton code là <br />    // mais pas besoin du coup du &quot;file = [directoryEnumerator nextObject]&quot; à  la fin<br />}
    
    Comment ça je chipotte ?
    Comment ça ça revient au même ?
    Ouais mais bon heu c'est comme ça que tout le monde fait, alors heu... :o :o :o :o
  • wiskywisky Membre
    14:26 modifié #7
    J'ai utilisé en effet un enumerator.

    Mon système me donnait des doublons. J'ai encore des fuites parfois à  cause des variables qui sont utilisé en boucle mais jamais releasé.

    le metier rentre petit à  petit ;)
  • ChachaChacha Membre
    14:26 modifié #8
    dans 1125528937:

    Juste une remarque stupide :

    NSString* file;<br />while(file = [directoryEnumerator nextObject])<br />
    

    Comment ça je chipotte ?

    nan, nan et nan je n'écrirai jamais ça : ça génère un warning.
    J'ai programmé assez longtemps en C pour avoir eu plus que ma dose de dérapages, transformant un if (pointeur == NULL) en if (pointeur = NULL), donc maintenant, je m'interdis systématiquement les effets de bords dans les conditions des if, while et autres.
    Philosophie "Warning = erreur potentielle"
    +
    Chacha
  • fouffouf Membre
    14:26 modifié #9
    dans 1125559687:

    dans 1125528937:

    Juste une remarque stupide :

    NSString* file;<br />while(file = [directoryEnumerator nextObject])<br />
    

    Comment ça je chipotte ?

    nan, nan et nan je n'écrirai jamais ça : ça génère un warning.
    J'ai programmé assez longtemps en C pour avoir eu plus que ma dose de dérapages, transformant un if (pointeur == NULL) en if (pointeur = NULL), donc maintenant, je m'interdis systématiquement les effets de bords dans les conditions des if, while et autres.
    Philosophie "Warning = erreur potentielle"
    +
    Chacha


    Je comprends pas : ici tu n'as pas besoin de faire de if : si file == nil, alors tu sort de la boucle. Pourquoi aurais-tu des effets de bord ?
  • ChachaChacha Membre
    14:26 modifié #10
    dans 1125561021:

    Je comprends pas : ici tu n'as pas besoin de faire de if : si file == nil, alors tu sort de la boucle. Pourquoi aurais-tu des effets de bord ?

    Je ne dis pas que ça plante, je dis que c'est dangereux. En général, si par erreur tu mets = au lieu de ==, ça ne se comporte plus du tout pareil, donc c'est un bug (quelles que soient les conséquences).
    De ce fait, je tiens compte du warning qui dit que if (p = ...) est "suspect".
    Et pour tenir compte de ce warning, et bien je l'empêche d'arriver en n'écrivant jamais if ( p = ...)
    Je parle en termes généraux, pas pour ce code-là  en particulier, (sinon j'aurais parlé de while et pas de if, mais la construction est la même).
    ça fait partie du style, on a tous ses petites habitudes.

    +
    Chacha
  • septembre 2005 modifié #11
    Et est-ce que [tt]while ((file = [e nextObject]))[/tt] génère un warning? Je dis ça car je n'ai pas réglé mon compilo pour qu'il soit si attentif, mais comme le truc que je code doit aussi tourner sous GNUStep, on m'a fait cette suggestion.
  • ChachaChacha Membre
    14:26 modifié #12
    dans 1125565482:

    Et est-ce que [tt]while ((file = [e nextObject]))[/tt] génère un warning?

    Alors
    while (file = [e nextObject])
    génère un warning quand on active le warning "Missing braces and parentheses"
    Mais
    while ((file = [e nextObject]))
    ne génère pas de warning

    Cela dit, je trouve ça bien moche. Pour moi ça reste une mauvaise pratique (non non, ce n'est pas de la mauvaise foi).

    +
    Chacha
  • 14:26 modifié #13
    Pourquoi? Si c'est prévu justement pour éviter les problèmes de if (a = b) où est le problème?
  • ChachaChacha Membre
    septembre 2005 modifié #14
    dans 1125566115:

    Pourquoi? Si c'est prévu où est le problème?

    Au secours, on m'oblige à  troller ;-)
    On n'est pas obligé d'accepter toutes les facilités offertes par un langage, quand on a l'impression qu'elles rendent le code moins lisible
    Par exemple,
    -je ne déclare pas deux variables sur la même ligne,
    -j'initialise toujours mes variables
    -je n'utilise pas les affectations dans les conditions (comme ici)
    -je ne mets qu'un seul "return" par fonction, à  la fin
    -...

    En C, on peut quasiment toujours raccourcir le code, mais il y a des limites à  la lisibilité et à  la maintenance qui va avec.

    +
    Chacha

    [edit]
    Là  par exemple, le coup des doubles parenthèses, je trouve ça moche, ça ressemble à  du bricolage pour vraiment vouloir "faire sa connerie" ;-).
    Dans ce cas, autant décocher le warning, au moins on ne sera pas embêté.
    [/edit]
  • septembre 2005 modifié #15
    Ah tu veux troller?

    J'aurais tendance à  dire que
    [tt]file = [e nextObject];
    while (file) { // ou (file != nil) pour faire de mon puriste
    ...
    file = [e nextObject];
    }[/tt]
    est du bricolage pour éviter une possibilité offerte par le langage, et qui ne nuit en rien à  la lisibilité du code. Au début ça me dérangeait, mais une fois habitué ça ne me gène absolument plus. Je précise que c'est le seul cas où je fais ça.
  • ChachaChacha Membre
    14:26 modifié #16
    Ah ! je rigole !
    (file != nil) pour faire de mon puriste
    

    Ce n'est pas du purisme, c'est une complication non nécessaire. Sémantiquement, le test à  nil est équivalent au test booléen, nil et NO sont identiques, autant par le sens que par la valeur, tout comme pourrait l'être le test de vacuité d'une pile ou l'ouverture réussie d'une unité physique de stockage de données (un fichier quoi). Sinon, autant écrire if (ok == YES) au lieu de if (ok)
    Par contre, le while (file = ...) est complètement différent, puisqu'il cache une instruction d'affectation dans un test, ce qui perturbe la lisibilité et dénote une grammaire trop permissive dans un contexte qui se devrait rigoureux.

    (je précise... on ne sait jamais... je suis en mode second degré, là )

    +
    Chacha
  • AliGatorAliGator Membre, Modérateur
    14:26 modifié #17
    Hé bé si j'avais su que je déchaà®nerai le gars chacha à  ce point...!!
  • ChachaChacha Membre
    14:26 modifié #18
    dans 1125672778:

    Hé bé si j'avais su que je déchaà®nerai le gars chacha à  ce point...!!

    Un p'tit troll/flame de temps en temps, ça fait du bien... surtout quand c'est pas sérieux !
    +
    Chacha
  • wiskywisky Membre
    14:26 modifié #19
    il faut bien rire dans la vie ;)

    sinon ont meurt triste et c'est le pire :(

    pour ma part je déconne souvent, et en plus comme je n'est pas honte de faire le con, tout le monde rigole de mes conneries. Ou du fait que je suis vraiment con. :)
    <3 <3
  • AliGatorAliGator Membre, Modérateur
    14:26 modifié #20
    Suite du message précédent :
    dans 1125672778:

    Hé bé si j'avais su que je déchaà®nerai le gars chacha à  ce point...!!
    ...
    Ben j'aurai écrit ça plus tôt :) :)  ;) <3 <3 <br />
Connectez-vous ou Inscrivez-vous pour répondre.