Проверьте, является ли строка допустимым именем файла с помощью Qt - PullRequest
19 голосов
/ 14 июня 2010

Есть ли способ с Qt 4.6 проверить, является ли данное QString действительным именем файла (или именем каталога) в текущей операционной системе?Я хочу проверить правильность имени, , а не , чтобы файл существовал.

Примеры:

// 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

Как бы мне этого добиться?Есть ли какая-нибудь Qt встроенная функция?

Я бы хотел избежать создания пустого файла, но если нет другого надежного способа, я все равно хотел бы посмотреть, как это сделать в "чистый "путь.

Большое спасибо.

Ответы [ 6 ]

22 голосов
/ 21 июня 2010

Это ответ, который я получил от Силье Йохансена - инженера службы поддержки - Trolltech ASA (хотя в марте 2008 г.)

Тем не менее. сложность включения настроек локали и поиска унифицированный способ запроса файловых систем в Linux / Unix об их функциональность близка к невозможной.

Однако, насколько мне известно, все известные мне приложения игнорируют это проблема.

(читай: они не собираются это реализовывать)

Повышение также не решает проблему, они дают лишь смутное представление о максимальной длине путей, особенно если вы хотите быть кроссплатформенным. Насколько я знаю, многие пытались и не смогли взломать эту проблему (по крайней мере, теоретически, на практике совершенно определенно можно написать программу, которая создает действительные имена файлов в большинстве случаев .

Если вы хотите реализовать это самостоятельно, возможно, стоит рассмотреть несколько не сразу очевидных вещей, таких как:

Осложнения с недопустимыми символами

Разница между ограничениями файловой системы и ОС и программного обеспечения. Проводник Windows, который я считаю частью ОС Windows, не полностью поддерживает NTFS, например. Файлы, содержащие «:», «?» И т. Д., Могут с легкостью находиться в разделе ntfs, но Explorer их просто душит. Кроме этого, вы можете играть безопасно и использовать рекомендации из Boost Filesystem .

Осложнения с длиной пути

Вторая проблема, которая не полностью решена страницей повышения, - это длина полного пути. Вероятно, единственное, что определенно в данный момент, - это то, что никакая комбинация ОС / файловой системы не поддерживает неопределенную длину пути. Однако такие утверждения, как «Максимальный путь Windows ограничен 260 символами», неверны. Unicode API из Windows позволяет создавать пути длиной до 32 767 символов utf-16. Я не проверял, но я представляю, что удушающий проводник Проводника в равной степени посвящен, что сделает эту функцию совершенно бесполезной для программного обеспечения, имеющего других пользователей, кроме вас (с другой стороны, вы можете предпочесть, чтобы ваш программный дроссель не хорил).

Существует старая переменная с именем PATH_MAX, которая звучит многообещающе, но проблема в том, что PATH_MAX просто не .

В заключение приведем несколько идей о возможных способах кодирования решения.

  1. Используйте определения для создания разделов, специфичных для ОС. ( Qt может помочь вам с этим )
  2. Используйте рекомендации, приведенные на странице поддержки, а также документацию по ОС и файловой системе, чтобы определить недопустимых символов
  3. Что касается длины пути, единственная работоспособная идея, которая возникает у меня в голове, - это пробное двоичное дерево, подход с ошибкой, использующий обработку ошибок системного вызова для проверки допустимой длины пути. Это довольно в стороне, но может быть единственной возможностью получить точные результаты на различных системах.
  4. Удачи в элегантной обработке ошибок.

Надеюсь, это дало некоторые идеи.

3 голосов
/ 14 июня 2010

Я не думаю, что Qt имеет встроенную функцию, но если Boost является опцией, вы можете использовать функции name_check Boost.Filesystem .

Если Boost нетопция, ее страница о функциях name_check все еще является хорошим обзором того, что проверять на различных платформах.

2 голосов
/ 24 июля 2017

На основании ответа пользователя User7116 здесь:

Как проверить, является ли данная строка допустимым / действительным именем файла в Windows?

Я перестал быть ленивым -искал элегантные решения и просто закодировал его.Я получил:

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;
}

Особенности:

  • Вероятно, быстрее, чем использование регулярных выражений
  • Проверяет недопустимые символы и исключает имена устройств (обратите внимание, что '\' ненедопустимо, поскольку оно может быть в именах путей)
  • Разрешить буквы дисков
  • Разрешить полные имена путей
  • Разрешить имена сетевых путей
  • Разрешить что-либо после \\? \ (необработанные имена файлов)
  • Запрещает все, что начинается с \\. \ (необработанные имена устройств)
  • Запрещает имена, заканчивающиеся на "\" (то есть имена каталогов)
  • Запрещает имена длиннее 260 символов, не начинающиеся с \\? \
  • Запрещает завершающие пробелы и периоды

Обратите внимание, что он не проверяет длину имен файлов, начинающихся с \\? \,так как это не жесткое и быстрое правило.Также обратите внимание, что, как указано здесь , имена, содержащие множественные обратные и прямые косые черты, НЕ отклоняются API win32.

1 голос
/ 12 июня 2014
1 голос
/ 14 июня 2010

Трудно сделать надежно в Windows (некоторые странные вещи, такие как файл с именем "com", по-прежнему недействителен), и вы хотите обрабатывать юникод или трюки с подстановками, чтобы разрешить имя файла> 260 символов.Здесь уже есть хороший ответ Как проверить, является ли данная строка допустимым / допустимым именем файла в Windows?

0 голосов
/ 14 июня 2010

Я бы просто создал простую функцию для проверки имени файла для платформы, которая просто ищет в строке любые недопустимые символы.Не думайте, что в Qt есть встроенная функция.Вы можете использовать #ifdefs внутри функции, чтобы определить, на какой платформе вы находитесь.Достаточно чисто, я бы сказал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...