【问题标题】:Comparing 2 directories using C++ in Visual Studio Express在 Visual Studio Express 中使用 C++ 比较 2 个目录
【发布时间】:2015-08-22 14:44:40
【问题描述】:

早安,

我有一个参考目录和一个目录。我想根据我的参考目录比较目录。比较两个文件夹的内容。我将如何编码?请帮忙。 对你的帮助表示感谢。提前致谢。 Bdw,我在 Visual Studio Express 中使用 C++。

【问题讨论】:

  • 这个问题很不清楚。但一般来说,C++ 标准库还不支持目录操作,但它来了。同时,Visual C++ 支持尚未标准的功能,参见例如(cpprocks.com/introduction-to-tr2-filesystem-library-in-vs2012)。或者您可以使用Boost filesystem library,这可能会提高可移植性。
  • 在哪一部分你觉得不清楚?
  • 首先不清楚比较是什么意思。你可以让一个智能实体比较两件事,他/她/它会看着并告诉你观察到的最显着的差异。但是计算机程序做了一些非常具体的事情,在这种情况下是什么?其次,关于“如何”,我怀疑即使“什么”很清楚,也会有无数种可能的方法来做到这一点,而且它们都不是特定于 C++ 的。我的第一条评论是引导您了解可能相关的(即将推出的)标准库功能。毕竟,您肯定需要目录信息。

标签: c++ file visual-studio-2013 directory folderbrowserdialog


【解决方案1】:

对于 C++/CLI:

我们需要#include <vcclr.h> 来转换 C++ 字符串和 CLI 字符串。更改为以下内容:

#include <vector> 
#include <string> 
#include <windows.h>

int get_files_and_folders(std::wstring dir, std::vector<std::wstring> &fullpath, std::vector<int> &filesize)
{
    if (!dir.size()) return 0;
    if (dir[dir.size() - 1] != '\\') dir += L"\\";

    WIN32_FIND_DATA find = { 0 };
    std::wstring wildcard = dir + L"*";
    HANDLE hfind = FindFirstFile(wildcard.c_str(), &find);
    if (hfind == INVALID_HANDLE_VALUE)
        return 0;

    do
    {
        std::wstring filename = find.cFileName;
        if (filename == L"." || filename == L"..")
            continue;
        std::wstring path = dir + filename;
        fullpath.push_back(path);
        filesize.push_back(find.nFileSizeLow);

        if (find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            get_files_and_folders(path, fullpath, filesize);

    } while (FindNextFile(hfind, &find));

    FindClose(hfind);
    return 1;
}

int compare_folders(std::wstring &dir1, std::wstring &dir2, std::wstring &result)
{
    std::vector<int> filesize1, filesize2;
    std::vector<std::wstring> path1, path2;

    if (!get_files_and_folders(dir1, path1, filesize1)) return 0;
    if (!get_files_and_folders(dir2, path2, filesize2)) return 0;

    //test
    for (unsigned i = 0; i < path1.size(); i++)
    {
        System::String^ s = gcnew System::String(path1[i].c_str());
        System::Diagnostics::Trace::WriteLine(s);
    }

    if (path1.size() != path2.size())
    {
        result += L"file + folder count doesn't match\n";
        return 0;
    }

    for (unsigned i = 0; i < path1.size(); i++)
    {
        std::wstring filename1 = path1[i];
        std::wstring filename2 = path2[i];

        filename1.erase(0, dir1.size() + 1);
        filename2.erase(0, dir2.size() + 1);
        if (filename1 != filename2)
        {
            result += L"filename doesn't match\n";
            return 0;
        }

        if (filesize1[i] != filesize2[i])
        {
            result += L"filesize doesn't match\n";
            return 0;
        }

        //todo:
        //open file by fullpath name and compare each bit by bit...?
    }

    result = L"match found\n";
    return 1;
}

现在您可以从 CLI 调用该函数

//In C++/CLI form: 
#include <vcclr.h>
String^ str1 = L"c:\\test1";
String^ str2 = L"c:\\test2";

//convert strings from CLI to C++
pin_ptr<const wchar_t> dir1 = PtrToStringChars(str1);
pin_ptr<const wchar_t> dir2 = PtrToStringChars(str2);
std::wstring result;

compare_folders(std::wstring(dir1), std::wstring(dir2), result);

//convert strings from C++ to CLI
System::String^ str = gcnew System::String(result.c_str());
MessageBox::Show(str);

ps,在前面的示例中,我包含了 using namespace std;,但它不应该出现在 Forms 中。

【讨论】:

  • 为什么不在 C++ 级别而不是 C 级别编写代码,因为问题标记为 C++。另外,请注意,如上所述,使用基于char 的 API 函数在许多情况下会给您带来错误的操作,因为这些函数使用 Windows ANSI 编码,它无法表示所有文件和目录名称。最后,最好使用 C++ 文件系统功能而不是 Windows API。
  • 提示:不要在程序末尾添加pause。从命令行运行程序时非常烦人。当您从例如运行程序时不需要它。 Visual Studio(例如通过Ctrl+F5)。简而言之,它没有积极的好处,但它确实有一些缺点。所以它非常愚蠢,是一种反模式,一种不应该传播的邪恶模因,尤其是不应该传播给初学者。
  • @Cheersandhth.-Alf 我正在使用std::vectorsstd::string。在其他地方,WinApi 具有 C 风格的功能,我不想无缘无故地强制 C++。我还需要system("pause") 从 VS IDE 进行调试,否则控制台会立即关闭。如果其他人正在做其他事情,他们可以删除暂停。
  • Re system("pause"),为了调试,只需在 main 的最后一个右大括号上放置一个断点。这真的是一种反模式,一种邪恶的模因。我没有提到它是不可移植的,因为这是一个 Windows 程序,但作为一般的反模式,也有这个方面。这完全是坏的,没有什么好。 Just Don't Teach It™(您可以在将代码发布到 SO 之前将其删除)。
  • @Cheersandhth.-Alf,好的,我删除了它。
猜你喜欢
  • 2013-10-12
  • 2018-09-19
  • 2017-12-09
  • 2021-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
相关资源
最近更新 更多