【问题标题】:How to skip the dot (.) and dotdot (..) in FindNextFileW? [duplicate]如何跳过 FindNextFileW 中的点 (.) 和点点 (..)? [复制]
【发布时间】:2019-10-28 13:30:35
【问题描述】:

我正在使用FindNextFileW 成功列出目录中的文件。问题是它使用. 引用自身,当前目录和.. 的父目录。我正在尝试使用 if 条件跳过这些,但它仍然会打印它们。

代码:

int wmain() {

WIN32_FIND_DATAW data;
std::wstring dir = L"c:\\* ";
HANDLE hFind = FindFirstFileW(dir.c_str(), &data);

if (hFind != INVALID_HANDLE_VALUE) {
    do {
        wchar_t dot[] = L"." ;
        wchar_t dotd[] = L"..";

        if ( data.cFileName != dot && data.cFileName != dotd)
        std::wcout << data.cFileName << std::endl;
    } while (FindNextFileW(hFind, &data));
    FindClose(hFind);
}
return 0;
}

如您所见,我试图通过使用if 条件来跳过... 的打印。但是,它仍然会打印它们。我做错了什么,我该如何解决?

编辑:

这个问题不是关于如何无法比较 wchar_t 数组。很高兴知道,但最终我的问题是关于如何跳过FindNextFileW 中的...。我已经尝试转换为std::wstring,但我可以定义:

std::wstring dot = '.';
std:wstring dotd = '..';

但是我如何对照cFilename检查它们?

【问题讨论】:

  • 任何类型的数组都无法与内置运算符进行比较。
  • SIZE_T FileNameLength = wcslen(data.cFileName); switch (FileNameLength) { case 2: if (data.cFileName[1] != '.') break; case 1: if (data.cFileName[0] == '.') continue; }
  • “这个问题不是关于如何无法比较 wchar_t 数组” 这正是它的意义所在。 wchar_t 数组包含的内容无关紧要,因此 FindNextFileW(以及一般的 Windows API)也无关紧要。分而治之。减少你的问题。
  • 多次重复。您可以通过执行字符串比较来跳过这些项目。

标签: c++ windows winapi


【解决方案1】:

您只是在比较指针,它们永远不会相同。 data.cFileName 不是 std::[w]string,它只是一个普通的 C 样式字符串。

您可以使用lstrcmpW(),但它们太短了,您甚至不必这样做,只需手动检查字符或使用辅助函数:

template<class T> bool IsDotOrDotDot(const T*s)
{
  if (s[0] == T('.'))
  {
    if (s[1] == T('\0')) return true; // .
    if (s[1] == T('.') && s[2] == T('\0')) return true; // ..
  }
  return false;
}

...

do {
  if (!IsDotOrDotDot(data.cFileName))
  {
    ...
  }
} while (...);

【讨论】:

  • 不确定当您的 char 类型被硬编码时模板的用途是什么,但其他方面很好。
【解决方案2】:

你可以这样做:

if (wcscmp (data.cFileName, dot) != 0 && wcscmp (data.cFileName, dotd) != 0)
    ...

还要注意:

wchar_t dot[] = L"." ;

应该是:

const wchar_t dot[] = L"." ;

dotd 也是如此。

如果使用 C++17,您可能还想查看std::filesystem

【讨论】:

  • 这里真的可以更高效的代码,对比一下strcmp,不过这样当然也ok
  • 为什么甚至 [] 而不是 *;不需要副本
  • 事实上,您可能想要采用在 Linux 上意外导致“隐藏文件”约定的快捷方式(尽管我知道这是针对 Windows),然后只需检查第一个字符是L'.'。不过,这取决于您需要做什么。
  • @LightnessRacesinOrbit Windows 允许目录和文件名以. 开头,我看到许多应用程序都利用了这一点,例如 Minecraft、TortoiseSVN 等
  • @RemyLebeau 您列出的应用程序肯定会像在 Linux 上一样使用前导 .(尽管这不是真正意义上的 Windows 约定;找到一个关心的本机工具关于领先.!)我的意思是,他们是否想在他们的应用程序中采用这个约定取决于OP;如果他们这样做了,他们可以大大简化这个逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-27
  • 2022-10-07
  • 1970-01-01
  • 2013-12-19
  • 2014-04-09
相关资源
最近更新 更多