1、迭代器的定义:

提供一种方法,使之能够依序访问某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表述方式。

2、迭代器的设计动机

一个聚合对象,应该提供一种方法来让别人可以访问它的元素,而又不需暴露它的内部结构。此外,针对不同的需要,可能要以不同的方式遍历这个容器。但即使可以预见到所需的那些遍历操作,你可能也不希望容器的接口中充斥着各种不同的遍历的操作。有时可能需要在同一个容器上同时进行多个遍历。

迭代器模式的关键思想是将对列表的访问和遍历从容器对象中分离出来并放入一个迭代器(iterator)对象中。迭代器类定义了一个访问该容器的接口。迭代器对象负责跟踪当前的元素;即它知道哪些元素已经遍历过了。将遍历机制与列表对象分离使我们可以定义不同的迭代器来实现不同的遍历策略,而无需在容器接口中列举它们。

一般一个迭代器类需要提供以下操作:

(1)    First():初始化迭代器,使当前元素指向列表的第一个元素。

(2)    Next():将当前元素指针向前推进一步,指向下一个元素。

(3)    CurrentItem():返回容器中的当前元素。

(4)    IsDone():检查是否已越过最后一个元素,也就是完成了本次遍历。

3、迭代器的适用性

(1)访问一个聚合对象的内容而无需暴露它的内部表示。

(2)支持对聚合对象的多种遍历

(3)为遍历不同的聚合结构提供一个统一的接口

4、空迭代器

一个空迭代器(NullIterator)是一个退化的迭代器,它有助于处理边界条件,根据定义,空迭代器总是已经完成了遍历,即,它的IsDone操作总是返回true;

5、例子——IE缓存迭代器

以下用C++实现一个迭代器类,用于遍历IE缓存空间。我们在访问网站或本地文件时,系统会把图片、动画、浏览记录等信息保存在Internet临时文件夹中,但这个文件夹是一个隐藏文件夹,不同于普通文件夹,Win32 API给用户提供了很多接口用于访问,修改这个文件夹里的内容。为了展示怎样怎样设计IE缓存迭代器,需要用到以下Win32 API。

5.1 需要用到的Win32 API

最低配置,头文件、库及动态链接库:

Minimum supported client

Windows 2000 Professional [desktop apps only]

Minimum supported server

Windows 2000 Server [desktop apps only]

Header

Wininet.h

Library

Wininet.lib

DLL

Wininet.dll

(1)IE缓存的入口点

HANDLE FindFirstUrlCacheEntry(_In_     LPCTSTR lpszUrlSearchPattern,_Out_    LPINTERNET_CACHE_ENTRY_INFO lpFirstCacheEntryInfo,_Inout_  LPDWORD lpcbCacheEntryInfo
);

参数:

lpszUrlSearchPattern [in]:一个字符串指针,该字符串指定索引模式,该参数只能被设定为以下三个值:

“cookie:”:列举出IE缓存的cookie;

“visited:”:列表出缓存空间中的URL历史记录;

NULL:列表出缓存空间中的所有内容

lpFirstCacheEntryInfo [out]:指向 INTERNET_CACHE_ENTRY_INFO 结构的指针

lpcbCacheEntryInfo [in,out]:指向DWORD变量的指针,用于指定lpcbCacheEntryInfo缓冲区的大小,以字节为单位。当函数返回时,该变量包含了该缓冲区的实际大小。

返回值:

返回一个被FindNextUrlCacheEntry访问随后的缓存空间所使用的句柄,如果该函数失败,则返回NULL。要想得到扩展错误信息,调用GetLastError函数获取。

(2) 获取IE缓存的下一个入口点

BOOL FindNextUrlCacheEntry(_In_     HANDLE hEnumHandle,_Out_    LPINTERNET_CACHE_ENTRY_INFO lpNextCacheEntryInfo,_Inout_  LPDWORD lpcbCacheEntryInfo
);

参数:

hEnumHandle [in]:调用FindFirstUrlCacheEntry返回的句柄

lpNextCacheEntryInfo [out]:指向INTERNET_CACHE_ENTRY_INFO 结构的指针

lpcbCacheEntryInfo [in,out]:指向DWORD变量的指针,用于指定lpcbCacheEntryInfo缓冲区的大小,以字节为单位。当函数返回时,该变量包含了该缓冲区的实际大小。

返回值:

如果成功则返回true,否则返回false.要想获取扩展错误信息,需要调用GetLastError,可能的错误值如下:

ERROR_INSUFFICIENT_BUFFER:lpcbCacheEntryInfo不足以提供lpNextCacheEntryInfo 指定的大小,函数返回时,lpcbCacheEntryInfo包含lpcbCacheEntryInfo指定的实际大小。

ERROR_NO_MORE_ITEMS:列举完成。

(3)关闭IE缓存句柄

BOOL FindCloseUrlCache(_In_  HANDLE hEnumHandle
);

参数:

hEnumHandle [in]:调用FindFirstUrlCacheEntry返回的句柄

返回值:

如果成功则返回true,否则返回false.要想获取扩展错误信息,需要调用GetLastError。

(4)IE缓存结构体,包含IE缓存的信息

typedefstruct_INTERNET_CACHE_ENTRY_INFO {DWORD   dwStructSize;LPTSTR  lpszSourceUrlName;LPTSTR  lpszLocalFileName;DWORD   CacheEntryType;DWORD   dwUseCount;DWORD   dwHitRate;DWORD   dwSizeLow;DWORD   dwSizeHigh;FILETIME LastModifiedTime;FILETIME ExpireTime;FILETIME LastAccessTime;FILETIME LastSyncTime;LPTSTR  lpHeaderInfo;DWORD   dwHeaderInfoSize;LPTSTR  lpszFileExtension;union {DWORD dwReserved;DWORD dwExemptDelta;};
}INTERNET_CACHE_ENTRY_INFO,*LPINTERNET_CACHE_ENTRY_INFO;

由于该结构体成员比较多,在此不一一解译,请参考MSDNhttp://msdn.microsoft.com/zh-cn/library/windows/desktop/aa385134(v=vs.85).aspx

5.2、CacheIterator类

(1)成员变量

用以上三个API中可以得知,FindFirstUrlCacheEntry返回的句柄hEnumHandle,指向INTERNET_CACHE_ENTRY_INFO 结构的指针lpCacheEntryInfo,还有INTERNET_CACHE_ENTRY_INFO 的实际大小都是要经常用到的变量,因此把它们作为CacheIterator的成员变量,如下:

HANDLE m_hCacheEntry;

LPINTERNET_CACHE_ENTRY_INFO m_lpCacheEntryInfo;

DWORD m_dwNeedBufSize;

(2)成员函数

从迭代器模式需要提供的四个操作来看,First和Next操作和FindFirstUrlCacheEntry与FindNextUrlCacheEntry是一一对应的;CurrentItem用于返回m_lpCacheEntryInfo所指向的IE缓存结构体INTERNET_CACHE_ENTRY_INFO;为了处理边界条件,同样需要IsDone操作,该操作只需判断m_lpCacheEntryInfo是否为NULL.

为了给出具体的代码,在此选择C++语言进行描述。从面向对象来看,我们可以在构造函数中进行初始化,即实现First操作;由于C++语言具有操作符重载机制,我们可以在前置operator++(),和后置operator++(int)中实现Next操作;同样由于操作符重载,我们可以在operator*()中实现CurrentItem操作,该成员函数用于返回m_lpCacheEntryInfo指向INTERNET_CACHE_ENTRY_INFO结构体的一个引用;最后一个问题是怎样实现IsDone操作呢?即该操作用于处理边界条件,判断遍历是否结束。在此,如果我们在构造的时候能够构造一个空迭代器,即当迭代器为空的时候,表示IsDone,遍历完成。空迭代器很简单,我们只需要将其m_lpCacheEntryInfo设为NULL即可。由于我们要进行比较操作,所以需要重载operator==和operator!=操作符。如下,得到了以下成员函数:

explicit CacheIterator();

explicit CacheIterator(LPCSTR accessMethod);

booloperator==(constCacheIterator& rhs);

booloperator!=(constCacheIterator& rhs);

INTERNET_CACHE_ENTRY_INFO& operator*();

CacheIterator& operator++();

CacheIterator operator++(int );

(3)主要成员函数的实现

构造函数:

从FindFirstUrlCacheEntry的第一个参数lpszUrlSearchPattern,我们也需要提供两样的接口给用户指定访问模式。在无参构造函数中,我们指定lpszUrlSearchPattern为0,即可以访问IE缓存的全部内容。在CacheIterator(LPCSTRaccessMethod)中可以给accessMethod指定访问模式,当accessMethod为空时,我们设定为空迭代器。构造函数如下:

CacheIterator::CacheIterator()
{Init(0);
}CacheIterator::CacheIterator(LPCSTR accessMethod):m_hCacheEntry(0),m_lpCacheEntryInfo(0), m_dwNeedBufSize(0)
{if(accessMethod != 0)Init(accessMethod);
}void CacheIterator::Init(LPCSTR accessMethod)
{FindFirstUrlCacheEntry(accessMethod,0, &m_dwNeedBufSize);m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[m_dwNeedBufSize]);m_hCacheEntry = FindFirstUrlCacheEntry(accessMethod, m_lpCacheEntryInfo,&m_dwNeedBufSize);
}

前置 Operator++

CacheIterator& CacheIterator::operator++()
{if(!FindNextUrlCacheEntry(m_hCacheEntry, m_lpCacheEntryInfo,&m_dwNeedBufSize)){delete[] m_lpCacheEntryInfo;switch(GetLastError()){case ERROR_NO_MORE_ITEMS:FindCloseUrlCache(m_hCacheEntry);m_hCacheEntry= 0;break;case ERROR_INSUFFICIENT_BUFFER:m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[m_dwNeedBufSize]);if(!FindNextUrlCacheEntry(m_hCacheEntry, m_lpCacheEntryInfo, &m_dwNeedBufSize)){delete[] m_lpCacheEntryInfo;FindCloseUrlCache(m_hCacheEntry);m_lpCacheEntryInfo = 0;}break;default:FindCloseUrlCache(m_hCacheEntry);m_lpCacheEntryInfo = 0;break;}}return *this;
}

6、完整代码:

///cacheiterator.h
#ifndef__CACHEITERATOR_H__
#define__CACHEITERATOR_H__#include"windows.h"
#include"wininet.h"
#pragmacomment(lib,"wininet.lib")class CacheIterator
{
public:explicit CacheIterator();explicit CacheIterator(LPCSTRaccessMethod);bool operator==(constCacheIterator& rhs);bool operator!=(constCacheIterator& rhs);INTERNET_CACHE_ENTRY_INFO& operator*();CacheIterator& operator++();CacheIterator operator++(int );
private:void Init(LPCSTR accessMethod);
private:HANDLE m_hCacheEntry;LPINTERNET_CACHE_ENTRY_INFO m_lpCacheEntryInfo;DWORD m_dwNeedBufSize;
};
#endif///cacheiterator.cpp
#include"cacheiterator.h"CacheIterator::CacheIterator()
{Init(0);
}CacheIterator::CacheIterator(LPCSTR accessMethod):m_hCacheEntry(0),m_lpCacheEntryInfo(0),m_dwNeedBufSize(0)
{if(accessMethod != 0)Init(accessMethod);
}void CacheIterator::Init(LPCSTR accessMethod)
{FindFirstUrlCacheEntry(accessMethod,0,&m_dwNeedBufSize);m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[m_dwNeedBufSize]);m_hCacheEntry = FindFirstUrlCacheEntry(accessMethod, m_lpCacheEntryInfo,&m_dwNeedBufSize);
}bool CacheIterator::operator==(const CacheIterator& rhs)
{return m_hCacheEntry == rhs.m_hCacheEntry;
}bool CacheIterator::operator!=(const CacheIterator& rhs)
{return !(*this == rhs);
}INTERNET_CACHE_ENTRY_INFO& CacheIterator::operator*()
{return *m_lpCacheEntryInfo;
}CacheIterator& CacheIterator::operator++()
{if(!FindNextUrlCacheEntry(m_hCacheEntry,m_lpCacheEntryInfo,&m_dwNeedBufSize)){delete[] m_lpCacheEntryInfo;switch(GetLastError()){case ERROR_NO_MORE_ITEMS:FindCloseUrlCache(m_hCacheEntry);m_hCacheEntry = 0;break;case ERROR_INSUFFICIENT_BUFFER:m_lpCacheEntryInfo = reinterpret_cast<LPINTERNET_CACHE_ENTRY_INFO>(new char[m_dwNeedBufSize]);if(!FindNextUrlCacheEntry(m_hCacheEntry,m_lpCacheEntryInfo, &m_dwNeedBufSize)){delete[] m_lpCacheEntryInfo;FindCloseUrlCache(m_hCacheEntry);m_lpCacheEntryInfo = 0;}break;default:FindCloseUrlCache(m_hCacheEntry);m_lpCacheEntryInfo = 0;break;}}return *this;
}CacheIterator CacheIterator::operator++(int)
{CacheIterator preCacheIter = *this;++*this;return preCacheIter;
}

7、测试——统计IE缓存的cookie项总数

int main()
{CacheIterator beg("cookie:"),end(0);int cnt = 0;for ( ; beg != end; ++beg){//cout<<(*beg).lpszLocalFileName<<endl;++cnt;}cout<<"sum of cookies ="<<cnt<<endl;return 0;
}

8、更多参考资料

[1] http://msdn.microsoft.com/en-us/magazine/cc301955.aspx

[2] http://www.cnblogs.com/yelaiju/archive/2010/10/01/1839860.html

[3]Erich Gamma,Richard Helm等著.设计模式[M],北京:机械工业出版社,2012.6

[4]侯捷著.STL源码剖析[M],湖北:华中科技大学出版社,2011.12

注:欢迎各个网友指出错误,一起探讨,大家共同进步!

C++实现IE缓存迭代器相关推荐

  1. C++/C++11中头文件iterator的使用

    <iterator>是C++标准程序库中的一个头文件,定义了C++ STL标准中的一些迭代器模板类,这些类都是以std::iterator为基类派生出来的.迭代器提供对集合(容器)元素的操 ...

  2. 中华万年历头条数据聚合优化之路

    业务介绍 中华万年历的头条数据是根据推荐算法聚合而成的数据,包括ALS算法数据.用户画像数据.时效数据.非时效数据.定投数据.惊喜数据.频道数据.热榜数据.用户相关阅读推荐数据等.启动方式分为冷启动和 ...

  3. 带你100% 地了解 Redis 6.0 的客户端缓存

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 近日 Redis 6.0.0 GA 版本发布,这是 Redis 历 ...

  4. LeetCode第 146 号问题: LRU 缓存机制

    题目描述 运用你所掌握的数据结构,设计和实现一个 LRU (最近最少使用) 缓存机制.它应该支持以下操作: 获取数据 get 和 写入数据 put . 获取数据 get(key) - 如果密钥 (ke ...

  5. Php-SPL库中的迭代器类详解(转)

    SPL提供了多个迭代器类,分别提供了迭代访问.过滤数据.缓存结果.控制分页等功能.,因为php总是在不断壮大,我尽可能列出SPL中所有的迭代类.下面其中一些迭代器类是需要php5.4,另外一些如Sea ...

  6. python生成器和装饰器_python三大法器:生成器、装饰器、迭代器

    迭代器 迭代的概念 使用for循环遍历取值的过程叫做迭代,比如:使用for循环遍历列表获取值的过程 使用for循环遍历取值的对象叫做可迭代对象, 比如:列表.元组.字典.集合.range.字符串 判断 ...

  7. 【Android 内存优化】Bitmap 硬盘缓存 ( Google 官方 Bitmap 示例 | DiskLruCache 开源库 | 代码示例 )

    文章目录 一.Google 官方 Bitmap 相关示例参考 二.磁盘缓存类 DiskLruCache 三.磁盘缓存初始化 四.存储数据到磁盘缓存中 五.从磁盘缓存中读取数据 六. Android 1 ...

  8. 【Android 内存优化】Bitmap 内存缓存 ( Bitmap 内存复用 | 弱引用 | 引用队列 | 针对不同 Android 版本开发不同的 Bitmap 复用策略 | 工具类代码 )

    文章目录 一.Bitmap 复用池 二.弱引用 Bitmap 内存释放 三.从 Bitmap 复用池中获取对应可以被复用的 Bitmap 对象 1.Android 2.3.3(API 级别 10)及以 ...

  9. day11 - 15(装饰器、生成器、迭代器、内置函数、推导式)

    day11:装饰器(装饰器形成.装饰器作用.@语法糖.原则.固定模式) 装饰器形成:最简单的.有返回值的.有一个参数的.万能参数 函数起的作用:装饰器用于在已经完成的函数前后增加功能 语法糖:使代码变 ...

  10. 装饰器,生成器,迭代器

    文章目录 装饰器 什么是装饰器 为什么使用装饰器 装饰器的使用场景 用户认证,判断用户是否登录 计算函数运行时间(算是一个功能,在项目中用的不多) 记录日志 redis缓存 装饰器1----能够适应9 ...

最新文章

  1. select刷新后保存原先选择的信息
  2. 数据采集技术python网络爬虫项目化教程_数据采集技术Python网络爬虫项目化教程 黄锐军课程资源.zip-KC17.pptx...
  3. 怎么缩小界面_188M的PPT,我是怎么把它压缩成18M的?这三个方法很少人知道
  4. image 闪烁 c# ajax updatepanel,Why doesn't asp:UpdatePanel refresh an Image?
  5. go 在windows下使用redis
  6. EJB+JSF开发示例(附源码)
  7. mac m1 php,【php】Macbook m1 Big Sur 安装php7.1 mondodb 折腾记
  8. JavaWeb——mybatis模糊查询与主键返回
  9. SpringCloud系列之Nacos+Dubbo+Seata应用篇
  10. 传说中的80后的17条潜规则,你占了几条...
  11. oracle solaris翻译,详解Oracle云操作系统Solaris 11.2
  12. 抖音热门音乐整理合集歌曲打包分享
  13. html网页效果跳动的心
  14. Linux 下 TC 命令原理及详解<一>
  15. springBoot redis开发的Java快递代拿系统(含人脸识别,验证码登录)
  16. 宏基笔记本电脑怎么进入bios设置功能按键图解
  17. 某工控图片上传服务 CPU 爆高分析
  18. PS长图快速切片_ps基础(PS常用工具详解一)
  19. 计算机主机的是指什么,电脑基本操作包括哪些 电脑的基本的操作是指什么
  20. 针对 Telnet 协议的威胁观察

热门文章

  1. 战舰世界换服务器改什么文件,战舰世界国服更新账号继承并合区,直营服已更新092...
  2. linux运行proxmark3,Linux 下编译使用Proxmark3
  3. 【MATLAB】MATLAB 仿真 — 模拟调制系统 之 AM 调制过程
  4. rclone 实现 GoogleDrive 同步至 OneDrive
  5. 微信Android热补丁方案Tinker
  6. Python基础更新
  7. POI导出Excel设置自适应列宽
  8. 商品归类查询服务_喜报 | 东泽国际获批进出口商品归类服务单位资质
  9. A银行B分行零售营销人员激励机制研究
  10. 高德纳(Donald Knuth)语录