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

时间:2010-06-14 15:11:35

标签: c++ validation qt filesystems

是否有办法让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 个答案:

答案 0 :(得分:22)

这是我从Silje Johansen - 支持工程师 - Trolltech ASA(2008年3月)获得的答案

  

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

     

然而,据我所知,我所知道的所有应用都忽略了这一点   问题

(读:他们不打算实施它)

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

如果您想自己实现这一点,可能值得考虑一些不那么明显的事情,例如:

包含无效字符的并发症

文件系统限制与操作系统和软件限制之间的差异。 Windows资源管理器,我认为是Windows操作系统的一部分,并不完全支持NTFS。包含':'和'?'等的文件可以很好地驻留在ntfs分区上,但资源管理器只会阻塞它们。除此之外,您可以安全地玩并使用Boost Filesystem中的建议。

路径长度的并发症

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

存在一个名为PATH_MAX的旧变量,听起来很有希望,但问题是PATH_MAX simply isn't

以结构性的说明结尾,这里有一些关于编写解决方案的可能方法的想法。

  1. 使用定义来制作特定于操作系统的部分。 (Qt can help you with this
  2. 使用boost页面上提供的建议以及操作系统和文件系统文档来确定您的非法字符
  3. 对于路径长度,我想到的唯一可行的想法是二叉树试验,一种错误方法,使用系统调用的错误处理来检查有效的路径长度。这是非常冷漠,但可能是在各种系统上获得准确结果的唯一可能性。
  4. 擅长优雅的错误处理。
  5. 希望这有一些见解。

答案 1 :(得分:3)

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

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

答案 2 :(得分:2)

基于User7116的答案:

How do I check if a given string is a legal / valid file name under 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;
}

特点:

  • 可能比使用正则表达式更快
  • 检查非法字符并排除设备名称(注意&#39; \&#39;不是非法的,因为它可以在路径名中)
  • 允许使用驱动器号
  • 允许完整路径名称
  • 允许网络路径名称
  • 允许\\?\(原始文件名)
  • 之后的任何内容
  • 禁止以\\。\(原始设备名称)
  • 开头的任何内容
  • 禁止以&#34; \&#34;结尾的名称(即目录名称)
  • 禁止超过260个字符但不以\\?\
  • 开头的名称
  • 禁止尾随空格和句点

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

答案 3 :(得分:1)

难以在Windows上可靠地执行(某些奇怪的事情,例如名为“com”的文件仍然无效),您是否想要处理unicode或替代技巧以允许&gt; 260 char文件名。

这里已有一个很好的答案How do I check if a given string is a legal / valid file name under Windows?

答案 4 :(得分:1)

答案 5 :(得分:0)

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