【问题标题】:Search files with UNICODE names搜索具有 UNICODE 名称的文件
【发布时间】:2026-02-24 20:05:01
【问题描述】:

我尝试在编译成功后编译这个程序,它会在控制台窗口上打印程序的当前目录。 但是该程序的工作是向我展示所有带有 .doc 扩展名的文件,当我不使用宽字符串 wstring() 时它也可以正常工作。所以这是我想用 wstring 功能编译这个程序的问题。

更新:

此代码正常工作:

#define UNICODE
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
#include <windows.h>
#include <conio.h>

using namespace std;
/*
#define UNICODE
#define _UNICODE

typedef std::string UTF8String;
*/
int SearchDirectory(std::vector<std::string> &refvecFiles,
                    const std::string         &refcstrRootDirectory,
                    const std::string         &refcstrExtension,
                    bool                     bSearchSubdirectories = true)
{
  std::string      strFilePath;             // Filepath
  std::string      strPattern;              // Pattern
  std::string      strExtension;            // Extension
  HANDLE          hFile;                   // Handle to file
  WIN32_FIND_DATA FileInformation;         // File information


  strPattern = refcstrRootDirectory + "\\*.*";

  hFile = ::FindFirstFile(strPattern.c_str(), &FileInformation);
  if(hFile != INVALID_HANDLE_VALUE)
  {
    do
    {
      if(FileInformation.cFileName[0] != '.')
      {
        strFilePath.erase();
        strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;

        if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
          if(bSearchSubdirectories)
          {
            // Search subdirectory
            int iRC = SearchDirectory(refvecFiles,
                                      strFilePath,
                                      refcstrExtension,
                                      bSearchSubdirectories);
            if(iRC)
              return iRC;
          }
        }
        else
        {
          // Check extension
          strExtension = FileInformation.cFileName;
          strExtension = strExtension.substr(strExtension.rfind(".") + 1);

          if(strExtension == refcstrExtension)
          {
            // Save filename
            refvecFiles.push_back(strFilePath);
          }
        }
      }
    } while(::FindNextFile(hFile, &FileInformation) == TRUE);

    // Close handle
    ::FindClose(hFile);

    DWORD dwError = ::GetLastError();
    if(dwError != ERROR_NO_MORE_FILES)
      return dwError;
  }

  return 0;
}


// Prototype for conversion functions
std::wstring StringToWString(const std::string& s);
std::string WStringToString(const std::wstring& s);

std::wstring StringToWString(const std::string& s)
{
    std::wstring temp(s.length(),L' ');
    std::copy(s.begin(), s.end(), temp.begin());
    return temp;
}


std::string WStringToString(const std::wstring& s)
{
    std::string temp(s.length(), ' ');
    std::copy(s.begin(), s.end(), temp.begin());
    return temp;
}

int main()
{
  int                      iRC         = 0;
  std::vector<std::string > vecAviFiles;
  std::vector<std::string > vecTxtFiles;


  // Search 'c:' for '.avi' files including subdirectories
  iRC = SearchDirectory(vecAviFiles, "c:", "doc");
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }


// Print results
  for(std::vector<std::wstring>::iterator iterAvi = vecAviFiles.begin(); iterAvi != vecAviFiles.end(); ++iterAvi)
    std::wcout << *iterAvi << std::endl;

}

代码无效:

#include <string>
#include <vector>
#include <iostream>

#include <windows.h>
#include <conio.h>

int SearchDirectory(std::vector<std::wstring> &refvecFiles,
                    const std::wstring        &refcstrRootDirectory,
                    const std::wstring        &refcstrExtension,
                    bool                     bSearchSubdirectories = true)
{
  std::wstring     strFilePath;             // Filepath
  std::wstring     strPattern;              // Pattern
  std::wstring     strExtension;            // Extension
  HANDLE          hFile;                   // Handle to file
  WIN32_FIND_DATAW FileInformation;         // File information

  strPattern = refcstrRootDirectory + L"\\*.*";

  hFile = ::FindFirstFileW(strPattern.c_str(), &FileInformation);
  if(hFile != INVALID_HANDLE_VALUE)
  {
    do
    {
      if(FileInformation.cFileName[0] != '.')
      {
        strFilePath.erase();
        strFilePath = refcstrRootDirectory + L"\\" + FileInformation.cFileName;

        if(FileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
        {
          if(bSearchSubdirectories)
          {
            // Search subdirectory
            int iRC = SearchDirectory(refvecFiles,
                                      strFilePath,
                                      refcstrExtension,
                                      bSearchSubdirectories);
            if(iRC)
              return iRC;
          }
        }
        else
        {
          // Check extension
          strExtension = FileInformation.cFileName;
          strExtension = strExtension.substr(strExtension.rfind(L".") + 1);

          if(strExtension == refcstrExtension)
          {
            // Save filename
            refvecFiles.push_back(strFilePath);
          }
        }
      }
    } while(::FindNextFileW(hFile, &FileInformation) == TRUE);

    // Close handle
    ::FindClose(hFile);

    DWORD dwError = ::GetLastError();
    if(dwError != ERROR_NO_MORE_FILES)
      return dwError;
  }

  return 0;
}


int main()
{
  int                      iRC         = 0;
  std::vector<std::wstring> vecAviFiles;

  // Search 'c:' for '.avi' files including subdirectories
  iRC = SearchDirectory(vecAviFiles, L"c:", L"doc");
  if(iRC)
  {
    std::cout << "Error " << iRC << std::endl;
    return -1;
  }

  // Print results
  for(std::vector<std::wstring>::iterator iterAvi = vecAviFiles.begin(); iterAvi != vecAviFiles.end(); ++iterAvi)
    std::wcout << *iterAvi << std::endl;
}

我想知道为什么第二个程序不起作用?

【问题讨论】:

  • 那么你得到的错误是什么?
  • 首先:X:\C++\boost iterator\bin\Debug\ 进程返回 0 (0x0) 执行时间:12.165 s 按任意键继续。其次,这不是进程的当前目录:我会将 .doc 更改为另一个扩展名,这不是问题,问题是我无法获取具有 .doc(或 wathever)扩展名的文件的路径。
  • 您的代码非常适合我。我唯一的建议是在这里使用不区分大小写的字符串比较:strExtension == refcstrExtension
  • 你在控制台屏幕上得到了什么,它只显示第一个 .doc 文件所在的目录

标签: c++ file search unicode wstring


【解决方案1】:

你做错了™。

考虑strPattern = refcstrRootDirectory + L"\\*.*";*.* 的存在是有原因的。您可以在其中指定要查找的文件模式。如果您想查找*.doc 文件,请这样说:strPattern = refcstrRootDirectory + L"\\*." + refcstrExtension;

还有一些风格说明:

  • 删除类型前缀。这是弱类型语言中使用的约定; C++ 是强类型的。
  • 在需要的地方定义变量,而不是更早地定义:
    • std::wstring Pattern = RootDirectory + L"\\*.*";
    • HFILE File = ::FindFirstFileW(Pattern.c_str(), &amp;FileInformation);
  • 如果要分配新值,则无需删除字符串。例如。这很好用。
    • FilePath = RootDirectory + L"\\" + FileInformation.cFileName;
  • 检查这对没有扩展名的文件有什么作用。
  • 您正在泄漏if(iRC) return iRC; 中的文件句柄。 (C++ 对象会自动清理,但这是一个 C API)。

【讨论】: