2010-05-27 3 views
1

내용이 다른 경우 이진 파일을 교체하고 싶습니다.C#에서 이진 파일을 비교할 수 있습니까?

그래서 이진 파일을 비 직렬화 할 필요없이 비교할 수 있어야합니다.

이것이 가능합니까?

이진 포맷터를 사용하여 파일을 저장했습니다.

+0

당신은 질문을 명확히해야합니다 : 이진 파일을 무엇과 비교하고 있습니까?다른 바이너리 파일입니까, 아니면 파일에 직렬화 할 것인지 안되는 클래스의 메모리 내 인스턴스입니까? –

답변

5

예. 각 파일 데이터 세트에 대해 MD5 또는 SHA1 해시를 생성 한 다음 비교할 수 있습니다.

샘플 코드 (오류 명확성을 위해 제거 확인) :

public bool CompareFiles(string filePath1, string filePath2) 
{ 

    FileInfo info1 = new FileInfo(filePath1); 
    FileInfo info2 = new FileInfo(filePath2); 


    byte[] data1 = new byte[info1.Length] 
    byte[] data2 = new byte[info2.Length]; 

    FileStream fs1 = new FileStream(filePath1, FileMode.Open); 
    FileStream fs2 = new FileStream(filePath2, FileMode.Open); 

    fs1.Read(data1, 0, info1.Length); 
    fs2.Read(data2, 0, info2.Length); 

    fs1.Dispose(); 
    fs2.Dispose(); 

    SHA1 sha = new SHA1CryptoServiceProvider(); 

    byte[] hash1 = sha.ComputeHash(data1); 
    byte[] hash2 = sha.ComputeHash(data2); 

    // c# 2 or less: you need to compare the hash bytes yourself 

    // c# 3.5/4 
    bool result = hash1.SequenceEqual(hash2); 

    return result; 
} 
+0

두 개의 파일 만 있으면 바이트를 직접 비교하면 첫 번째 차이에서 빠져 나올 수 있지만 해시를 계산할 경우 매우 비쌀 수있는 전체 파일을 읽어야합니다. – luke

+0

둘 다 전체 파일을 읽지 않습니까? 요점은 무엇입니까? 물론 하나의 파일을 여러 번 비교할 때 해시를 계산하는 것이 유용 할 수 있지만 그럴 수는 없습니다. –

+0

해시 계산은 실제로 더 나쁩니다. 바이트 단위로 비교할 때 처음 몇 바이트 이후에 멈출 수 있습니다 (다른 경우). –

12

예 가능합니다.

파일을 읽으려면 파일을 읽어야합니다.

의사 코드는 다음과 같습니다 스트림으로

  • 열기 파일 1과 파일 2.
  • 길이를 비교하여 시작하십시오. 길이가 동일하지 않으면 파일이 동일하지 않습니다.
  • 각 파일의 청크를 버퍼로 읽어 들여 버퍼를 비교합니다. 차이가 발생할 때까지 반복하거나 파일의 끝에 도달하십시오.

동일한 파일을 여러 파일과 비교해야하는 경우 첫 번째 파일의 해시를 계산하는 것이 좋습니다. 그런 다음 다른 파일 각각의 해시를 계산하고 해시를 비교하십시오.

+1

나는 마지막 단계를 약간 수정했다 : "서로 다르거 나 파일 끝에 도달 할 때까지 반복한다."첫 번째 바이트가 다른 경우 끝까지 계속 가고 싶지는 않을 것이다. –

+2

나는 OP가 직렬화 된 버전에 따라 클래스가 변경되었는지 감지하려고한다고 생각합니다. 필자는 BinaryFormatter가 '동일한'클래스가 정확히 동일한 바이트를 가질 것이라고 보장하지 않기 때문에 파일 비교가 불가능하다고 생각합니다. –

+0

@ Neil, 물론 맞습니다. 나는 그것이 명백했다라고 생각했다 - 지금 대답을 정정했다 :-) – driis

0
byte[] myFile = File.ReadAllBytes(pathToFile); 

그런 다음 반복하십시오. 파일이 클 경우 속도가 느려질 수 있습니다.

아마 당신은 당신이 파일의 바이너리 내용을 읽고 당신이 얻을 바이트를 비교할 수있는 파일의 MD5 해시 알고리즘

0

을 찾아야한다. 파일을 읽으려면 ReadAllBytes (파일 크기가 적당하고 메모리에 편안하게 맞는지 확인) 또는 FileStream을 사용하고 두 파일의 데이터 청크를 읽을 수 있습니다.

다음과 같을 수 버퍼를 사용하여 접근 방식의 구조 :

byte[] buffer1 = new byte[1024], buffer2 = new byte[1024]; 
using(var fs1 = new FileStream(firstFile, FileMode.Open, FileAccess.Read) 
using(var fs2 = new FileStream(secondFile, FileMode.Open, FileAccess.Read) 
{ 
    // Use: fs.Read(buffer1, 0, 1024) to repeatedly read 1kb of data 
    // from both fs1 and fs2 and compare the content in buffer1 and buffer2 
} 

어떤 사람들은 해시를 사용하는 것이 좋습니다,하지만 그건 좋은 생각이 아니다 - 파일이 동일한 경우, 당신은 모든 읽기해야합니다 파일로부터의 데이터이므로 해시를 계산하는 것이 모든 데이터를 읽고 비교하는 것보다 효율적이지 않습니다. 그러나 파일이 처음 몇 바이트가 다른 경우 처음 몇 바이트 만 읽어야합니다 (바이트 단위로 비교하는 경우).

해시는 여러 파일 (예 : 각 파일 각각)을 비교하려는 경우에 유용합니다.

0

다음과 같은 기능이 있습니다. 다른 사람이 바이트 배열을 비교하는 더 좋은 방법을 제공 할 수 없다면.

private static bool CompareFiles(string file1, string file2) 
{ 
    var fsFile1 = new System.IO.FileStream(file1, System.IO.FileMode.Open, System.IO.FileAccess.Read); 
    var fsFile2 = new System.IO.FileStream(file2, System.IO.FileMode.Open, System.IO.FileAccess.Read); 
    var md5 = new System.Security.Cryptography.MD5Cng(); 
    var md5File1 = md5.ComputeHash(fsFile1); 
    var md5File2 = md5.ComputeHash(fsFile2); 
    for (int i = 0; i < md5File1.Length; ++i) 
    { 
     if (md5File1[i] != md5File2[i]) 
      return false; 
    } 
    return true; 
} 
관련 문제