使用 Qt 检查字符串是否是有效的文件名

发布于 2024-09-05 05:18:24 字数 415 浏览 2 评论 0原文

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内置函数?

我想避免创建空文件,但如果没有其他可靠的方法,我仍然想看看如何以“干净”的方式做到这一点。

非常感谢。

Is there a way with Qt 4.6 to check if a given QString is a valid filename (or directory name) on the current operating system ? I want to check for the name to be valid, not for the file to exist.

Examples:

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

How would I achieve this ? Is there some Qt built-in function ?

I'd like to avoid creating an empty file, but if there is no other reliable way, I would still like to see how to do it in a "clean" way.

Many thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

魂ガ小子 2024-09-12 05:18:24

这是我从 Trolltech ASA 支持工程师 Silje Johansen 那里得到的答案(不过是在 2008 年 3 月)

但是。包括区域设置和查找的复杂性
查询 Linux/Unix 上文件系统的统一方法
功能几乎是不可能的。

但是,据我所知,我所知道的所有应用程序都忽略了这一点
问题。

(阅读:他们不会实现它)

Boost 也没有解决问题,他们只给出了路径最大长度的一些模糊概念,特别是如果你想跨平台的话。据我所知,很多人都尝试过解决这个问题,但都失败了(至少在理论上,在实践中,绝对有可能编写一个在大多数情况下创建有效文件名的程序。

如果你想自己实现这一点,可能值得考虑一些不是立即显而易见的事情,例如:

无效字符的并发症

文件系统限制与操作系统和软件限制之间的区别,我认为这是文件系统限制的一部分。例如,Windows 操作系统不完全支持 NTFS。包含“:”和“?”等的文件可以愉快地驻留在 ntfs 分区上,但资源管理器只会卡住它们。除此之外,您可以安全地使用它们。来自 Boost 文件系统的建议

。路径长度

升压页面没有完全解决的第二个问题是完整路径的长度,目前唯一确定的是没有操作系统/文件系统组合支持不确定的路径长度。但是,诸如“Windows 最大路径限制为 260 个字符”之类的说法是错误的。 Windows 中的 unicode API 允许您创建最长 32,767 个 utf-16 字符的路径。我没有检查过,但我想象资源管理器同样会窒息,这将使该功能对于除您之外的任何用户的软件完全无用(另一方面,您可能不希望让您的软件齐声窒息)。

存在一个名为 PATH_MAX 的旧变量,这听起来很有希望,但问题是 PATH_MAX 根本就不是

最后,以建设性的意见结束,这里有一些关于编写解决方案的可能方法的想法。

  1. 使用定义来创建操作系统特定的部分。 (Qt 可以帮助您实现这一点
  2. 使用 boost 页面上给出的建议并操作系统和文件系统文档来决定非法字符
  3. 对于路径长度,我想到的唯一可行的想法是二叉树尝试一种错误方法,使用系统调用的错误处理来检查有效的路径长度。这是相当遥远的,但可能是在各种系统上获得准确结果的唯一可能性。
  4. 擅长优雅的错误处理。

希望这能提供一些见解。

This is the answer I got from Silje Johansen - Support Engineer - Trolltech ASA (in March 2008 though)

However. the complexity of including locale settings and finding
a unified way to query the filesystems on Linux/Unix about their
functionality is close to impossible.

However, to my knowledge, all applications I know of ignore this
problem.

(read: they aren't going to implement it)

Boost doesn't solve the problem either, they give only some vague notion of the maximum length of paths, especially if you want to be cross platform. As far as I know many have tried and failed to crack this problem (at least in theory, in practice it is most definitely possible to write a program that creates valid filenames in most cases.

If you want to implement this yourself, it might be worth considering a few not immediately obvious things such as:

Complications with invalid characters

The difference between file system limitations and OS and software limitations. Windows Explorer, which I consider part of the Windows OS does not fully support NTFS for example. Files containing ':' and '?', etc... can happily reside on an ntfs partition, but Explorer just chokes on them. Other than that, you can play safe and use the recommendations from Boost Filesystem.

Complications with path length

The second problem not fully tackled by the boost page is length of the full path. Probably the only thing that is certain at this moment is that no OS/filesystem combination supports indefinite path lengths. However, statements like "Windows maximum paths are limited to 260 chars" are wrong. The unicode API from Windows does allow you to create paths up to 32,767 utf-16 characters long. I haven't checked, but I imagine Explorer choking equally devoted, which would make this feature utterly useless for software having any users other than yourself (on the other hand you might prefer not to have your software choke in chorus).

There exists an old variable that goes by the name of PATH_MAX, which sounds promising, but the problem is that PATH_MAX simply isn't.

To end with a constructive note, here are some ideas on possible ways to code a solution.

  1. Use defines to make OS specific sections. (Qt can help you with this)
  2. Use the advice given on the boost page and OS and filesystem documentation to decide on your illegal characters
  3. For path length the only workable idea that springs to my mind is a binary tree trial an error approach using the system call's error handling to check on a valid path length. This is quite aloof, but might be the only possibility of getting accurate results on a variety of systems.
  4. Get good at elegant error handling.

Hope this has given some insights.

与君绝 2024-09-12 05:18:24

基于 User7116 的回答:

How do我检查给定的字符串在 Windows 下是否是合法/有效的文件名?

我不再偷懒了 ​​- 寻找优雅的解决方案,然后对其进行编码。我得到:

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

    // 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& d, devices)
        if (basename == d)

            // Note: Names with ':' other than with a drive letter have already been rejected.
            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 个字符且不以 \\?\ 开头的名称
  • 不允许尾随空格和请

注意,它不会检查以 \\? 开头的文件名的长度,因为这不是一个硬性规定。另请注意,正如此处指出的,名称包含多个反斜杠win32 API 不会拒绝正斜杠。

Based on User7116's answer here:

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

I quit being lazy - looking for elegant solutions, and just coded it. I got:

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

    // 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& d, devices)
        if (basename == d)

            // Note: Names with ':' other than with a drive letter have already been rejected.
            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;
}

Features:

  • Probably faster than using regexes
  • Checks for illegal characters and excludes device names (note that '' is not illegal, since it can be in path names)
  • Allows drive letters
  • Allows full path names
  • Allows network path names
  • Allows anything after \\?\ (raw file names)
  • Disallows anything starting with \\.\ (raw device names)
  • Disallows names ending in "\" (i.e. directory names)
  • Disallows names longer than 260 characters not starting with \\?\
  • Disallows trailing spaces and periods

Note that it does not check the length of filenames starting with \\?, since that is not a hard and fast rule. Also note, as pointed out here, names containing multiple backslashes and forward slashes are NOT rejected by the win32 API.

一抹苦笑 2024-09-12 05:18:24

我不认为Qt有内置函数,但是如果Boost是一个选项,你可以使用Boost.Filesystem的 name_check 函数

如果 Boost 不是一个选项,它的 name_check 函数页面仍然很好地概述了在各种平台上检查的内容。

I don't think that Qt has a built-in function, but if Boost is an option, you can use Boost.Filesystem's name_check functions.

If Boost isn't an option, its page on name_check functions is still a good overview of what to check for on various platforms.

怀中猫帐中妖 2024-09-12 05:18:24

在 Windows 上很难可靠地完成(一些奇怪的事情,例如名为“com”的文件仍然无效),并且您是否想要处理 unicode,或者使用 subst 技巧来允许大于 260 个字符的文件名。

这里已经有一个很好的答案 如何如何检查给定的字符串在 Windows 下是否是合法/有效的文件名?

Difficult to do reliably on windows (some odd things such as a file named "com" still being invalid) and do you want to handle unicode, or subst tricks to allow a >260 char filename.

There is already a good answer here How do I check if a given string is a legal / valid file name under Windows?

太阳男子 2024-09-12 05:18:24

我只是创建一个简单的函数来验证平台的文件名,该函数只是在字符串中搜索任何无效字符。不要以为Qt中有内置函数。您可以在函数内使用#ifdefs 来确定您所在的平台。我想说足够干净。

I'd just create a simple function to validate the filename for the platform, which just searches through the string for any invalid characters. Don't think there's a built-in function in Qt. You could use #ifdefs inside the function to determine what platform you're on. Clean enough I'd say.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文