Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 比较C语言中的二进制文件#_C#_File_Compare - Fatal编程技术网

C# 比较C语言中的二进制文件#

C# 比较C语言中的二进制文件#,c#,file,compare,C#,File,Compare,我想比较两个二进制文件。其中一个已经存储在服务器上,数据库中的CRC32是我最初存储时预先计算的 我知道如果CRC是不同的,那么文件肯定是不同的。但是,如果CRC是相同的,我不知道这些文件是相同的。因此,我正在寻找一种非常有效的方法来比较这两个流:一个来自发布的文件,另一个来自文件系统 我不是溪流专家,但我很清楚,就内存使用而言,我很容易在这里攻击自己。如果您将crc更改为sha1签名,则它不同但具有相同签名的可能性非常小您甚至可以在检查crc之前检查两个文件的长度和日期,以避免出现错误循环冗余

我想比较两个二进制文件。其中一个已经存储在服务器上,数据库中的CRC32是我最初存储时预先计算的

我知道如果CRC是不同的,那么文件肯定是不同的。但是,如果CRC是相同的,我不知道这些文件是相同的。因此,我正在寻找一种非常有效的方法来比较这两个流:一个来自发布的文件,另一个来自文件系统


我不是溪流专家,但我很清楚,就内存使用而言,我很容易在这里攻击自己。

如果您将crc更改为sha1签名,则它不同但具有相同签名的可能性非常小

您甚至可以在检查crc之前检查两个文件的长度和日期,以避免出现错误循环冗余校验

但是如果要比较整个文件的内容,我看到的一个巧妙的技巧是读取字节的速度等于CPU的比特数。例如,在32位PC上,一次读取4个字节,并将它们作为int32进行比较。在64位PC上,一次可以读取8个字节。这大约是逐字节执行的4到8倍。您可能还想使用一个不安全的代码块,这样您就可以使用指针,而不是执行一系列的位移位和/或运算来将字节转换为本机int大小

您可以使用IntPtr.Size来确定当前处理器体系结构的理想大小。

我通过在读取流块上的循环中使用Int64比较来加速“memcmp”。这将时间减少到大约1/4

static bool FileEquals(string fileName1, string fileName2)
{
    // Check the file size and CRC equality here.. if they are equal...    
    using (var file1 = new FileStream(fileName1, FileMode.Open))
        using (var file2 = new FileStream(fileName2, FileMode.Open))
            return FileStreamEquals(file1, file2);
}

static bool FileStreamEquals(Stream stream1, Stream stream2)
{
    const int bufferSize = 2048;
    byte[] buffer1 = new byte[bufferSize]; //buffer size
    byte[] buffer2 = new byte[bufferSize];
    while (true) {
        int count1 = stream1.Read(buffer1, 0, bufferSize);
        int count2 = stream2.Read(buffer2, 0, bufferSize);

        if (count1 != count2)
            return false;

        if (count1 == 0)
            return true;

        // You might replace the following with an efficient "memcmp"
        if (!buffer1.Take(count1).SequenceEqual(buffer2.Take(count2)))
            return false;
    }
}
    private static bool StreamsContentsAreEqual(Stream stream1, Stream stream2)
    {
        const int bufferSize = 2048 * 2;
        var buffer1 = new byte[bufferSize];
        var buffer2 = new byte[bufferSize];

        while (true)
        {
            int count1 = stream1.Read(buffer1, 0, bufferSize);
            int count2 = stream2.Read(buffer2, 0, bufferSize);

            if (count1 != count2)
            {
                return false;
            }

            if (count1 == 0)
            {
                return true;
            }

            int iterations = (int)Math.Ceiling((double)count1 / sizeof(Int64));
            for (int i = 0; i < iterations; i++)
            {
                if (BitConverter.ToInt64(buffer1, i * sizeof(Int64)) != BitConverter.ToInt64(buffer2, i * sizeof(Int64)))
                {
                    return false;
                }
            }
        }
    }
private static bool streams内容重新相等(Stream stream1、Stream stream2)
{
常量int bufferSize=2048*2;
var buffer1=新字节[bufferSize];
var buffer2=新字节[bufferSize];
while(true)
{
int count1=stream1.Read(buffer1,0,bufferSize);
int count2=stream2.Read(buffer2,0,bufferSize);
如果(count1!=count2)
{
返回false;
}
如果(count1==0)
{
返回true;
}
int迭代=(int)数学上限((double)count1/sizeof(Int64));
对于(int i=0;i
如果您不想依赖crc,我会这样做:

    /// <summary>
    /// Binary comparison of two files
    /// </summary>
    /// <param name="fileName1">the file to compare</param>
    /// <param name="fileName2">the other file to compare</param>
    /// <returns>a value indicateing weather the file are identical</returns>
    public static bool CompareFiles(string fileName1, string fileName2)
    {
        FileInfo info1 = new FileInfo(fileName1);
        FileInfo info2 = new FileInfo(fileName2);
        bool same = info1.Length == info2.Length;
        if (same)
        {
            using (FileStream fs1 = info1.OpenRead())
            using (FileStream fs2 = info2.OpenRead())
            using (BufferedStream bs1 = new BufferedStream(fs1))
            using (BufferedStream bs2 = new BufferedStream(fs2))
            {
                for (long i = 0; i < info1.Length; i++)
                {
                    if (bs1.ReadByte() != bs2.ReadByte())
                    {
                        same = false;
                        break;
                    }
                }
            }
        }

        return same;
    }
//
///两个文件的二进制比较
/// 
///要比较的文件
///要比较的其他文件
///指示文件是否相同的值
公共静态布尔比较文件(字符串文件名1、字符串文件名2)
{
FileInfo info1=新的FileInfo(fileName1);
FileInfo info2=新的FileInfo(fileName2);
bool same=info1.Length==info2.Length;
如果(相同)
{
使用(FileStream fs1=info1.OpenRead())
使用(FileStream fs2=info2.OpenRead())
使用(BufferedStream bs1=新的BufferedStream(fs1))
使用(BufferedStream bs2=新的BufferedStream(fs2))
{
for(长i=0;i
接受的答案有一个已指出但从未更正的错误:流读取调用不保证返回所有请求的字节

BinaryReaderReadBytes除非首先到达流的末尾,否则保证返回请求的字节数

以下代码利用BinaryReader进行比较:

    static private bool FileEquals(string file1, string file2)
    {
        using (FileStream s1 = new FileStream(file1, FileMode.Open, FileAccess.Read, FileShare.Read))
        using (FileStream s2 = new FileStream(file2, FileMode.Open, FileAccess.Read, FileShare.Read))
        using (BinaryReader b1 = new BinaryReader(s1))
        using (BinaryReader b2 = new BinaryReader(s2))
        {
            while (true)
            {
                byte[] data1 = b1.ReadBytes(64 * 1024);
                byte[] data2 = b2.ReadBytes(64 * 1024);
                if (data1.Length != data2.Length)
                    return false;
                if (data1.Length == 0)
                    return true;
                if (!data1.SequenceEqual(data2))
                    return false;
            }
        }
    }

在大多数严肃的应用程序中,你永远不应该依赖它。这就像只是在哈希表查找中检查哈希,而不比较实际的键!不幸的是,你可以保证,一旦它搞砸了,将是绝对关键的,可能是一个大的投球。@Simon-呵呵,非常正确@Mehrdad-可能不会,但这会大大减少你检查超级优步的次数。拿CRC来说,文件大小和变化都越来越小。@Mehrdadadafshari是一款像git这样相当严肃的应用程序,它正是依赖于此。引用莱纳斯·托瓦尔兹(Linus Torvalds)的话,我们“很可能永远不会在[通过比较沙的《两个文件的碰撞》]的《宇宙的全部历史》中看到它”。Cf。但我从未在纯32位CPU上尝试过。您必须尝试一下,也许只需将Int64更改为int32即可。但是,大多数现代CPU不是或多或少都能进行64位操作吗(自2004年以来就是x86)?去试试吧!见对的评论。依赖
count1
等于
count2
是不可靠的。这是否正确处理最后的0-7字节?您是否在
fileSize%sizeof(Int64)>0的两个文件上测试了它,只有最后一个字节不同?Require conunt1==count2可能不准确,因为Stream.Read可以自由返回长度小于请求字节计数的块。谢谢你的解决方案,Mehrdad。你需要接电话吗?我只尝试了
如果(!buffer1.SequenceEqual(buffer2))
,它似乎可以工作。@Ozgur它可以工作,但效率较低,在IMO中也不是很有原则。说它可能是一个问题,即使对于FileStream也是如此。你是说这通常不是问题吗?还是文档有误导性?@Karata是绝对正确的,这个错误代码不应该不被纠正(有人可能会在我以后使用的软件上使用它)。至少
FileStreamEqua