65.9K
CodeProject 正在变化。 阅读更多。
Home

DIFF: 用于远程差分压缩的 IRdcLibrary API

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (6投票s)

2015 年 1 月 6 日

CPOL

3分钟阅读

viewsIcon

35120

downloadIcon

274

一个用于差分内存/文件处理的快速库

引言

在我看来,你一直都想创建一个具有每个文件增量处理的备份/恢复功能。这是一个小型库,展示了 IRdcLibrary COM API 的强大功能,随时可以使用。

背景

像往常一样,使用 COM、Win32 和 C++。我在这里不容忍比我更初级的人 :P。

Using the Code

DIFF 库可以从文件和内存中读取/写入。对于读取数据,您可以使用 Microsoft 的 IRdcFileReader interface。为了您的方便,我在代码中提供了 2 个辅助类,它们可以提供 IRdcFileReader interface

MemoryRdcFileReader,它可以从内存中读取。在存在此 interface 时,内存必须持久存在(即,interface 不会复制内存)。

构造函数

MemoryRdcFileReader(const char* dd,unsigned long long size);

FileRdcFileReader,它可以从现有的 HANDLE 中读取。该句柄必须已使用 GENERIC_READ 打开,并且必须是可寻址的。

构造函数

FileRdcFileReader(HANDLE hF);

对于写入数据,我的函数需要一个 DIFFWRITER 类的实例。我还提供了一个 FileDiffWriter (它可以从一个必须使用 GENERIC_WRITE 打开的 HANDLE 提供一个 DIFFWRITER)和一个 MemoryDiffWriter ,它写入到一个 vector<char>。这些辅助类提供了成员函数 GetReader(IRdcFileReader**) ,该函数返回一个 MemoryRdcFileReader 或一个 FileRdcFileReader

增量备份

假设您在 c:\test 中有一个名为 1.txt 的文件,并且您已将其备份到 c:\test2 中。现在假设您已修改了原始 c:\test 目录中的 1.txt,因此 c:\test\1.txt 是较新的。现在,您的增量备份步骤是(为简单起见,删除了错误检查)

// Prereqs: file readers for both files. 
// Say that hX1 and hX2 are handles to these two files
CComPtr<IRdcFileReader> fil1;
CComPtr<IRdcFileReader> fil2;
fil1.Attach(new DIFF::FileRdcFileReader(hX1));
fil2.Attach(new DIFF::FileRdcFileReader(hX2));

// Instantiate the library
DIFF::DIFF d;

// Create a signature for both files
// Say that hS1 and hS2 are handles to new files that the signature is to be stored
DIFF::FileDiffWriter sig1(hS1);
DIFF::FileDiffWriter sig2(hS2);
d.GenerateSignature(fil1,sig1);
d.GenerateSignature(fil2,sig1);

// Close handles

这会将新旧 1.txt 的 RDC 签名保存在文件中。

您的下一步是生成 2 个文件之间的差异。我的库为您提供 2 个选项:您可以创建一个自包含的 diff,或者创建一个独立的 diff

自包含的 diff 允许您从源文件离线重建更新的文件。
独立的 diff 要小得多,但它需要远程文件的一部分。因此,如果要使用独立的 diff,您必须自己实现一个 IRdcFileReader,该 IRdcFileReader 从服务器下载更新文件的请求部分。由于这需要服务器,因此我们将在此处重点介绍自包含的 diff

现在,您要创建新旧文件之间的 diff

 CComPtr<IRdcFileReader> xsig1;
 CComPtr<IRdcFileReader> xsig2;
 sig1.GetReader(&xsig1);
 sig2.GetReader(&xsig2);
 DIFF::MemoryDiffWriter diff1_2_sc;
 d.GenerateDiff(xsig1,xsig2,r2,diff1_2_sc));

如果传递 NULL 而不是第三个参数中的 r2,这将生成一个自包含的 diff (如果传递 NULL 代替第3个参数中的 r2,它将生成一个独立的diff)。现在,您可以上传此较小的 diff 文件,而不是上传您的新文件 c:\test\1.txt。它的小程度取决于文件之间的差异程度。

Diff 恢复

现在假设您有 1.txt 的原始(主)备份,并且您想恢复较新的 1.txt。您需要原始的 1.txt 和一个自包含的 diff 文件

// r1 is the reader for the original file.
// xdiff2 is reader for the diff.
// Say hX3 is a handle to the file we want to reconstruct
DIFF::FileDiffWriter reco1(hX3);
d.Reconstruct(r1,xdiff1,0,reco1);

就这样。您的较新 1.txt 文件已通过原始文件和 diff 重建。如果 diff 是一个独立的 diff,您将必须传递一个读取器到 DIFF::Reconstruct 的第 3 个参数,该参数将被要求提供文件的部分内容。

关注点

  • 该 API 需要 Vista 或更高版本。
  • 该库仅在多线程 COM 环境中运行 (CoInitializeEx(0, COINIT_MULTITHREADED);)
  • 如果无法创建 COM 对象,则构造函数会引发异常。
  • 我必须进一步调查一个相似性 API。
  • 该库使用智能指针,包括 COM ATL 和 C++。

玩得开心!

历史

  • 2016 年 3 月 21 日:实现为 * .h * 文件,并进行了一些错误修复
  • 2015 年 10 月 21 日:一些错误修复和一些实验性的多签名内容
  • 2015 年 1 月 6 日:首次发布(新年快乐:))
© . All rights reserved.