c++ 判断两个字符串或二进制文件是否不同的最快方法是什么?

of1yzvn4  于 11个月前  发布在  其他
关注(0)|答案(5)|浏览(109)

我正在编写一个单元测试,需要将结果文件与黄金文件进行比较。最简单的方法是什么?
到目前为止,我已经(对于Linux环境):

int result = system("diff file1 file2");

字符串
如果result != 0,它们就不同。

z9gpfhce

z9gpfhce1#

这可能有点大材小用,但你可以使用boost/bimap和boost/scope_exit来构建一个SHA-256哈希表。
以下是Stephan T Lavavej制作的视频(从8.15开始):http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Advanced-STL/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-5-of-n
有关算法的更多信息:http://en.wikipedia.org/wiki/SHA-2

r3i60tvu

r3i60tvu2#

如果你想要一个纯c++的解决方案,我会这样做

#include <algorithm>
#include <iterator>
#include <string>
#include <fstream>

template<typename InputIterator1, typename InputIterator2>
bool
range_equal(InputIterator1 first1, InputIterator1 last1,
        InputIterator2 first2, InputIterator2 last2)
{
    while(first1 != last1 && first2 != last2)
    {
        if(*first1 != *first2) return false;
        ++first1;
        ++first2;
    }
    return (first1 == last1) && (first2 == last2);
}

bool compare_files(const std::string& filename1, const std::string& filename2)
{
    std::ifstream file1(filename1);
    std::ifstream file2(filename2);

    std::istreambuf_iterator<char> begin1(file1);
    std::istreambuf_iterator<char> begin2(file2);

    std::istreambuf_iterator<char> end;

    return range_equal(begin1, end, begin2, end);
}

字符串
它避免了将整个文件阅读到内存中,并且在文件不相同时(或在文件结束时)立即停止。range_equal是因为std::equal不接受第二个范围的迭代器对,并且如果第二个范围更短,则不安全。

o2gm4chl

o2gm4chl3#

DaveS's answer发展而来,首先是checking file size

#include <fstream>
#include <algorithm>

bool compare_files(const std::string& filename1, const std::string& filename2)
{
    std::ifstream file1(filename1, std::ifstream::ate | std::ifstream::binary); //open file at the end
    std::ifstream file2(filename2, std::ifstream::ate | std::ifstream::binary); //open file at the end
    const std::ifstream::pos_type fileSize = file1.tellg();

    if (fileSize != file2.tellg()) {
        return false; //different file size
    }

    file1.seekg(0); //rewind
    file2.seekg(0); //rewind

    std::istreambuf_iterator<char> begin1(file1);
    std::istreambuf_iterator<char> begin2(file2);

    return std::equal(begin1,std::istreambuf_iterator<char>(),begin2); //Second argument is end-of-range iterator
}

字符串
(我想知道在倒回之前,fileSize是否可以用来创建一个更有效的流结束迭代器,通过知道流长度,这将允许std::equal在同一时间处理更多的字节)。

7xllpg7q

7xllpg7q4#

一种防止阅读两个文件的方法是预先计算黄金文件到一个散列,例如md5。然后你只需要检查测试文件。注意,这可能比仅仅阅读两个文件慢!
或者,分层检查-查看文件大小,如果它们不同,则文件不同,您可以避免冗长的读取和比较操作。

1aaf6o9v

1aaf6o9v5#

这应该可以:

#include <string>
#include <fstream>
#include <streambuf>
#include <iterator>

bool equal_files(const std::string& a, const std::string& b) {
  std::ifstream stream{a};
  std::string file1{std::istreambuf_iterator<char>(stream),
                    std::istreambuf_iterator<char>()};
  
  stream = std::ifstream{b};
  std::string file2{std::istreambuf_iterator<char>(stream),
                    std::istreambuf_iterator<char>()};
  
  return file1 == file2;
}

字符串
我怀疑它没有diff那么快,但它避免了调用system,不过对于测试用例来说应该足够了。

相关问题