C# 将内存中的字节[]与文件中的字节[]进行比较。ReadAllBytes(),是否可能匹配?

C# 将内存中的字节[]与文件中的字节[]进行比较。ReadAllBytes(),是否可能匹配?,c#,.net,unit-testing,io,C#,.net,Unit Testing,Io,我正在针对一个API编写一些单元测试,基本上,它接受一些填充的对象并输出一个byte[],然后可以将其输出为Excel文件(这就是应用程序使用它所做的,但可能与此无关) 我想编写一个测试来验证,给定一些填充的对象,我将收到一个预期的字节[]数组,因此我的方法是使用以前输出的Excel文件,并在测试时加载它,以与代码应该输出的内容进行比较。我通过File.ReadAllBytes()读取它来获得byte[]数组,并将其与应用程序中生成的byte[]数组进行比较 我理解.NET中二进制再现性的问题,

我正在针对一个API编写一些单元测试,基本上,它接受一些填充的对象并输出一个
byte[]
,然后可以将其输出为Excel文件(这就是应用程序使用它所做的,但可能与此无关)

我想编写一个测试来验证,给定一些填充的对象,我将收到一个预期的
字节[]
数组,因此我的方法是使用以前输出的Excel文件,并在测试时加载它,以与代码应该输出的内容进行比较。我通过
File.ReadAllBytes()
读取它来获得
byte[]
数组,并将其与应用程序中生成的
byte[]
数组进行比较

我理解.NET中二进制再现性的问题,但我不确定这是否适用于这种情况。有人能提供字节数组不匹配的原因吗?我的猜测是,从磁盘读取文件会在二进制数据中出现一些差异,或者使用
GetString()
方法在运行时以某种方式更改数据

我的代码如下:

// The data generated by the app
var data = reportGenerator.GenerateReport(timeFrame, date);
// The expected data
var compareData = File.ReadAllBytes(@"Deployment\TestData.xls");

// Get string representation of the data for comparison
var dataString = Encoding.ASCII.GetString(data);
var compareDataString = Encoding.ASCII.GetString(compareData);

// Compare, Fails
Assert.AreEqual(dataString, compareDataString);

数据几乎匹配,但不完全相同。当查看Beyond Compare中的字符串时,它们可能99.9%相同,但有一些小差异。

当使用集合而不是使用
断言时,请在同一命名空间中使用该类

你可能想要

如果两个集合具有相同顺序和数量的相同元素,则它们是相等的。如果元素的值相等,则元素相等,而不是引用同一对象

至于为什么
GetString
不起作用,很可能您的数据无效
ASCII
文本,将任意二进制数据传递到
GetString
不起作用,将非字符串二进制数据转换为字符串格式的正确方法是使用


如果这两种方法都不起作用,那么您的
GenerateReport
方法不是每次都生成相同的文件,可能文件中有某种时间戳或序列号,如果发生这种情况,您需要解析文件并比较解析后的版本。

在使用集合而不是使用
Assert
时,请在同一命名空间中使用该类

你可能想要

如果两个集合具有相同顺序和数量的相同元素,则它们是相等的。如果元素的值相等,则元素相等,而不是引用同一对象

至于为什么
GetString
不起作用,很可能您的数据无效
ASCII
文本,将任意二进制数据传递到
GetString
不起作用,将非字符串二进制数据转换为字符串格式的正确方法是使用


如果这两种方法都不起作用,那么您的
GenerateReport
方法不是每次都生成相同的文件,可能文件中有某种时间戳或序列号,如果发生这种情况,您需要解析文件并比较解析后的版本。

Excel电子表格包含相关日期和时间、创建工作表的用户、文件位置等元数据。因此,在比较文件之间的原始字节时,您似乎无法获得100%的匹配

这有点复杂,但是您需要从每个电子表格中查询数据,并在断言中比较它们。例如,有一些Office扩展允许您使用电子表格数据。还有一个可以与OLEDB连接一起使用的Jet驱动程序。我经常在单元测试中输入大量案例时使用它。在这篇CodeProject文章中可以找到一个例子:


Excel电子表格包含元数据,如相关日期和时间、创建工作表的用户、文件位置等。因此,在比较不同文件的原始字节时,您似乎无法获得100%的匹配

这有点复杂,但是您需要从每个电子表格中查询数据,并在断言中比较它们。例如,有一些Office扩展允许您使用电子表格数据。还有一个可以与OLEDB连接一起使用的Jet驱动程序。我经常在单元测试中输入大量案例时使用它。在这篇CodeProject文章中可以找到一个例子:


是否更改了excel文件中嵌入的保存时间日期?如果连续两次运行GenerateReport,是否会得到相同的输出?谢谢您的评论。如果我运行两次
GenerateReport
,输出结果将一字不差(Beyond Compare中的不同调试器数据)。同样,如果我对数据连续使用
File.writealBytes()
,并用
Thread.Sleep(5000)
分隔,Excel文件的二进制数据是一字不差的。实际上,它现在似乎正在工作。我的猜测是,我使用“添加->现有文件”将文件导入到VS中,该文件可能通过创建副本(以及创建日期)修改了文件。我只是通过将文件移动到应用程序中而不是这样做来进行测试,现在它似乎有相同的GetString()数据。它是生成二进制文件还是实际生成类似于逗号分隔文件的ASCII文件?如果是二进制
ASCII.GetString(
将不会产生可靠的结果,因此不应使用。遇到的第一个
'\0'
将停止读取二进制数据。至少需要将其切换到
Convert.ToBase64String(
。可能是excel文件中嵌入的保存时间日期发生了更改吗?如果连续运行GenerateReport两次,是否会得到相同的输出?谢谢您的评论。如果我运行
GenerateReport
两次,输出将一字不差(无法比较的不同调试器数据)。同样,如果我对数据使用
File.writealBytes()
// The data generated by the app
var data = reportGenerator.GenerateReport(timeFrame, date);
// The expected data
var compareData = File.ReadAllBytes(@"Deployment\TestData.xls");

// expected data comes first in a Assert method.
CollectionAssert.AreEqual(compareData, data);
// The data generated by the app
var data = reportGenerator.GenerateReport(timeFrame, date);
// The expected data
var compareData = File.ReadAllBytes(@"Deployment\TestData.xls");

// Get string representation of the data for comparison
var dataString = Convert.ToBase64String(data);
var compareDataString = Convert.ToBase64String(compareData);

Assert.AreEqual(dataString, compareDataString);