Outils d'utilisateurs

Outils du Site


c_1y_file_system

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

c_1y_file_system [2014/03/11 18:01]
gbdivers créée
c_1y_file_system [2014/10/05 15:12] (Version actuelle)
91.182.106.28 [Les classes et énumérations]
Ligne 5: Ligne 5:
 ===== Les classes et énumérations ===== ===== Les classes et énumérations =====
  
-Le draft [[https://github.com/cplusplus/filesystem-ts|N3803]] est relativement simple à lire, puisqu'il n'y a pas de modification du langage, mais simplement des ajouts sous forme de bibliothèque. Ceux qui ont déjà utilisé une bibliothèque de gestion de fichiers retrouveront des éléments familiers. Du coup, je ne vais pas reprendre en détail le document (ce qui reviendrait en gros à le traduire), mais je vais donner des exemples de code pour répondre à des problématique spécifiques. Pour ceux intéressé par les détails, je vais juste décrire l'organisation du draft.+Le draft [[https://github.com/cplusplus/filesystem-ts|N3803]] est relativement simple à lire, puisqu'il n'y a pas de modification du langage, mais simplement des ajouts sous forme de bibliothèque. Ceux qui ont déjà utilisé une bibliothèque de gestion de fichiers retrouveront des éléments familiers. Du coup, je ne vais pas reprendre en détail le document (ce qui reviendrait en gros à le traduire), mais je vais donner des exemples de code pour répondre à des problématiques spécifiques. Pour ceux intéressés par les détails, je vais juste décrire l'organisation du draft.
  
 Le document commence à définir un ensemble de notions généralistes sur les systèmes de fichiers : ce qu'est un fichier, un répertoire, un nom de fichier ou de répertoire, un lien, ainsi que les notions de chemin absolu, relatif ou canonique. Le document commence à définir un ensemble de notions généralistes sur les systèmes de fichiers : ce qu'est un fichier, un répertoire, un nom de fichier ou de répertoire, un lien, ainsi que les notions de chemin absolu, relatif ou canonique.
  
-Ensuite, le document décrit les différentes types :+Ensuite, le document décrit les différents types :
  
   * la classe ''path'', qui représente un chemin vers un fichier ou répertoire ;   * la classe ''path'', qui représente un chemin vers un fichier ou répertoire ;
   * la classe ''filesystem_error'' pour la gestion des erreurs ;   * la classe ''filesystem_error'' pour la gestion des erreurs ;
-  * l'énumération ''file_type'' pour lister les types (fichier, répertoire, lien, etc) ; +  * l'énumération ''file_type'' pour lister les types (fichier, répertoire, lien, etc.) ; 
-  * l'énumération ''copy_options'' pour lister les options possibles lors d'une copie (écraser les fichiers existants, parcourir les sous-répertoires, suivre les liens symboliques, et.) ; +  * l'énumération ''copy_options'' pour lister les options possibles lors d'une copie (écraser les fichiers existants, parcourir les sous-répertoires, suivre les liens symboliques, etc.) ; 
-  * l'énumération ''perms'' pour lister les permissions d'un fichier (propriétaire du fichier, groupe d'utilisateurs, etc) ;+  * l'énumération ''perms'' pour lister les permissions d'un fichier (propriétaire du fichier, groupe d'utilisateurs, etc.) ;
   * la classe ''file_status'' pour gérer le type de fichier et les permissions d'accès ;   * la classe ''file_status'' pour gérer le type de fichier et les permissions d'accès ;
   * la classe ''directory_entry'' représente une entrée dans un répertoire, avec un chemin et les statuts du fichier ;   * la classe ''directory_entry'' représente une entrée dans un répertoire, avec un chemin et les statuts du fichier ;
Ligne 23: Ligne 23:
 Pour terminer, le document définit l'ensemble des fonctions libres pour copier, renommer, déplacer ou supprimer des fichiers et répertoires, manipuler les chemins, tester le type et les accès des fichiers, créer des liens. Pour terminer, le document définit l'ensemble des fonctions libres pour copier, renommer, déplacer ou supprimer des fichiers et répertoires, manipuler les chemins, tester le type et les accès des fichiers, créer des liens.
  
-L'ensemble des fonctionnalités est accessible via l'en-tête <filesystem>.+L'ensemble des fonctionnalités est accessible via l'en-tête ''<filesystem>''.
  
 ===== La gestion des erreurs ===== ===== La gestion des erreurs =====
Ligne 29: Ligne 29:
 Pour gérer les erreurs en C, il est classique d'utiliser un code d'erreur en retour de fonction. L'un des problèmes de cette approche est qu'il devient vite fastidieux d'ajouter du code pour tester toutes les erreurs et beaucoup de développeurs ne vérifient plus toutes les erreurs. Pour gérer les erreurs en C, il est classique d'utiliser un code d'erreur en retour de fonction. L'un des problèmes de cette approche est qu'il devient vite fastidieux d'ajouter du code pour tester toutes les erreurs et beaucoup de développeurs ne vérifient plus toutes les erreurs.
  
-Le C++ ajoute une nouvelle approche pour la gestion des erreurs : les exceptions. Cette différence majeure par rapport au C fait qu'il est très dangereux de porter directement du code C en C++. Un code aussi simple que le suivant ne sera pas valide en C++ (risque de fuite mémoire).+Le C++ ajoute une nouvelle approche pour la gestion des erreurs : [[http://en.cppreference.com/w/cpp/language/exceptions|les exceptions]]. Cette différence majeure par rapport au C fait qu'il est très dangereux de porter directement du code C en C++. Un code aussi simple que le suivant ne sera pas valide en C++ (risque de fuite mémoire).
  
 <code cpp> <code cpp>
Ligne 42: Ligne 42:
 Il est donc conseillé en C++ d'utiliser des classes assurant le RAII : les pointeurs intelligents (''shared_ptr'', ''weak_ptr'', ''unique_ptr''), les conteneurs standards (''vector'', ''list'', ''map'', etc.) et plus généralement les outils de la STL (''string'', ''stream'', etc). Je vous conseille la lecture de l'article [[http://alexandre-laurent.developpez.com/cpp/retour-fonctions-ou-exceptions/|Retour de fonctions ou exceptions ?]] Il est donc conseillé en C++ d'utiliser des classes assurant le RAII : les pointeurs intelligents (''shared_ptr'', ''weak_ptr'', ''unique_ptr''), les conteneurs standards (''vector'', ''list'', ''map'', etc.) et plus généralement les outils de la STL (''string'', ''stream'', etc). Je vous conseille la lecture de l'article [[http://alexandre-laurent.developpez.com/cpp/retour-fonctions-ou-exceptions/|Retour de fonctions ou exceptions ?]]
  
-En complément, le C++11 introduit un nouveau mot-clé ''noexcept'' qui permet d'indiquer qu'une fonction ne retournera pas d'exception (c'est-à-dire qu'elle ne lance pas d'exception et qu'elle n'appelle que des fonctions ''noexcept'').+En complément, le C++11 introduit un nouveau mot-clé ''noexcept'' qui permet d'indiquer qu'une fonction ne retournera pas d'exception (c'est-à-dire ne lançant pas d'exception et n’appelant que des fonctions ''noexcept'').
  
-Les fonctions de //File System// existent en deux versions, l'une utilisant la gestion d'erreur par exception et l'autre par un code d'erreur. Pour garder les signatures des fonctions similaires, le code d'erreur est passé comme argument (référence non constante) et non en retour de fonction.+Les fonctions de //File System// existent en deux versions, l'une utilisant la gestion d'erreur par exception et l'autre par code d'erreur. Pour garder les signatures des fonctions similaires, le code d'erreur est passé comme argument (référence non constante) et non en retour de fonction.
  
 Ainsi, pour tester l’existence d'un fichier, la fonction ''exists'' existe selon les deux signatures suivantes : Ainsi, pour tester l’existence d'un fichier, la fonction ''exists'' existe selon les deux signatures suivantes :
Ligne 53: Ligne 53:
 </code> </code>
  
-La première version ne prend pas de code d'erreur en argument, la second oui (et est donc déclarée en ''noexcept''). Pour les utiliser :+La première version ne prend pas de code d'erreur en argument, la seconde oui (et est donc déclarée en ''noexcept''). Pour les utiliser :
  
 <code cpp> <code cpp>
Ligne 71: Ligne 71:
 </code> </code>
  
-(Je ne suis pas sûr du code pour tester le code d'erreur, le type error_code n'est pas défini).+(Je ne suis pas sûr du code pour tester le code d'erreur, le type ''error_code'' n'est pas défini).
  
 Il est préférable d'utiliser la version avec exception par défaut. Il est préférable d'utiliser la version avec exception par défaut.
Ligne 77: Ligne 77:
 ===== Les fonctions libres ===== ===== Les fonctions libres =====
  
-Beaucoup de fonction prennent en paramètre un objet de type ''path'' ou de type ''file_status''. Comme il existe un constructeur (non ''explicit'') de ''path'' prenant en paramètre une chaîne, il est possible d'appeler les fonctions directement avec une chaîne.+Beaucoup de fonctions prennent en paramètre un objet de type ''path'' ou de type ''file_status''. Comme il existe un constructeur (non ''explicit'') de ''path'' prenant en paramètre une chaîne, il est possible d'appeler les fonctions directement avec une chaîne.
  
 <code cpp> <code cpp>
Ligne 86: Ligne 86:
 </code> </code>
  
-==== Connaître le répertoire courant ====+===== Connaître le répertoire courant =====
  
 <code cpp> <code cpp>
Ligne 92: Ligne 92:
 </code> </code>
  
-==== Les fonctions de tests ====+===== Chemin relatif, absolu, canonique ===== 
 + 
 +Un chemin n'est pas représenté par une écriture unique, plusieurs chaînes de caractères peuvent correspondre à un même chemin (et donc au même fichier ou même répertoire) : 
 + 
 +  * le chemin relatif est le chemin défini à partir d'un emplacement (le plus souvent, l'application) ; 
 +  * le chemin absolu est défini à partir de la racine, avec ou sans définir le chemin de base ; 
 +  * le chemin canonique est le chemin absolu sans lien symbolique ou élément ''.'' et ''..'' 
 + 
 +Les fonctions ''absolute'' et ''canonical'' permettent d'obtenir les chemins absolu et canonique : 
 + 
 +<code cpp> 
 +auto path_absolute = absolute(old_path); 
 +auto path_absolute = absolute("my_file.cpp"); 
 +auto path_absolute = absolute("my_file.cpp", "/home/me"); 
 + 
 +auto path_canonical = canonical(old_path); 
 +auto path_canonical = canonical("my_file.cpp"); 
 +auto path_canonical = canonical("my_file.cpp", "/home/me"); 
 +</code> 
 + 
 +La fonction ''system_complete'' permet de retourner un chemin absolu à partir du répertoire courant ou de root. 
 + 
 +<code cpp> 
 +auto p system_complete(my_file); 
 +    // est équivalent à : 
 +auto p absolute(my_file, current_path()); 
 +</code> 
 + 
 +===== Statuts des fichiers ===== 
 + 
 +La fonction ''statuts'' permet de connaître le type et les permissions d'un fichier. 
 + 
 +<code cpp> 
 +auto file_statuts = statuts(my_file); 
 +auto perms = file_statuts.permissions(); 
 +if (file_statuts.type() = file_type.regular) 
 +    cout << "Est un fichier régulier" << endl; 
 +</code> 
 + 
 +Ces fonctions sont similaires aux fonctions suivantes, permettant de tester directement le type d'un fichier.
  
 <code cpp> <code cpp>
Ligne 107: Ligne 146:
 auto b9 = is_socket(m_filename); // type socket ? auto b9 = is_socket(m_filename); // type socket ?
 auto b10 = is_fifo(my_filename); // type fifo ? auto b10 = is_fifo(my_filename); // type fifo ?
 +</code>
 +
 +La fonction ''statuts'' peut émettre une exception ''filesystem_error'' si le type détecté est ''file_type::none''. Attention, les types ''file_type::not_found'' et ''file_type::unknown'' ne sont pas considérés comme des erreurs et ne lancent pas d'exception (cela est considéré comme étant normal dans le fonctionnement des systèmes de fichiers).
 +
 +Pour terminer, la fonction ''status_known'' permet de tester si un statut est connu (c'est-à-dire qu'il n'est pas de type ''file_type::none'').
 +
 +<code cpp>
 +if (status_known(file_statuts))
 +    cout << "Statut connu" << endl;
 +</code>
 +
 +La fonction ''symlink_status'' est similaire à statuts, mais retourne ''file_type::symlink'' si le chemin correspond à un lien symbolique.
 +
 +<code cpp>
 +auto file_statuts = symlink_status(my_file);
 </code> </code>
  
Ligne 116: Ligne 170:
 </code> </code>
  
-==== Connaître la taille d'un fichier ====+==== Taille des fichiers ====
  
 <code cpp> <code cpp>
 auto size = file_size(my_filename); auto size = file_size(my_filename);
 +resize_file(my_filename, new_size);
 auto b = is_empty(my_filename); auto b = is_empty(my_filename);
 </code> </code>
  
-==== Chemin relatifabsolu, canonique ====+Il est également possible d'obtenir des informations sur le système de fichiersavec la fonction ''space''. Celle-ci prend en paramètre un chemin vers n'importe quel fichier du système de fichiers.
  
-Un chemin n'est pas représenté par une écriture unique, plusieurs chaînes de caractères peuvent correspondre à un même chemin (et donc au même fichier ou même répertoire:+<code cpp> 
 +auto s = space(my_file)
 +cout << s.capacity << endl; // capacité 
 +cout << s.free << endl; // espace libre 
 +cout << s.available << endl; // espace 
 +    // disponible, en fonction des autorisations d'accès 
 +</code>
  
-  * le chemin relatif est le chemin défini à partir d'un emplacement (le plus souvent, l'application) ; +==== Gérer les permissions d'accès ====
-  * le chemin absolu est défini à partir de la racine, avec ou sans définir le chemin de base ; +
-  * le chemin canonique est le chemin absolu sans lien symbolique ou élément ''.'' et ''..''+
  
-Les fonction absolute et canonical permettent d'obtenir les chemins absolu et canonique :+Les permissions sont définies dans l'énumération ''perms'', pour le propriétaire, le groupe et les autres : 
 + 
 +  * ''none'' (ne fait rien) ; 
 +  * Pour le propriétaire : 
 +    * ''owner_read'' (lecture) ; 
 +    * ''owner_write'' (écriture) ; 
 +    * ''owner_exec'' (exécutable) ; 
 +    * ''owner_all'' (tout) ; 
 +  * Pour le groupe : 
 +    * ''group_read'' (lecture) ; 
 +    * ''group_write'' (écriture) ; 
 +    * ''groupe_exec'' (exécutable) ; 
 +    * ''group_all'' (tout) ; 
 +  * Pour les autres : 
 +    * ''others_read'' (lecture) ; 
 +    * ''others_write'' (écriture) ; 
 +    * ''others_exec'' (exécutable) ; 
 +    * ''others_all'' (tout) ; 
 +  * ''all'' (toutes les permissions, pour tout le monde) ; 
 +  * Pour les identifiants : 
 +    * ''set_uid'' (user id) ; 
 +    * ''set_gid'' (group id) ; 
 +    * ''sticky_bit'' (système dépendant). 
 + 
 +Deux valeurs supplémentaires permettent de sélectionner le mode de modification des permissions : 
 + 
 +  * ''add_perms'' : ajoute les permissions ; 
 +  * ''remove_perms''  supprime les permissions ; 
 +  * aucun des deux : remplace les permissions. 
 + 
 +Il existe également d'autres valeurs : 
 + 
 +  * ''resolve_symlinks'' 
 +  * ''mask'' 
 +  * ''unknown''
  
 <code cpp> <code cpp>
-auto path_absolute = absolute(old_path); +permissions(my_file, perms(all)); 
-auto path_absolute = absolute("my_file.cpp"); +    // donne les permissions à tout le monde
-auto path_absolute = absolute("my_file.cpp", "/home/me");+
  
-auto path_cononical = canonical(old_path); +permissions(my_file, perms(others_all | remove_perms)); 
-auto path_canonical = canonical("my_file.cpp"); +    // supprime toutes les permissions des autres 
-auto path_canonical = canonical("my_file.cpp"";/home/me");+ 
 +permissions(my_file, perms(other_read | add_perms)); 
 +    // ajoute l'autorisation en lecture pour les autres
 </code> </code>
  
-==== Copie des fichiers et répertoires ====+Pour connaître les permissions : 
 + 
 +<code cpp> 
 +auto perms status.permissions() 
 +</code> 
 + 
 +===== Manipulation des fichiers et répertoires ===== 
 + 
 +==== Copie ====
  
 Les options de copie sont définies dans l'énumération ''copy_options'' : Les options de copie sont définies dans l'énumération ''copy_options'' :
Ligne 155: Ligne 257:
     * ''none'' (ne rien faire) ;     * ''none'' (ne rien faire) ;
     * ''recursive'' (parcourir les sous-répertoires).     * ''recursive'' (parcourir les sous-répertoires).
-  * lien symbolique : +  * lien symbolique :
     * ''none'' (ne rien faire) ;     * ''none'' (ne rien faire) ;
     * ''copy_symlinks'' (copier les liens symboliques) ;     * ''copy_symlinks'' (copier les liens symboliques) ;
     * ''skip_symlinks'' (passer les liens symboliques).     * ''skip_symlinks'' (passer les liens symboliques).
-  * type de copie : +  * type de copie :
     * ''none'' (ne rien faire) ;     * ''none'' (ne rien faire) ;
     * ''directories_only'' (copier seulement les répertoires) ;     * ''directories_only'' (copier seulement les répertoires) ;
Ligne 182: Ligne 284:
 </code> </code>
  
-==== Créer des répertoires ou des liens symboliques ==== +==== Suppression ====
- +
-<code cpp> +
-create_directory("/home/me/my_dir"); +
-create_directories("/home/me/my_dir"); +
-create_directory_symlink("/home/me/my_dir"); +
-create_hard_link("/home/me/link"); +
-create_symlink("/home/me/link"); +
-</code> +
- +
-==== Suppression des fichiers et répertoires ====+
  
 <code cpp> <code cpp>
Ligne 199: Ligne 291:
 </code> </code>
  
-==== Pour renommer ==== +==== Renommer ====
  
 <code cpp> <code cpp>
Ligne 205: Ligne 297:
 </code> </code>
  
-==== Gérer les permissions ==== +==== Création des répertoires ou des liens symboliques ====
- +
-Les permissions sont définies dans l'énumération ''perms'', pour le propriétaire, le groupe et les autres : +
- +
-  * ''none'' (ne fait rien) ; +
-  * Pour le propriétaire : +
-    * ''owner_read'' (lecture) ; +
-    * ''owner_write'' (écriture) ; +
-    * ''owner_exec'' (exécutable) ; +
-    * ''owner_all'' (tout) ; +
-  * Pour le groupe : +
-    * ''group_read'' (lecture) ; +
-    * ''group_write'' (écriture) ; +
-    * ''groupe_exec'' (exécutable) ; +
-    * ''group_all'' (tout) ; +
-  * Pour les autres : +
-    * ''others_read'' (lecture) ; +
-    * ''others_write'' (écriture) ; +
-    * ''others_exec'' (exécutable) ; +
-    * ''others_all'' (tout) ; +
-  * ''all'' (toutes les permissions, pour tot le monde) ; +
- +
-L'énumération ''perms" permet également de spécifier les modifications : +
- +
-  * set_uid +
-  * set_gid +
-  * sticky_bit +
-  * mask +
-  * unknown +
-  * add_perms +
-  * remove_perms +
-  * resolve_symlinks+
  
 <code cpp> <code cpp>
-auto p = perms(owner_all | remove_perms);+create_directory("/home/me/my_dir"); 
 +create_directories("/home/me/my_dir"); 
 +create_directory_symlink("/home/me/my_dir"); 
 +create_hard_link("/home/me/link"); 
 +create_symlink("/home/me/link");
 </code> </code>
  
-Pour modifier les permissions : +La fonction ''hard_link_count'' permet de connaître le nombre de hard link d'un chemin :
 <code cpp> <code cpp>
-permissions(my_path, perms);+cout << hard_link_count("/home/me/file");
 </code> </code>
  
-connaître les permissions :+La fonction ''read_symlink'' permet de récupérer le chemin pointé par un lien symbolique. 
 <code cpp> <code cpp>
-auto perms status.permissions()+auto read_symlink(my_file);
 </code> </code>
  
-==== Divers ====+===== Fichier et répertoire temporaire ===== 
 + 
 +Pour faciliter la création de fichiers temporaires, la fonction ''unique_path'' permet de créer un chemin qui n'existe pas, ce qui permet de créer un fichier sans supprimer ou modifier un fichier existant. Pour cela, la fonction prend une chaîne de caractères comme modèle et génère aléatoirement un nom de fichier. Les caractères ''%'' de la chaîne sont remplacés par une valeur hexadécimale. Par défaut, le modèle est ''"%%%%-%%%%-%%%%-%%%%"''.
  
-Nombre de hard link 
 <code cpp> <code cpp>
-hard_link_count(&quot;/home/me/file");+cout << unique_path(&lt;< endl; 
 +    // peut générer par exemple : 25e9-a1f3-6b4b-671c 
 +    // 2^64 valeurs possibles 
 + 
 +cout << unique_path("test-%%%%%%%%%%%.txt") <;< endl; 
 +    // peut générer par exemple : test-0db7f2bf57a.txt 
 +    // 2^44 valeurs possibles
 </code> </code>
  
-  * read_symlink +La fonction ''temp_directory_path'' permet d'obtenir un répertoire existant pour enregistrer des fichiers temporaires. Le répertoire obtenu dépend de l'implémentation et peut correspondre par exemple à ''"/tmp"'' ou au retour de la fonction ''GetTempPath''.
-  * resize_file +
-  * space +
-  * statuts +
-  * status_known +
-  * symlink_status +
-  * system_complete +
-  * temp_directory_path +
-  * unique_path+
  
 +<code cpp>
 +auto temp_path = temp_directory_path();
 +</code>
  
 {{tag> C++ C++1y}} {{tag> C++ C++1y}}
c_1y_file_system.1394557271.txt.gz · Dernière modification: 2014/03/11 18:01 par gbdivers