剪贴板图像存档器





4.00/5 (6投票s)
2005年5月23日
4分钟阅读

45794

733
ClipboardImageArchiver 使用的方法 - 优点和缺点。
引言
ClipboardImageArchiver
是一个存档剪贴板图像的实用工具。它将剪贴板中的图像保存到一个单一的目的地,让您不必费心记住您具体将图像保存在哪里。您可以将这些图像作为单个 zip 文件或提取到某个目录中。ClipboardImageArchiver
还提供将图像保存为不同格式的选项。ClipboardImageArchiver
使用开源的 SharpZip 压缩库。ClipboardImageArchiver
结合了二进制序列化和流压缩来克服“追加到 zip”文件的难题。本文主要讨论 ClipboardImageArchiver
使用的这种方法及其优缺点。
用户只需“复制”一张图像,然后在任务栏上右键单击 ClipboardImageArchiver
图标,然后从菜单中选择“粘贴”。屏幕右角会弹出一个小弹出窗口,提供有关已保存图像的大小、格式和名称的信息。用户还可以通过从菜单中选择“格式”并单击所需的格式来选择格式。目前支持七种格式:JPEG、Bitmap、GIF、PNG、WMF、EMF 和 TIFF。默认情况下选择 JPEG。
所有已保存的图像都可以通过单击主屏幕上的“导出”来检索。有两种选项,一种导出为单个文件,另一种导出为目录中的单个文件。在这两种情况下,都保留了单个文件的格式。
“追加”到 Zip 文件的难题
无法直接将条目追加到现有的 zip 存档。这不像向文本文件追加文本。值得在此理解的是,任何追加到 zip 文件的内容都会导致整个 zip 文件发生更改。我的意思是,它不会导致局部更改。
所以这意味着,每次我需要向例如名为 images.zip 的文件添加内容时,我需要执行以下步骤:
- 初始化一个新的
ZipOutputStream
对象。将旧 zip 文件中的项复制到新 zip 文件中作为 zip 条目。 - 创建并添加一个新 zip 条目,用于要添加的新文件。
- 对
ZipOutputStreamObject
调用compress
方法,将其保存到 temp.zip 文件。 - 现在删除 images.zip 并用 temp.zip 替换它。
这就是向 zip 存档添加新文件时发生的事件的确切顺序。这具有以下明显的缺点:
- 每次添加新条目时,我们都必须创建一个临时 zip。将所有条目从旧文件复制到其中。
- 如果 zip 存档非常大,它们将占用大量磁盘空间和内存资源。这对于
ClipboardImageArchiver
这样的实用工具来说是非常不可取的。 - 此外,随着 images.zip 文件大小的增加,添加新条目的时间会越来越长。非常不可取!
克服难题
为了克服这个问题,我们结合使用了序列化和流压缩。首先,我创建了一个名为 ‘ZipImageObject
’ 的类,它以以下格式保存图像的压缩数据:
ZipImageObject 类
[Serializable]
private long _length;
实际未压缩图像的字节长度
private byte [] _imgData;
GZipped(二进制)图像字节流。这是进行压缩的地方。使用库中的 GZip 算法压缩二进制图像,并将生成的数据存储为字节流。
private short _imgFormat;
指示图像格式的整数
private string _fileName;
图像名称 [GUID]
当用户将图像“粘贴”到 zip 剪贴板时,会发生以下事件序列:
下面的代码说明了如何使用 GZip 压缩将 BMP 文件转换为 ZipImageObject
。此 ZipImageObject
被序列化并存储到 data.dat 文件中。代码非常直接且不言自明。
public ZipImageObject CompressFile(string bmpFilename, short formatIndicator)
{
FileStream fsbmpFile = new FileStream(bmpFilename, FileMode.Open);
MemoryStream ms = new MemoryStream(Convert.ToInt32(fsbmpFile.Length));
GZipOutputStream gzipOutput = new GZipOutputStream(ms);
Byte[] bmpData = new Byte[Convert.ToInt32(fsbmpFile.Length)];
fsbmpFile.Read(bmpData, 0, Convert.ToInt32(fsbmpFile.Length));
gzipOutput.SetLevel(9);
gzipOutput.Write(bmpData, 0, bmpData.Length);
gzipOutput.Close();
ZipImageObject zipImg = new ZipImageObject();
zipImg.Filename = bmpFilename;
zipImg.ImgData = ms.ToArray();
zipImg.Length = fsbmpFile.Length;
zipImg.ImgFormat =formatIndicator;
fsbmpFile.Close();
ms.Close();
return zipImg;
}
这里需要注意的一点是,我们可能无法获得最佳压缩效果。我的意思是,包含十个 ZipImageObject
的文件可能比包含所有图像的单个 zip 文件占用更多空间。这是此方法的缺点。即便如此,它们的大小差异应该不会太大。当用户单击“导出”时,所有序列化的 ZipImageObject
都将导出到 zip 存档。此应用程序的完整代码可以从上面的链接下载。
重要:要编译代码,您必须在 IDE 中添加对 ICSharpCode.SharpZipLib.dll 的引用。
结论
ClipboardImageArchiver
展示了一种避免在处理 zip 压缩时频繁读写磁盘的方法。它为此结合使用了流压缩和序列化。该技术在处理大量数据时非常有用。此外,它是一个非常有用且便捷的实用工具,可以在浏览网页时保存图像。
希望您发现本文有用。任何评论和批评都欢迎。
历史
- 2005 年 5 月 23 日:初始版本
许可证
本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。
作者可能使用的许可证列表可以在此处找到。