1

我需要比较 2 个文件,如果它们相同则返回 1,否则返回 0,但函数总是返回 0。我不知道为什么。也许你知道可以做到这一点的不同功能。

int compare(char *file_1, char *file_2)
{
    FILE *data_1 = fopen(file_1,"r");
    FILE *data_2 = fopen(file_2,"r");
    char line1[1000];
    char line2[1000];
    while(fgets(line1, sizeof(line1), data_1)&&fgets(line2, sizeof(line2), data_2)){
        if(strcmp(line1,line2)==0){
          fclose(data_1);
          fclose(data_2);
          return 0;
        }
    }
    fclose(data_1);
    fclose(data_2);
    return 1;
}
4

6 回答 6

4

strcmp(line1,line2)==0表示line1line2相等,您的代码假设它们不同

还有一个错误,如果一个文件以另一个文件的内容开头,你认为文件是相等的(假设你更正了strcmp


我鼓励您检查fopen的结果,以防其中至少一个不存在/无法打开


解决方案可以是:

int compare(char *file_1, char *file_2)
{
  FILE *fp1 = fopen(file_1,"r");

  if (fp1 == 0)
    return 0;

  FILE *fp2 = fopen(file_2,"r");

  if (fp2 == 0) {
    fclose(fp1);
    return 0;
  }

  char line1[1000];
  char line2[1000];
  char * r1, * r2;
  int result;

  for (;;) {
    r1 = fgets(line1, sizeof(line1), fp1);
    r2 = fgets(line2, sizeof(line2), fp2);

    if ((r1 == 0) || (r2 == 0)) {
      result = (r1 == r2);
      break;
    }

    if (strcmp(line1,line2) != 0) {
      result = 0;
      break;
    }
  }

  fclose(fp1);
  fclose(fp2);

  return result;
}
于 2019-01-09T11:40:03.100 回答
1

有关比较文件的其他问题尚未包含在答案中

文件数据与'\0'

如果文件包含null 字符fgets()将像读取任何其他非行尾字符一样读取该字符。然后下面strcmp()不会比较所有已读取的行。最好使用fread()/memcmp()来避免这个缺点。

比较为文本还是二进制?

"r"使用as in打开文件fopen(file_1,"r")允许进行各种翻译:行尾、文件尾、字节顺序标记。

打开 with 与text"r"进行比较是有意义的。否则,以二进制模式打开文件。在任何一种情况下使用。"rb"fread()

一个"\r\n"文件中的一行文本和另一个文件中的一行文本在文本"\n"模式下可以比较相等,但在二进制模式下不同。

由于帖子被标记为 [linux],因此在文本模式下不需要翻译。

不可比

在读取期间,可能会出现输入错误,从而使比较没有意义。


示例比较代码

#include <stdbool.h>
#include <stdio.h>
#define FILE_COMPARE_N 1024

// 1: match
// 0: mis-match
// -1: failure
int stream_compare(FILE *f1, FILE *f2) {
  unsigned char buf1[FILE_COMPARE_N];
  unsigned char buf2[FILE_COMPARE_N];
  size_t l1, l2;
  do {
    l1 = fread(buf1, sizeof buf1[0], FILE_COMPARE_N, f1);
    if (ferror(f1))
      return -1;

    l2 = fread(buf2, sizeof buf2[0], FILE_COMPARE_N, f2);
    if (ferror(f2))
      return -1;

    if (l1 != l2 || memcmp(buf1, buf2, l1) != 0)
      return 0; // mis-match

  } while (l1);
  return 1; //match
}

int file_compare(const char *name1, const char *name2, bool as_text) {
  FILE *f1 = fopen(name1, as_text ? "rb" : "r");
  if (f1 == NULL)
    return -1;

  FILE *f2 = fopen(name2, as_text ? "rb" : "r");
  if (f2 == NULL) {
    fclose(f1);
    return -1;
  }

  int compare = stream_compare(f1, f2);

  fclose(f1);
  fclose(f2);
  return compare;
}
于 2019-01-09T16:20:36.887 回答
1

您可以逐个字符(或逐个字节)比较文件以获得更快的结果,以防文件不相等:

int compare(char *file_1, char *file_2)
{
    FILE *data_1 = fopen(file_1,"r");
    FILE *data_2 = fopen(file_2,"r");
    int ch1, ch2;
    for (;;) {
        ch1 = getc(data_1); 
        ch2 = getc(data_2); 

        if ((ch1 != ch2) || (ch1 == EOF)) break;
    }

    fclose(data_1);
    fclose(data_2);

    return (ch1 == ch2);
}
于 2019-01-09T12:43:32.900 回答
1

这是解决方案,一个字符一个字符的读取/比较(灵感来自 myxaxa 的答案,但有错误修复)和另一个逐块读取/比较。由于懒惰,错误检查已被跳过,但一个健壮的实现必须有错误检查。(看评论)

#include <stdio.h>

int main(int argc, char **argv)
{
    int equal = 1;

    // TODO: check argc == 3

    FILE *data_1 = fopen(argv[1],"r");
    FILE *data_2 = fopen(argv[2],"r");

    // TODO: check data_1 and data_2 !=NULL

    for (;;)
      {
        int ch1, ch2;
        ch1 = fgetc(data_1); 
        ch2 = fgetc(data_2); 

        if (ch1 != ch2)
         { 
           equal = 0;
           break;
         }
        // We only need to test ch1, because at this point ch1 == ch2;   
        if (ch1 == EOF)
          break;
      }

    // TODO: check for read errors in data_1 and data_2 using ferror

    fclose(data_1);
    fclose(data_2);

    if (equal)
      printf("equal\n");
    else
      printf("not equal\n");
}

使用块读取/比较的第二种解决方案:

#include <stdio.h>
#include <string.h>

#define BUFFSIZE 4096

int main(int argc, char **argv)
{
    int equal = 1;

    // TODO: check argc == 3

    FILE *data_1 = fopen(argv[1],"r");
    FILE *data_2 = fopen(argv[2],"r");

    // TODO: check data_1 and data_2 !=NULL

    for (;;)
      {
        char b1[BUFFSIZE];
        char b2[BUFFSIZE];

        size_t r1 = fread(b1, 1, BUFFSIZE, data_1); 
        size_t r2 = fread(b2, 1, BUFFSIZE, data_2);

        if (r1 != r2)
          {
            equal = 0;
            break;
          }

        // We only need to test r1, because at this point r1 == r2;   
        if (r1 == 0)
          break;
        if (memcmp(b1, b2, r1) != 0)
          { 
            equal = 0;
            break;
          }
      }

    // TODO: check for read errors in data_1 and data_2 using ferror 

    fclose(data_1);
    fclose(data_2);

    if (equal)
      printf("equal\n");
    else
      printf("not equal\n");
}

与自身相比,840Mb 文件上的 char by char 读取/比较的运行时间:

real    0m5.158s
user    0m4.880s
sys     0m0.277s

...并在同一个文件上逐块:

real    0m0.353s
user    0m0.083s
sys     0m0.270s

两个测试都进行了多次运行以确保文件已被缓存

于 2019-01-09T14:15:52.507 回答
0

好吧,如果这些文件不是很大,一个好的方法是这样的:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>

void fileExistence( const char *fileName );
char *readFile( const char *const fileName  );
size_t getFileSize ( FILE *const file );

int main ( void )
{
    const char *const file_1 = "file1.txt";
    const char *const file_2 = "file2.txt";

    char *const getFile_01 = readFile( file_1 );
    char *const getFile_02 = readFile( file_2 );

    if (strcmp( getFile_01, getFile_02 ) == 0 )
    {
        printf( "Files are the same\n" );
    }else
    {
        printf( "Files are not the same\n" );
    }

    free( getFile_01 );
    free( getFile_02 );

    return 0;
}

char *readFile( const char *const fName )
{
    fileExistence( fName );
    size_t size, length;
    char *buffer;
    FILE *file = fopen ( fName , "rb" );
    if ( file == NULL )
    {
        fprintf( stderr, "Can't open output file %s!\n", fName );
        exit( EXIT_FAILURE );
    }

    length = getFileSize( file );
    if ( length == 0 )
    {
        printf( "Error, getFileSize()\n" );
    }

    buffer = malloc( length + 1 );
    if ( buffer == NULL ){
        printf( "Error, malloc().\n" );
        exit( EXIT_FAILURE );
    }

    size = fread ( buffer , 1 , length, file );
    if ( size != length ){
        printf( "Error, fread().\n" );
        exit( EXIT_FAILURE );
    }

    buffer[length] = '\0';
    fclose ( file );
    return buffer;
}

size_t getFileSize ( FILE *const file )
{
    int fsk = fseek ( file , 0 , SEEK_END );
    if ( fsk == -1 )
    {
        printf( "Error, fseek()\n" );
        return 0;
    }
    long tel = ftell( file );

    if ( tel < 0 || (unsigned long) tel >= SIZE_MAX )
    {
        printf( "Error, ftell()\n" );
        return 0;
    }

    fsk = fseek (file , 0 , SEEK_SET );
    if ( fsk == -1 )
    {
        printf( "Error, fseek()\n" );
        return 0;
    }
    return ( size_t )tel;
}

void fileExistence( const char *const fileName )
{
    if( access(fileName, F_OK ) )
    {
        printf("The File %s\t not Found\n",fileName);
        exit( EXIT_FAILURE );
    }

    if( access(fileName, R_OK ) )
    {
        printf("The File %s\t cannot be readed\n",fileName);
        exit( EXIT_FAILURE );
    }

    if( access( fileName, W_OK ) )
    {
        printf("The File %s\t it cannot be Edited\n",fileName);
        exit( EXIT_FAILURE );
    }
}

您读取两个文件并将它们保存在两个缓冲区中并用于strcmp()比较它们的位置。

如果您需要比较没有大写的文件,您可以使用strcasecmp()strings.h

于 2019-01-09T12:22:49.950 回答
0

Try reading whole file in one go, the loop will run until whole of the file is read and If it matches once, it will always going to return 0. Get the file size something like this and use malloc and read>

fseek(fp, 0, SEEK_END); 
size = ftell(fp);
fseek(fp, 0, SEEK_SET); 
于 2019-01-09T11:55:02.267 回答