你是否碰到你的收藏夹凌乱不堪,或者很多收藏网页地址虽然分类,可是使用起来却感觉不太好,有没有想过把你的收藏夹内容自动生成一个网页的导航页面生成类似Hao123(http://www.hao123.com/),或者番茄花园导航(http://www.tomatolei.com/)一样的网页,用来迅速导航到自己的网址呢?

即使使用场景有争议,不过我们也来关注一下这种自动生成页面的技术吧,说不定可以使用在合适的环境下,如下面我测试了两个类别的收藏夹Favorite目录下,其中“搜索引擎”和“新闻网络”两个目录是我的测试收藏夹分类,Icon和Images是我构造生成主页所需要的一些内容目录。我们根据Index.htm来生成index.htm来作为导航的主页面。

由于我们不想改变收藏夹的IE快捷方式的内容,因此收藏夹里面的内容还是以IE快捷方式来保存,如下图所示。

其中IE快捷方式的内容如下所示,文件时采用INI格式进行保存的。

[DEFAULT]
BASEURL=http://g.cn
[InternetShortcut]
URL=http://g.cn

其中的Default中的BaseURL是域名地址,InternetShortcut中的URL是具体的网页地址,基本上这些内容就可以构造成一个IE快捷方式了。

整体运行的效果如下图所示。其中内容可以动态生成,由于采用了NVelocity引擎来生成内容,速度非常快,和你直接浏览一个html页面的速度相差无几。

下面我们来具体介绍下如何实现这个页面的自动生成吧。

单击Home主页的时候,我们就自动生成一个页面,生成代码如下所示。

代码

        /// <summary>
        /// 导航到主页面
        /// </summary>
        public void GoHome()
        {
            string tempFile = "Favorite/index.txt";
            try
            {
                HelperClassAdapter helper = new HelperClassAdapter(tempFile);
                helper.Execute();
                //MessageUtil.ShowTips("生成成功");

bool found = false;
                foreach (IDockContent content in this.dockPanel.Documents)
                {
                    MainIE form = content as MainIE;
                    if (form != null && form.extendedWebBrowser1.DocumentTitle == "收藏夹导航")
                    {
                        found = true;
                        form.Activate();
                        break;
                    }
                }
                if (!found)
                {
                    this._currentUrl = "my:home";
                    AddMainIE();
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                MessageUtil.ShowTips(ex.Message);
            }
        }

这里其实主要的就是生成代码的类HelperClassAdapter,这个类通过获得模版文件,通过Nevelocity引擎把指定格式的内容附加到模版文件中,然后输出文件即可。

代码

    public class HelperClassAdapter : AbstractAdapter
    {
        public HelperClassAdapter(string templateFile)
            : base(templateFile)
        {
        }

public override void Execute()
        {
            string startPath = Path.Combine(Application.StartupPath, "Favorite");
            if (!Directory.Exists(startPath))
            {
                Directory.CreateDirectory(startPath);
            }

//遍历目录和文件,根据文件模版输出到文件中

#region 根据目录放置的字典
            Dictionary<string, List<FavoriteInfo>> fileDict = new Dictionary<string, List<FavoriteInfo>>();
            string[] dirArray = Directory.GetDirectories(startPath);
            foreach (string dir in dirArray)
            {
                string dirName = new DirectoryInfo(dir).Name;
                if (dirName.ToLower() == "icon" || dirName.ToLower() == "images") //系统图标跳过
                    continue;

string[] fileArray = Directory.GetFiles(dir);
                List<FavoriteInfo> fileList = new List<FavoriteInfo>();
                FavoriteInfo info = null;
                foreach (string file in fileArray)
                {
                    if (!string.IsNullOrEmpty(file))
                    {
                        info = new FavoriteInfo();
                        info.Category = dirName;
                        info.Title = new FileInfo(file).Name.Replace(".url", "");

INIFileUtil iniUtil = new INIFileUtil(file);
                        info.Url = iniUtil.IniReadValue("InternetShortcut", "URL");

fileList.Add(info);
                    }

}
                if (!fileDict.ContainsKey(dir))
                {
                    fileDict.Add(dir, fileList);
                }
            } 
            #endregion

//设置输出文件名称和页面变量,然后输出文件
            this.FileNameOfOutput = Path.Combine(Application.StartupPath, "Favorite/index.htm");
            context.Put("FileDict", fileDict); 
            OutputFile();
        }
    }

其中模版文件index.txt文件很简单,部分关键代码如下所示,其中主要关注有$开始的运算符和变量,这些代码是实现对象到页面内容的转换的。其中#foreach($FavoriteList in ${FileDict.Values})是遍历里面的对象,进行循环处理的,语法也很简单。

代码

<DIV id=content>
  <!--/ sidebar--><!--/ board-->
<div class=box id=coolsites>
      <h2 align="center" class="style2">收藏夹导航<a class="" id=cslayout title=居中对齐/左对齐>居中对齐/左对齐</a></h2>
      <div id=list>
#foreach($FavoriteList in ${FileDict.Values})
        <dl>
#set($count = 0)
#foreach($FavoriteInfo in $FavoriteList)
#if($count==0)
          <dt><a href="#">[ ${FavoriteInfo.Category.ToString()} ]</a>
#end
#set($count = $count + 1)
          <dd><a href="${FavoriteInfo.Url.ToString()}">${FavoriteInfo.Title.ToString()}</a>
#end
        </dd></dl>
#end
      </div>
    </div>
  </div>

另外FavoriteInfo是一些基本属性的实体类,代码很简单:

代码

    public class FavoriteInfo
    {
        private string m_category;//目录分类名称
        private string m_title;//网页标题
        private string m_url;//网页链接

/// <summary>
        /// 目录分类名称
        /// </summary>
        public string Category
        {
            get { return m_category; }
            set { m_category = value; }
        }

/// <summary>
        /// 网页标题
        /// </summary>
        public string Title
        {
            get { return m_title; }
            set { m_title = value; }
        }

/// <summary>
        /// 网页链接
        /// </summary>
        public string Url
        {
            get { return m_url; }
            set { m_url = value; }
        }
    }

HelperClassAdapter的基类如下所示,主要是定义一些公共的属性变量及操作,方便被继承成各种类型的子类。

代码

    public abstract class AbstractAdapter : IAdapter
    {
        #region 保护成员变量

protected VelocityContext context;
        protected Template template;

protected string templateFile;

protected const string NVELOCITY_PROPERTY = "nvelocity.properties";

#endregion

#region 成员变量及公共属性

private string fileExtension = ".htm"; //输出的文件后缀名,如".cs"。
        private string directoryOfOutput = "Articles"; //输出文件的文件夹名称
        private string fileNameOfOutput; //输出的文件名称

/// <summary>
        /// 输出文件的文件夹名称, 如"Entity","Common"等
        /// </summary>
        public string DirectoryOfOutput
        {
            set { directoryOfOutput = value; }
            get { return directoryOfOutput; }
        }

/// <summary>
        /// 输出的文件名称. 如果想输出的文件为 "A.cs", 那么文件名为"A".
        /// 默认的文件名称为模板文件的名称,没有后缀名.
        /// </summary>
        public string FileNameOfOutput
        {
            set { fileNameOfOutput = value; }
            get { return fileNameOfOutput; }
        }

/// <summary>
        /// 输出的文件后缀名,如".cs"。
        /// </summary>
        public string FileExtension
        {
            get { return fileExtension; }
            set { fileExtension = value; }
        }

#endregion

/// <summary>
        /// 根据参数初始化基类的Adapter
        /// </summary>
        /// <param name="templateFile">模板文件名称</param>
        public AbstractAdapter(string templateFile)
        {
            #region 判断输入的参数是否有效

if (templateFile == null)
            {
                const string error = "Invalid parameter of templateFile.";

LogHelper.Error(error);
                throw new ArgumentException(error, "templateFile");
            }

#endregion

this.templateFile = templateFile;
          
            InitTemplateEngine(); //初始化模板引擎

fileNameOfOutput = GetFileNameFromTemplate(templateFile); // 默认情况下, 输出的文件名称为模板名称           
            directoryOfOutput = "Articles"; // 默认情况下,放到Common目录下面
        }

/// <summary>
        /// 创建输出到文件中的方法
        /// </summary>
        public virtual void Execute()
        {
        }

/// <summary>
        ///根据模板创建输出的文件
        /// </summary>
        public virtual void OutputFile()
        {
            if (template != null)
            {
                string filePath = Path.GetDirectoryName(this.fileNameOfOutput);
                DirectoryInfo dir = new DirectoryInfo(filePath);
                if (!dir.Exists)
                {
                    dir.Create();
                }

LogHelper.Debug(string.Format("Class file output path:{0}", this.fileNameOfOutput));
                using (StreamWriter writer = new StreamWriter(this.fileNameOfOutput, false))
                {
                    template.Merge(context, writer);
                }
            }
        }

/// <summary>
        /// 根据模板创建代码输出到字符串流中
        /// </summary>
        /// <returns>根据模板生成的代码</returns>
        public virtual string OutputString()
        {
            string code = string.Empty;

if (template != null)
            {
                using (StringWriter writer = new StringWriter())
                {
                    template.Merge(context, writer);
                    code =  writer.GetStringBuilder().ToString();
                }
            }
            return code;
        }

/// <summary>
        /// 初始化NVelocity模板引擎并加载程序的配置信息e
        /// </summary>
        protected void InitTemplateEngine()
        {
            Velocity.Init(NVELOCITY_PROPERTY);
            //Velocity.Init();

// Make a context object and populate with the data.  This is where the Velocity engine 
            // gets the data to resolve the references (ex. $foreignList) in the template
            context = new VelocityContext();

try
            {
                template = Velocity.GetTemplate(templateFile);
            }
            catch (ResourceNotFoundException re)
            {
                string error = string.Format("Cannot find template " + templateFile);

LogHelper.Error(error);
                throw new Exception(error, re);
            }
            catch (ParseErrorException pee)
            {
                string error = string.Format("Syntax error in template " + templateFile + ":" + pee.StackTrace);

LogHelper.Error(error);
                throw new Exception(error, pee);
            }

}

#region 辅助方法

/// <summary>
        /// 从模板文件名称获取输出文件名的方法
        /// </summary>
        /// <param name="templateFileName">带后缀名的模板文件名</param>
        /// <returns>输出的文件名(无后缀名)</returns>
        private string GetFileNameFromTemplate(string templateFileName)
        {
            int sindex1 = templateFileName.LastIndexOf('/');
            int sindex2 = templateFileName.LastIndexOf('\\');

int sindex = (sindex1 > sindex2) ? sindex1 : sindex2;
            int eindex = templateFileName.IndexOf('.');

if (sindex < eindex)
            {
                return templateFileName.Substring(sindex + 1, eindex - sindex - 1);
            }
            else
            {
                return templateFileName.Substring(sindex);
            }
        }

#endregion
    }

    public interface IAdapter
    {
        /// <summary>
        /// 创建输出到文件中的方法
        /// </summary>
        void Execute();
    }

另外,读取INI文件,需要的辅助类代码INIFileUtil如下所示。

代码

    public class INIFileUtil
    {
        public string path;

public INIFileUtil(string INIPath)
        {
            path = INIPath;
        }

[DllImport("kernel32")]
        private static extern long WritePrivateProfileString(string section,string key,string val,string filePath);

[DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section,string key,string def, StringBuilder retVal,int size,string filePath);

[DllImport("kernel32")]
        private static extern int GetPrivateProfileString(string section, string key, string defVal, Byte[] retVal, int size, string filePath);

/// <summary>
        /// 写INI文件
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <param name="Value"></param>
        public void IniWriteValue(string Section,string Key,string Value)
        {
            WritePrivateProfileString(Section,Key,Value,this.path);
        }

/// <summary>
        /// 读取INI文件
        /// </summary>
        /// <param name="Section"></param>
        /// <param name="Key"></param>
        /// <returns></returns>
        public string IniReadValue(string Section,string Key)
        {
            StringBuilder temp = new StringBuilder(255);
            int i = GetPrivateProfileString(Section,Key,"",temp, 255, this.path);
            return temp.ToString();
        }

public byte[] IniReadValues(string section, string key)
        {
            byte[] temp = new byte[255];
            int i = GetPrivateProfileString(section, key, "", temp, 255, this.path);
            return temp;

}

/// <summary>
        /// 删除ini文件下所有段落
        /// </summary>
        public void ClearAllSection()
        {
            IniWriteValue(null,null,null);
        }
        /// <summary>
        /// 删除ini文件下personal段落下的所有键
        /// </summary>
        /// <param name="Section"></param>
        public void ClearSection(string Section)
        {
            IniWriteValue(Section,null,null);
        }
    }

使用NVelocity自动生成Favorite收藏夹的导航页面相关推荐

  1. python制作相册_《自拍教程73》Python 自动生成相册文件夹

    这里将告诉您<自拍教程73>Python 自动生成相册文件夹,具体操作过程:案例故事: 接Python mediainfo批量重命名图片文件,测试图片是批量重命名好了, 但是将测试图片放于 ...

  2. VS2010 编译程序自动生成ipch文件夹和.sdf文件

    使用VS2010编译C/C++代码时,在工程目录下会自动生成ipch文件夹和.sdf文件,它们所占的内存很大,往往从10M到上100M不等,是VS用来保存预编译的头文件和自动补全功能分析代码数据.删掉 ...

  3. 自动生成excel中sheet目录导航

    自动生成excel中sheet目录导航: 1.alt+f11 2.插入-模版 Sub mulu() On Error GoTo Tuichu Dim i As Integer Dim ShtCount ...

  4. python做相册_《自拍教程73》Python 自动生成相册文件夹

    案例故事: 接Python mediainfo批量重命名图片文件,测试图片是批量重命名好了, 但是将测试图片放于一个文件夹相册,图库App并不能显示图片信息, 为了测试的方便性, 需要把图片放到对应的 ...

  5. 在WPS中利用wordVBA实现批量识别题目数量和自动生成序号,方便在导航窗格中进行拖动排序

    原来的文件 运行程序后的效果 主要代码如下: Sub 批量插入题目编号() '快捷键ALT+1Dim i As Integer批量五号加粗设置为标题3'timuCount = CInt(InputBo ...

  6. android接入高德API,生成正式包后,导航页面闪退

    添加如下混淆,可防止,出现问题,记录一下,希望对别人有帮助. #3D 地图 V5.0.0之前: -keep class com.amap.api.maps.{;} -keep class com.au ...

  7. 文件夹自动生成html画廊,【桌面自动生成文件夹】桌面自动生成网站_桌面自动生成tmp文件-系统城...

    2017-01-26 13:59:36 浏览量:11190 有的用户发现自己的电脑系统中,总是会在桌面上生成一个名称为MobileFile的文件夹.其实,这个MobileFile文件夹是QQ相关的文件 ...

  8. make--变量与函数的综合示例 自动生成依赖关系

    一.变量与函数的示例 示例的要求 1.自动生成target文件夹存放可执行文件 2.自动生成objs文件夹存放编译生成的目标文件 3.支持调试版本的编译选项 4.考虑代码的扩展性 完成该示例所需的 1 ...

  9. sap 新建事务_SAP GUI里的收藏夹事务码管理工具

    本文是2020年第13篇原创文章,也是汪子熙公众号总共第196篇原创文章. 今天是2020年1月20日,农历大年二十六,年味渐浓. Jerry的老家,从成都乘坐高铁只要十五分钟就能到达,所以从来不会遭 ...

最新文章

  1. telnet时显示:允许更多到 telnet 服务器的连接。请稍候再试
  2. JavaScript内置函数及API
  3. 使用elementui实现表单上传功能_使用ElementUI中的upload组件上传Excel文件
  4. GBDT(MART) 迭代决策树入门教程 | 简介 .
  5. Android 监听Home键
  6. 【Java代码】Lamda表达式将List对象中的Map对象的key全部转化为大写或者小写【去除外层循环:可用于Map对象中的key全部转化为大写或者小写】
  7. java带参数的构造方法_看了Java的Class的源码,我自闭了
  8. leetcode 88
  9. Nodejs 操作 MongoDb 数据库
  10. 多线程编程学习笔记——使用并发集合(三)
  11. 数据结构之图的遍历:广度优先遍历(BFS)
  12. Android之控件与布局,结构知识点,基础完结
  13. 饱暖思淫欲之美女图片的Python爬虫实例(一)
  14. 操盘软件富赢版V7 2016正式版
  15. java计算机毕业设计西安市城市绿地管理系统源码+系统+数据库+lw文档
  16. 威富通 php,关于威富通的微信扫码支付处理思路和流程
  17. TypeError: can only concatenate list (not “int“) to list
  18. 麻省理工大学公开课笔记:算法导论(二)——课程简介及算法分析
  19. android 备份qcn文件,关于efs文件的qcn备份
  20. 约瑟夫环-猴子选大王(变型题)

热门文章

  1. 【队列源码研究】消息队列beanstalkd源码详解
  2. CentOS 6.5下Redis安装配置记录
  3. 鱼缸式百分比信息图表,这样计算才正确
  4. 面试题6--利用前序和中序遍历重构二叉树--递归方法
  5. SpringMVC源码解析 - HandlerAdapter - HandlerMethodArgumentResolver
  6. RHEL6.4换CentOS源
  7. ruby on rails 之 延时执行代码
  8. .net开发框架比较
  9. 数据结构与算法:二分查找
  10. 反编译插件jadclips