20 votes

Vérifiez si une chaîne est un nom de fichier valide avec Qt

Y a-t-il un moyen avec Qt 4.6 de vérifier si un QString donné est un nom de fichier valide (ou de répertoire) sur le système d'exploitation actuel ? Je veux vérifier que le nom est valide, pas que le fichier existe.

Exemples :

// Certains noms valides
test
under_score
.dotted-name

// Certains noms spécifiques
colon:name // valide sous les systèmes UNIX, mais pas sur Windows
what? // valide sous les systèmes UNIX, mais toujours pas sur Windows

Comment puis-je réaliser cela ? Y a-t-il une fonction intégrée de Qt pour cela ?

J'aimerais éviter de créer un fichier vide, mais s'il n'y a pas d'autre moyen fiable, j'aimerais quand même savoir comment le faire de manière "propre".

Merci beaucoup.

23voto

nus Points 1613

C'est la réponse que j'ai obtenue de Silje Johansen - Ingénieur Support - Trolltech ASA (en mars 2008 cependant)

Cependant. la complexité de l'inclusion des paramètres locaux et de trouver une façon unifiée d'interroger les systèmes de fichiers sur Linux/Unix à propos de leur fonctionnalité est proche de l'impossible.

Cependant, à ma connaissance, toutes les applications que je connais ignorent ce problème.

(à lire : ils ne vont pas le mettre en œuvre)

Boost ne résout pas non plus le problème, ils donnent seulement une notion vague de la longueur maximale des chemins, en particulier si vous voulez être multiplateforme. Autant que je sache, beaucoup ont essayé et ont échoué à résoudre ce problème (du moins en théorie, en pratique il est certainement possible d'écrire un programme qui crée des noms de fichiers valides dans la plupart des cas.

Si vous souhaitez le mettre en œuvre vous-même, il pourrait être utile de prendre en compte quelques choses qui ne sont pas immédiatement évidentes, comme :

Complications avec les caractères non valides

La différence entre les limitations du système de fichiers et les limitations du système d'exploitation et du logiciel. Par exemple, Windows Explorer, que je considère comme faisant partie du système d'exploitation Windows, ne prend pas en charge pleinement le NTFS. Des fichiers contenant ':' et '?', etc... peuvent résider sans problème sur une partition ntfs, mais Explorer s'étouffe juste avec eux. Mis à part cela, vous pouvez jouer la prudence et utiliser les recommandations de Boost Filesystem.

Complications avec la longueur du chemin

Le deuxième problème partiellement abordé par la page de boost est la longueur du chemin complet. La seule chose certaine à ce moment est qu'aucune combinaison OS/système de fichiers ne supporte des longueurs de chemin indéfinies. Cependant, des affirmations comme "les chemins maximum de Windows sont limités à 260 caractères" sont fausses. L'API unicode de Windows vous permet en fait de créer des chemins allant jusqu'à 32,767 caractères utf-16. Je n'ai pas vérifié, mais j'imagine qu'Explorer s'étouffe de la même manière, ce qui rendrait cette fonctionnalité complètement inutile pour les logiciels ayant des utilisateurs autres que vous-même (d'un autre côté, vous préférerez peut-être que votre logiciel ne s'étouffe pas en chœur).

Il existe une ancienne variable qui répond au nom de PATH_MAX, qui semble prometteuse, mais le problème est que PATH_MAX simplement n'est pas.

Pour finir sur une note constructive, voici quelques idées sur des façons possibles de coder une solution.

  1. Utilisez des définitions pour créer des sections spécifiques aux OS. (Qt peut vous aider avec cela)
  2. Utilisez les conseils donnés sur la page de boost et la documentation des OS et des systèmes de fichiers pour décider des caractères non valides
  3. Pour la longueur du chemin, la seule idée réalisable qui me vient à l'esprit est une approche d'essai et d'erreur avec un arbre binaire en utilisant la gestion d'erreurs de l'appel système pour vérifier une longueur de chemin valide. C'est plutôt distant, mais cela pourrait être la seule possibilité d'obtenir des résultats précis sur une variété de systèmes.
  4. Devenez bon en gestion d'erreurs élégante.

J'espère que cela vous a donné des idées.

4voto

CodeLurker Points 6

Basé sur la réponse de User7116 ici:

Comment vérifier si une chaîne donnée est un nom de fichier légal/valide sous Windows?

J'ai arrêté d'être paresseux - à la recherche de solutions élégantes, et je l'ai simplement codé. J'ai obtenu:

bool isLegalFilePath(QString path)
{
    if (!path.length())
        return false;

    // Tout ce qui suit le préfixe de nom de fichier brut doit être légal.
    if (path.left(4)=="\\\\?\\")
        return true;

    // Les noms de fichiers Windows ne sont pas sensibles à la casse.
    path = path.toUpper();

    // Supprimer la lettre de lecteur
    if (path[1]==':' && (path[0]>='A' && path[0]<='Z'))
        path = path.right(path.length()-2);

    QString illegal="<>:\"|?*";

    foreach (const QChar& c, path)
    {
        // Vérifier les caractères de contrôle
         if (c.toLatin1() >= 0 && c.toLatin1() < 32)
            return false;

        // Vérifier les caractères interdits
        if (illegal.contains(c))
            return false;
    }

    // Vérifier les noms de périphériques dans les noms de fichiers
    static QStringList devices;

    if (!devices.count())
        devices << "CON" << "PRN" << "AUX" << "NUL" << "COM0" << "COM1" << "COM2"
                << "COM3" << "COM4" << "COM5" << "COM6" << "COM7" << "COM8" << "COM9" << "LPT0"
                << "LPT1" << "LPT2" << "LPT3" << "LPT4" << "LPT5" << "LPT6" << "LPT7" << "LPT8"
                << "LPT9";

    const QFileInfo fi(path);
    const QString basename = fi.baseName();

    foreach (const QString& d, devices)
        if (basename == d)

            // Remarque: Les noms avec ':' autre que avec une lettre de lecteur ont déjà été rejetés.
            return false;    

    // Vérifier les points ou les espaces en fin de nom
    if (path.right(1)=="." || path.right(1)==" ")
        return false;

    // Vérifier les noms de chemin trop longs (ignorant les noms de chemin bruts)
    if (path.length()>260)
        return false;

    // Exclure les noms de périphérique bruts
    if (path.left(4)=="\\\\.\\")
        return false;

    // Comme nous vérifions un nom de fichier, cela ne doit pas être un répertoire
    if (path.right(1)=="\\")
        return false;

    return true;
}

Fonctionnalités:

  • Probablement plus rapide que d'utiliser des expressions régulières
  • Vérifie les caractères illégaux et exclut les noms de périphériques (notez que '' n'est pas illégal, car il peut être dans les noms de chemin)
  • Permet les lettres de lecteur
  • Permet les noms de chemin complets
  • Permet les noms de chemin réseau
  • Permet tout après \\?\ (noms de fichiers bruts)
  • Interdit tout ce qui commence par \\.\ (noms de périphériques bruts)
  • Interdit les noms se terminant par "\" (c'est-à-dire les noms de répertoires)
  • Interdit les noms plus longs que 260 caractères ne commençant pas par \\?\
  • Interdit les espaces et les points en fin de nom

Remarquez qu'il ne vérifie pas la longueur des noms de fichiers commençant par \\?, car ce n'est pas une règle stricte. Notez également, comme indiqué ici, les noms contenant plusieurs barres obliques inverses et barres obliques normales ne sont PAS rejetés par l'API win32.

3voto

Josh Kelley Points 24438

Je ne pense pas que Qt ait une fonction intégrée, mais si Boost est une option, vous pouvez utiliser les fonctions name_check de Boost.Filesystem.

Si Boost n'est pas une option, sa page sur les fonctions name_check reste une bonne vue d'ensemble de ce qu'il faut vérifier sur différentes plateformes.

1voto

Martin Beckett Points 60406

Difficile à faire de manière fiable sur Windows (quelques choses étranges telles qu'un fichier nommé "com" restant toujours invalide) et voulez-vous gérer l'unicode, ou des astuces de subst pour permettre un nom de fichier >260 caractères.

Il y a déjà une bonne réponse ici Comment vérifier si une chaîne donnée est un nom de fichier légal / valide sous Windows?

1voto

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X