【发布时间】:2013-08-27 19:08:48
【问题描述】:
我正在比较两个文件,其中一个文件可能添加或删除了项目。我正在检查两个文件之间是否存在差异,如果存在差异,那么无论是否添加或删除了记录,这些差异是什么。我想返回那些记录(添加或删除)
根据我所拥有的,它告诉我文件是否删除或添加了项目,但它没有返回已添加或删除的项目。对我所缺少的任何帮助将不胜感激。
foreach (ExcelRow rowA in fileA.excelRows)
{
if (!fileB.ContainsHash(rowA.rowHash))
{
MessageBox.Show("Files are NOT the same. Data was REMOVED.\n" + rowA.ToString());
}
}
foreach (ExcelRow rowB in fileB.excelRows)
{
if (!fileA.ContainsHash(rowB.rowHash))
{
MessageBox.Show("Row added" + rowB.ToString());
}
}
public List<ExcelRow> excelRows = new List<ExcelRow>();
public bool ContainsHash(byte[] hashToLook)
{
bool found;
found = false;
foreach (ExcelRow eRow in excelRows)
{
found = EqualHash(eRow.rowHash, hashToLook);
if (found)
{
break;
}
}
return found;
}
public static bool EqualHash(byte[] hashA, byte[] hashB)
{
bool bEqual ;
int i ;
bEqual = false;
if (hashA.Length == hashB.Length)
{
i = 0;
while ((i < hashA.Length) && (hashA[i] == hashB[i]))
{
i++ ;
}
if (i == hashA.Length)
{
bEqual = true;
}
}
return bEqual ;
}
读取文件:
public ExcelInfo ReadExcel(OpenFileDialog openFileDialog)
{
var _excelFile = new ExcelQueryFactory(openFileDialog.FileName);
var _info = from c in _excelFile.WorksheetNoHeader() select c;
ExcelRow excelRow;
ExcelInfo resp;
resp = new ExcelInfo();
foreach (var item in _info)
{
excelRow = new ExcelRow();
excelRow.lstCells.Add(item.ElementAt(0));
excelRow.lstCells.Add(item.ElementAt(1));
excelRow.lstCells.Add(item.ElementAt(2));
excelRow.lstCells.Add(item.ElementAt(3));
excelRow.lstCells.Add(item.ElementAt(4));
excelRow.lstCells.Add(item.ElementAt(5));
excelRow.lstCells.Add(item.ElementAt(6));
excelRow.lstCells.Add(item.ElementAt(7));
excelRow.lstCells.Add(item.ElementAt(8));
excelRow.lstCells.Add(item.ElementAt(9));
excelRow.lstCells.Add(item.ElementAt(10));
excelRow.lstCells.Add(item.ElementAt(11));
excelRow.lstCells.Add(item.ElementAt(12));
excelRow.CalculateHash();
resp.excelRows.Add(excelRow);
}
return resp;
}
计算哈希:
public void CalculateHash()
{
byte[] rowBytes;
byte[] cellBytes;
int pos;
int numRowBytes;
numRowBytes = 0;
foreach (string cellText in lstCells)
{
numRowBytes += NumBytes(cellText);
}
//Allocate space to calculate the HASH of a single row
rowBytes = new byte[numRowBytes];
pos = 0;
//Concatenate the cellText of each row into a single byte array
foreach (string cellText in lstCells)
{
cellBytes = GetBytes(cellText);
System.Buffer.BlockCopy(cellBytes, 0, rowBytes, pos, cellBytes.Length);
pos = cellBytes.Length;
}
rowHash = new MD5CryptoServiceProvider().ComputeHash(rowBytes);
}
调试时:
if (!fileB.ContainsHash(rowA.rowHash))
fileB 包含 3 行,fileA 包含 4 行。
文件B = 3, rowA = fileA 中的第一行,(.rowHash) 为 byte[16]
当我继续使用 ContainHash 方法时,byte[] hashToLook = 16 - 这不应该是 rowA 吗?
excelRows = 3 (fileB)
那么 EqualHash(eRow.rowHash, hashToLook) 是 (fileA 中的第一行, byte[16])
我是不是传入 rowA 错了?
【问题讨论】:
-
请说明您是如何计算哈希的。 IE。
ExcelRow.CalculateHash的实现。 -
@Alex 我添加了上面的方法。谢谢
-
我想我在哈希计算中发现了错误。您需要将
pos = cellBytes.Length;替换为pos += cellBytes.Length; -
此外,有时可能会发生哈希冲突。因此,如果哈希匹配,您还应该比较每个字段以确保两行相等。尽管所有字节都使用 MD5,但发生这种情况的机会非常低。
-
@Alex 我认为我非常接近 - 现在它表明我删除的行之前的行是删除的行。例如:文件有 1、2、3、4(我删除了 5)它返回说明 4 已删除