比较两个文件

Chr*_*ris 10 c++

我正在尝试编写一个比较两个文件内容的函数.

我希望它在文件相同时返回1,如果不同则返回0.

ch1ch2作为缓冲区,我曾经fgets获取我的文件的内容.

我认为eof指针有问题,但我不确定.FILE变量在命令行中给出.

PS它适用于大小低于64KB的小文件,但不适用于较大的文件(例如700MB电影,或5MB的.mp3文件).

任何想法,如何解决?

int compareFile(FILE* file_compared, FILE* file_checked)
{
    bool diff = 0;
    int N = 65536;
    char* b1 = (char*) calloc (1, N+1);
    char* b2 = (char*) calloc (1, N+1);
    size_t s1, s2;

    do {
        s1 = fread(b1, 1, N, file_compared);
        s2 = fread(b2, 1, N, file_checked);

        if (s1 != s2 || memcmp(b1, b2, s1)) {
            diff = 1;
            break;
        }
      } while (!feof(file_compared) || !feof(file_checked));

    free(b1);
    free(b2);

    if (diff) return 0;
    else return 1;
}
Run Code Online (Sandbox Code Playgroud)

编辑:我已经通过包含你的答案改进了这个功能.但它只是比较第一个缓冲区 - >但有例外 - >我发现它停止读取文件,直到达到1A字符(附加文件).我们怎样才能让它发挥作用?

EDIT2:任务已解决(附加工作代码).感谢大家的帮助!

mtr*_*trw 19

如果你可以放弃一点速度,这是一种需要很少代码的C++方式:

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

bool compareFiles(const std::string& p1, const std::string& p2) {
  std::ifstream f1(p1, std::ifstream::binary|std::ifstream::ate);
  std::ifstream f2(p2, std::ifstream::binary|std::ifstream::ate);

  if (f1.fail() || f2.fail()) {
    return false; //file problem
  }

  if (f1.tellg() != f2.tellg()) {
    return false; //size mismatch
  }

  //seek back to beginning and use std::equal to compare contents
  f1.seekg(0, std::ifstream::beg);
  f2.seekg(0, std::ifstream::beg);
  return std::equal(std::istreambuf_iterator<char>(f1.rdbuf()),
                    std::istreambuf_iterator<char>(),
                    std::istreambuf_iterator<char>(f2.rdbuf()));
}
Run Code Online (Sandbox Code Playgroud)

通过使用istreambuf_iterators您将缓冲区大小选择,实际读取和跟踪eof推入标准库实现.std::equal当它遇到第一个不匹配时返回,所以这不应该超过它需要的时间.

这比Linux慢cmp,但它很容易阅读.


Geo*_*nis 9

当文件是二进制文件时,使用memcmp而不是strcmp,因为\ 0可能显示为数据.


Jas*_*son 8

由于您已经在堆栈上分配了数组,因此它们会被随机值填充......它们不会被清零.

其次,strcmp只会比较第一个NULL值,如果它是二进制文件,则不一定在文件的末尾.因此,您应该真正使用memcmp缓冲区.但同样,这会产生不可预测的结果,因为你的缓冲区是在堆栈上分配的,所以即使你比较相同的文件,缓冲区结束EOF可能也不一样,所以memcmp仍然会报告错误结果(即,由于缓冲区末尾的随机值超过每个相应文件的EOF,它很可能会报告文件不相同).

要解决这个问题,首先应该首先测量文件的长度,首先遍历文件并查看文件以字节为单位的时间,然后使用malloccalloc分配您要比较的缓冲区,并重新用实际文件的内容填充这些缓冲区.然后,您应该能够对每个文件的二进制内容进行有效比较.此时,您还可以使用大于64K的文件,因为您在运行时动态分配缓冲区.


jww*_*jww 8

这是一个C++解决方案.这似乎是合适的,因为您的问题被标记为C++.该程序使用ifstream的是s而不是FILE*s.它还向您展示了如何在文件流上进行搜索以确定文件的大小.最后,它一次读取4096个块,因此将按预期处理大文件.

// g++ -Wall -Wextra equifile.cpp -o equifile.exe

#include <iostream>
using std::cout;
using std::cerr;
using std::endl;

#include <fstream>
using std::ios;
using std::ifstream;

#include <exception>
using std::exception;

#include <cstring>
#include <cstdlib>
using std::exit;
using std::memcmp;

bool equalFiles(ifstream& in1, ifstream& in2);

int main(int argc, char* argv[])
{
    if(argc != 3)
    {
        cerr << "Usage: equifile.exe <file1> <file2>" << endl;
        exit(-1);
    }

    try {
        ifstream in1(argv[1], ios::binary);
        ifstream in2(argv[2], ios::binary);

        if(equalFiles(in1, in2)) {
            cout << "Files are equal" << endl;
            exit(0);
        }
        else
        {
            cout << "Files are not equal" << endl;
            exit(1);
        }

    } catch (const exception& ex) {
        cerr << ex.what() << endl;
        exit(-2);
    }

    return -3;
}

bool equalFiles(ifstream& in1, ifstream& in2)
{
    ifstream::pos_type size1, size2;

    size1 = in1.seekg(0, ifstream::end).tellg();
    in1.seekg(0, ifstream::beg);

    size2 = in2.seekg(0, ifstream::end).tellg();
    in2.seekg(0, ifstream::beg);

    if(size1 != size2)
        return false;

    static const size_t BLOCKSIZE = 4096;
    size_t remaining = size1;

    while(remaining)
    {
        char buffer1[BLOCKSIZE], buffer2[BLOCKSIZE];
        size_t size = std::min(BLOCKSIZE, remaining);

        in1.read(buffer1, size);
        in2.read(buffer2, size);

        if(0 != memcmp(buffer1, buffer2, size))
            return false;

        remaining -= size;
    }

    return true;
}
Run Code Online (Sandbox Code Playgroud)