2010-06-14 26 views
16

¿Hay alguna manera con Qt 4.6 de verificar si un determinado QString es un nombre de archivo (o nombre de directorio) válido en el sistema operativo actual? Quiero verificar que el nombre sea válido, no para que el archivo exista.Compruebe si una cadena es un nombre de archivo válido con Qt

Ejemplos:

// Some valid names 
test 
under_score 
.dotted-name 

// Some specific names 
colon:name // valid under UNIX OSes, but not on Windows 
what? // valid under UNIX OSes, but still not on Windows 

¿Cómo voy a lograr esto? ¿Hay alguna función incorporada Qt?

Me gustaría evitar crear un archivo vacío, pero si no hay otra manera confiable, todavía me gustaría ver cómo hacerlo de una manera "limpia".

Muchas gracias.

Respuesta

3

no creo que Qt tiene una función incorporada, pero si Boost es una opción, puede utilizar Boost.Filesystem de name_check functions.

Si Boost no es una opción, su página en funciones name_check sigue siendo una buena visión general de lo que se debe comprobar en varias plataformas.

+0

'boost' es definitivamente una opción ¡y eso es perfecto! Muchas gracias ! – ereOn

+3

Nota boost no verifica nombres inválidos (en win) como com, lpt, aux, etc., para aquellos que no recuerdan los días de DOS. –

0

Solo crearía una función simple para validar el nombre de archivo de la plataforma, que solo busca en la cadena los caracteres no válidos. No creo que haya una función incorporada en Qt. Puedes usar #ifdefs dentro de la función para determinar en qué plataforma estás. Lo suficientemente limpio como yo diría.

21

Esta es la respuesta que obtuve de Silje Johansen - Ingeniero de Soporte - Trolltech ASA (marzo de 2008 aunque)

Sin embargo. la complejidad de incluir la configuración regional y encontrar una forma unificada de consultar los sistemas de archivos en Linux/Unix sobre su funcionalidad es casi imposible.

Sin embargo, que yo sepa, todas las aplicaciones que conozco ignoran este problema .

(léase: no van a ponerlo en práctica)

Boost no resuelve el problema, que sólo dan una idea vaga de la longitud máxima de los caminos, especialmente si quieres estar plataforma cruzada. Por lo que sé, muchos han intentado y no han podido resolver este problema (al menos en teoría, en la práctica es definitivamente posible escribir un programa que crea nombres de archivo válidos en la mayoría de los casos.

Si desea implementar esto por sí mismo, podría valer la pena considerar algunas cosas no inmediatamente obvias como:

Las complicaciones con caracteres no válidos

La diferencia entre las limitaciones del sistema de archivos y las limitaciones del sistema operativo y software.El Explorador de Windows, que considero parte del sistema operativo Windows, no es totalmente compatible con NTFS, por ejemplo. Los archivos que contienen ':' y '?', Etc ... pueden residir felizmente en una partición ntfs, pero Explorer simplemente los ahoga. Aparte de eso, puede jugar seguro y utilizar las recomendaciones de Boost Filesystem.

Las complicaciones con la longitud de la trayectoria

El segundo problema no abordado plenamente por la página de impulso es la longitud de la ruta completa. Probablemente, lo único que es cierto en este momento es que ninguna combinación de sistema de archivos/OS admite longitudes de ruta indefinidas. Sin embargo, las afirmaciones como "Las rutas máximas de Windows están limitadas a 260 caracteres" son incorrectas. La API Unicode de Windows le permite crear rutas de hasta 32.767 utf-16 caracteres. No lo he comprobado, pero imagino que Explorer se asfixia con la misma dedicación, lo que haría que esta característica sea completamente inútil para el software que tenga usuarios que no sean usted (por otro lado, es posible que prefiera no tener el estrangulador de software a coro).

Existe una variable antigua que recibe el nombre de PATH_MAX, que suena prometedor, pero el problema es que PATH_MAX simply isn't.

Para finalizar con una nota constructiva, aquí hay algunas ideas sobre posibles formas de codificar una solución.

  1. Use define para hacer secciones específicas del sistema operativo. (Qt can help you with this)
  2. uso Los consejos que se dan en la página impulso y la documentación del sistema operativo y el sistema de archivos para decidir sobre sus caracteres no válidos
  3. Para longitud de la trayectoria de la única idea viable que me viene a la mente es un ensayo árbol binario un enfoque de error mediante el manejo de errores de las llamadas al sistema para verificar una longitud de ruta válida. Esto es bastante distante, pero podría ser la única posibilidad de obtener resultados precisos en una variedad de sistemas.
  4. Ponte a la altura del elegante manejo de errores.

Espero que esto haya dado algunas ideas.

+0

Gracias, muy instructiva y bien escrita respuesta. Merece mi +1. – ereOn

+1

¡Oye, gracias, eso lo convierte en mi primer voto popular! Por ahora, incluso tengo la reputación suficiente para limpiar los enlaces y votar su pregunta ... Soñemos que algún día surgirá una buena biblioteca para abordar este problema tan común. – nus

+0

+1 y especialmente para su idea # 4. – Hossein

1

Sobre la base de la respuesta de User7116 aquí:

How do I check if a given string is a legal/valid file name under Windows?

que dejar de ser perezoso - en busca de soluciones elegantes, y justo codificado él. Tengo:

bool isLegalFilePath(QString path) 
{ 
    // Anything following the raw filename prefix should be legal. 
    if (path.left(4)=="\\\\?\\") 
     return true; 

    // Windows filenames are not case sensitive. 
    path = path.toUpper(); 

    // Trim the drive letter off 
    if (path[1]==':' && (path[0]>='A' && path[0]<='Z')) 
     path = path.right(path.length()-2); 

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

    foreach (const QChar& c, path) 
    { 
     // Check for control characters 
     if (c.toLatin1() > 0 && c.toLatin1() < 32) 
      return false; 

     // Check for illegal characters 
     if (illegal.contains(c)) 
      return false; 
    } 

    // Check for device names in filenames 
    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& s, devices) 
     if (basename == s) 
      return false; 

    // Check for trailing periods or spaces 
    if (path.right(1)=="." || path.right(1)==" ") 
     return false; 

    // Check for pathnames that are too long (disregarding raw pathnames) 
    if (path.length()>260) 
     return false; 

    // Exclude raw device names 
    if (path.left(4)=="\\\\.\\") 
     return false; 

    // Since we are checking for a filename, it mustn't be a directory 
    if (path.right(1)=="\\") 
     return false; 

    return true; 
} 

Características:

  • Probablemente más rápido que utilizando expresiones regulares
  • Comprueba si hay caracteres no válidos y excluye los nombres de dispositivo (tenga en cuenta que '\' no es ilegal, ya que puede estar en camino nombres)
  • Permite letras de unidad
  • permite que los nombres completos de rutas
  • permite nombres de ruta de red
  • Permite nada después de \\? \ (Nombres de archivo en bruto)
  • rechaza cualquier cosa que empiece con \\. \ (Nombres de dispositivos básicos)
  • no permite nombres terminan en "\" (es decir,nombres de directorio)
  • no permite nombres de más de 260 caracteres que no empiezan con \\? \
  • Impide espacios finales y períodos

Tenga en cuenta que no se comprueba la longitud de los nombres de fichero comenzando con \\? \, ya que esa no es una regla dura y rápida. También tenga en cuenta que, como se señala en here, los nombres que contienen múltiples barras diagonales inversas y barras diagonales no son rechazados por la API win32.

+0

Esto no funciona, p. diéresis. :-("Ä" es 196 y c.toLatin1() devuelve -60 que es menor que 32. – falkb

+0

mejor uso: if (c.toLatin1()> 0 && c.toLatin1() <32) – falkb

+0

Hmm. Después de mirar De nuevo, me pregunto si un carácter de control puede codificarse en un QString. Si está almacenado como UTF16 internamente, entonces el carácter de control debería existir en el estándar UTF. Tendré que analizarlo cuando tenga tiempo. , o podría. – CodeLurker

Cuestiones relacionadas