如何在 C++ 中递归查找具有 Unicode 名称的文件?

Posted

技术标签:

【中文标题】如何在 C++ 中递归查找具有 Unicode 名称的文件?【英文标题】:How recursively find files with Unicode names in C++? 【发布时间】:2017-04-10 17:37:11 【问题描述】:

我从here找到并修改了解决方案:

#include <iostream>
#include <windows.h>
#include <vector>
#include <fstream>

using namespace std;

//wofstream out;

void FindFile(const std::wstring &directory)

    std::wcout << endl << endl << endl << "FindFile(" << directory << ")" << std::endl;

    std::wstring tmp = directory + L"\\*";
    WIN32_FIND_DATAW file;
    HANDLE search_handle = FindFirstFileW(tmp.c_str(), &file);
    if (search_handle != INVALID_HANDLE_VALUE)
    
        std::vector<std::wstring> directories;

        do
        
            std::wcout << std::endl;
            std::wcout << "    [" << file.cFileName << "]" << std::endl;
            tmp = directory + L"\\" + std::wstring(file.cFileName);

            if (file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            
                if ((!lstrcmpW(file.cFileName, L".")) || (!lstrcmpW(file.cFileName, L".."))) 
                    std::wcout << "continuing..." << std::endl;
                
                else 
                    std::wcout << "saving path to this directory" << std::endl;
                    directories.push_back(tmp);
                
             else 
                std::wcout << "save [" << tmp << "] as file" << std::endl;
            

            //std::wcout << tmp << std::endl;
            //out << tmp << std::endl;
        
        while (FindNextFileW(search_handle, &file));

        std::wcout << "all items inside current directory was worked out. close it's handle." << std::endl;
        FindClose(search_handle);

        for(std::vector<std::wstring>::iterator iter = directories.begin(), end = directories.end(); iter != end; ++iter) 
            std::wcout << "recursively find in next directory: [" << *iter << "]" << std::endl;
            FindFile(*iter);
        
     else 
        std::wcout << "invalid handle value" << std::endl;
    


int main()

    //out.open("C:\\temp\\found.txt");

    FindFile(L"C:\\test");

    //out.close();

    cout << "The end" << endl;
    string str;
    cin >> str;

    return 0;

但此代码不适用于具有西里尔名称的文件夹或文件(但我使用所有类型和功能的 Unicode 版本!)

更新:应用程序刚刚完成,没有任何异常,好像所有命令都已执行。

Update-2(打印屏幕):

谁有同样的问题?感谢您的帮助。

已解决 非常感谢@zett42! 经过一些重构工作代码看起来像:

#include <iostream>
#include <windows.h>
#include <vector>
#include <fstream>
#include <io.h>
#include <fcntl.h>

using namespace std;

vector<wstring> FindFiles(const std::wstring &directory) 
    vector<wstring> files;
    std::vector<std::wstring> directories;

    std::wstring fullPath = directory + L"\\*";
    WIN32_FIND_DATAW file;
    HANDLE search_handle = FindFirstFileW(fullPath.c_str(), &file);

    if (search_handle == INVALID_HANDLE_VALUE)
        return files;

    do
    
        fullPath = directory + L"\\" + std::wstring(file.cFileName);

        if (!(file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
            files.push_back(fullPath);
        else 
            if ((lstrcmpW(file.cFileName, L".")) && (lstrcmpW(file.cFileName, L"..")))
                directories.push_back(fullPath);
        
    
    while (FindNextFileW(search_handle, &file));

    FindClose(search_handle);

    for(std::vector<std::wstring>::iterator iter = directories.begin(), end = directories.end(); iter != end; ++iter) 
        vector<wstring> newFiles = FindFiles(*iter);
        files.insert(files.begin(), newFiles.begin(), newFiles.end());
    

    return files;


int main()

    _setmode( _fileno(stdout), _O_U16TEXT );

    vector<wstring> files = FindFiles(L"E:\\test");

    wcout << L"All found files: " << endl;
    for (int i = 0; i < files.size(); ++i)
        wcout << files[i] << endl;

    cout << "The end" << endl;
    string str;
    cin >> str;

    return 0;

【问题讨论】:

"...但是这段代码不起作用..." 你能解释一下吗?它会跳过它们吗?你看到它们的名字有错吗?程序崩溃了? 没有。应用程序刚刚完成,没有任何错误。 (谢谢,@RichardCritten) FindFirstFileWFindNextFileW 添加一些错误检查,如果它们失败,则输出GetLastError 的结果。还要调试您的程序并单步执行它 - 实际上是第一次调试。 std::wcout &lt;&lt; "invalid handle value" &lt;&lt; std::endl; 和其他类似的行在我看来是错误的。 @RichardCritten:可能是这样,但调用了const void* 模板特化。无论如何,那些应该是宽字符串文字,例如wcout &lt;&lt; L"save [" &lt;&lt; ...;. 【参考方案1】:

在 Windows 上,默认情况下无法将 Unicode 输出到控制台,即使您使用 std::wcout

要使其正常工作,请在程序开头插入以下行:

_setmode( _fileno(stdout), _O_U16TEXT );

_setmode_fileno 是 Microsoft 特定功能。

您可能还需要更改控制台字体。我正在使用 Lucida Console,它适用于西里尔字母。

完整示例:

#include <iostream>
#include <io.h>      // _setmode()
#include <fcntl.h>   // _O_U16TEXT

int main()

    // Windows needs a little non-standard magic for Unicode console output.
    _setmode( _fileno(stdout), _O_U16TEXT );

    std::wcout << L"по русски\n";

由于 Unicode 字符串文字,示例应保存为 UTF-8 编码文件,但这与您的情况无关,因为您没有 Unicode 字符串文字。

我已经在Win10的MSVC2015和MSVC2017下成功测试了这段代码。

【讨论】:

好的,谢谢!)我现在会尝试这样做,并让您知道结果:) 但是,我的目标是获取“vector files”中的所有路径,而不是将它们打印到控制台。 @V.Panchenko 我看不出你的代码有什么问题。我认为这只是一个输出问题。 您想“获取”路径吗? “得到”是什么意思?你想把它们放到一个向量中吗?将它们写入文件?在树林里追捕他们?什么? @Dan 您可以看到 OP 不是以英语为母语的人,但即使我知道 OP 想要 add 指向向量的路径。这就是他目前在代码中所做的事情。 @zett42,我解决了!代码块有STDOUT_FILENO 宏,_O_U16TEXT 可以替换为0x20000 :)

以上是关于如何在 C++ 中递归查找具有 Unicode 名称的文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在给定路径下查找具有与递归精确模式匹配的位置的目录名称列表[重复]

如何递归地查找具有文本模式的文件,不包括某些目录和文件[重复]

使用 boost 和标准 C++ 的 Unicode 安全查找

Linux递归查找具有给定字符串的文件名[重复]

如何在Android源码里查找Java中native方法对应的C++实现

java中如何输出字符变量的Unicode编码值