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

时间:2017-04-10 17:37:11

标签: c++ winapi recursion unicode

我找到并修改了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版本!)

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

更新-2(打印屏幕): print-screen

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

解决 非常感谢@ 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;
}

1 个答案:

答案 0 :(得分:2)

在Windows上,即使您使用std::wcout,默认情况下,Unicode输出到控制台也不起作用。

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

_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下成功测试了此代码。