2008年3月5日
stringTemplate是一个模板引擎,同时支持java,C#,Python. 大家可以从
http://www.stringtemplate.org/下载.
StringTemplate 语法说明
StringTemplate的语法是以$xxxx$来进行分割的. stringtemplate关键写是区分大小写的.
属性引用
名称属性
在模板中,这个是最常用的一个属性.用于显示文字.如下:
你的邮件地址:$email$
替换属性名为email的值.
同一个属性可以有多个值,多个值的语法如下
$value;null="xxx",separator=", "$
定义value属性,当value为null则显示xxx.如果有多个属性值则以,号分开
字段引用
如果一个属性名称是对象或集合.可以用 属性名称.字段名 访问字段值
例如:
你的姓名: $人.姓名$
你的邮件:$人.邮件$
使用语法: $对象名.字段名$
在C#可以直接将一个对象设置到一个属性名称中.
如:
User us = new User();
us.Name = "xxsssx";
us.Value ="80";
StringTemplate st = new StringTemplate("$User.Name$,$User.Value$");
st.SetAttribute("User", us);
Console.WriteLine(st.ToString());
对于键/值对象,也同样使用上面方式进行访问如:
StringTemplate a = new StringTemplate("$user.name$, $user.phone$");
Hashtable user = new Hashtable();
user.Add("name", "Terence");
user.Add("phone", "none-of-your-business");
a.SetAttribute("user", user);
string results = a.ToString();
自定义属性字段名
格式: $属性名:{it.字段名}$
例如:
StringTemplate st = new StringTemplate("$abcdef:{第一个: $it.ddddd$ 第二个:$it.ddddd$}$");
st.SetAttribute("abcdef.{ddddd,ddddd}","中国人", "我不来了");
Console.WriteLine(st.ToString());
如果字段名是保留字,可以使用$对象名.("保留字")$
一次显示多个属性
$[属性名,属性名]$
模板引用
必需把模板加入同一个模板组,才能相互之间调用模板.
通过$模板名()$来调用模板
模板传参数
$模板名(参数名=参数值,参数名=参数值)$
例如:
StringTemplateGroup Group = new StringTemplateGroup("Temp");
Group.DefineTemplate("link", "<a href='$url$'>$title$</a>");
StringTemplate st = new StringTemplate(Group, "调用link模板,显示链接 $link(url=\"/faq/view?ID=\"+faqid, title=faqtitle)$ ,真的啊!");
st.SetAttribute("faqid", 1);
st.SetAttribute("title","中华人民共和国");
Console.WriteLine(st.ToString());
循环显示使用
User us = new User();
us.Name = "哈哈";
us.Value = "99";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
uss.Add(us);
StringTemplate st = new StringTemplate("<table>$User:{<tr>$it.Name$<td></td>$it.Value$</tr>}$</table>");
st.SetAttribute("User", uss);
Console.WriteLine(st.ToString());
通过模板交替显示
StringTemplateGroup group = new StringTemplateGroup("Test");
group.DefineTemplate("TrRed", "<tr class=red><td>$it.name$</td><td>$it.value$</td></tr>\n");
group.DefineTemplate("TrWither", "<tr class=wither><td>$it.name$</td><td>$it.value$</td></tr>\n");
StringTemplate st = new StringTemplate(group, "<table>$User:TrRed(),TrWither()$</table>");
User us = new User();
us.Name = "哈哈哈";
us.Value = "999";
List<User> uss = new List<User>();
uss.Add(us);
uss.Add(us);
uss.Add(us);
st.SetAttribute("User", uss);
Console.WriteLine(st.ToString());
例子教程下载:下载
附:英文语法介绍
|
Syntax
|
Description
|
|
<attribute>
|
Evaluates to the value of attribute.ToString() if it exists else empty string.
|
|
<i>, <i0>
|
The iteration number indexed from one and from zero, respectively, when referenced within a template being applied to an attribute or attributes.
|
|
<attribute.property>
|
Looks for property of attribute as a property (C#), then accessor methods like getProperty() or isProperty(). If that fails, StringTemplate looks for a raw field of the attribute called property. Evaluates to the empty string if no such property is found.
|
|
<attribute.(expr)>
|
Indirect property lookup. Same as attribute.property except use the value of expr as the property_ name. Evaluates to the empty string if no such property is found.
|
|
<multi-valued-attribute>
|
Concatenation of ToString() invoked on each element. If multi-valued-attribute is missing his evaluates to the empty string.
|
|
<multi-valued-attribute; separator=expr>
|
Concatenation of ToString() invoked on each element separated by expr.
|
|
<template(argument-list)>
|
Include template. The argument-list is a list of attribute assignments where each assignment is of the form arg-of-template=expr where expr is evaluated in the context of the surrounding template
not of the invoked template.
|
|
<(expr)(argument-list)>
|
Include template whose name is computed via expr. The argument-list is a list of attribute assignments where each assignment is of the form attribute=expr. Example $(whichFormat)()$ looks up whichFormat's value and uses that as template name. Can also apply an indirect template to an attribute.
|
|
<attribute:template(argument-list)>
|
Apply template to attribute. The optional argument-list is evaluated before application so that you can set attributes referenced within template. The default attribute it is set to the value of attribute. If attribute is multi-valued, then it is set to each element in turn and template is invoked n times where n is the number of values in attribute. Example: $name:bold() applies bold() to name's value.
|
|
<attribute:(expr)(argument-list)>
|
Apply a template, whose name is computed from expr, to each value of attribute. Example $data:(name)()$ looks up name's value and uses that as template name to apply to data.
|
|
<attribute:t1(argument-list): ... :tN(argument-list)>
|
Apply multiple templates in order from left to right. The result of a template application upon a multi-valued attribute is another multi-valued attribute. The overall expression evaluates to the concatenation of all elements of the final multi-valued attribute resulting from templateN's application.
|
|
<attribute:{anonymous-template}>
|
Apply an anonymous template to each element of attribute. The iterated it atribute is set automatically.
|
|
<attribute:{argument-name_ | _anonymous-template}>
|
Apply an anonymous template to each element of attribute. Set the argument-name to the iterated value and also set it.
|
|
<a1,a2,...,aN:{argument-list_ | _anonymous-template}>
|
Parallel list iteration. March through the values of the attributes a1..aN, setting the values to the arguments in argument-list in the same order. Apply the anonymous template. There is no defined it value unless inherited from an enclosing scope.
|
|
<attribute:t1(),t2(),...,tN()>
|
Apply an alternating list of templates to the elements of attribute. The template names may include argument lists.
|
|
<if(attribute)>subtemplate
<else>subtemplate2
<endif>
|
If attribute has a value or is a bool object that evaluates to true, include subtemplate else include subtemplate2. These conditionals may be nested.
|
|
<if(!attribute)>subtemplate<endif>
|
If attribute has no value or is a bool object that evaluates to false, include subtemplate. These conditionals may be nested.
|
|
<first(attr)>
|
The first or only element of attr. You can combine operations to say things like first(rest(names)) to get second element.
|
|
<last(attr)>
|
The last or only element of attr.
|
|
<rest(attr)>
|
All but the first element of attr. Returns nothing if $attr$ a single valued.
|
|
<strip(attr)>
|
Returns an iterator that skips any null values in $attr$. strip
=x when x is a single-valued attribute.
|
|
<length(attr)>
|
Return an integer indicating how many elements in length $attr$ is. Single valued attributes return 1. Strings are not special; i.e., length("foo") is 1 meaning "1 attribute". Nulls are counted in lists so a list of 300 nulls is length 300. If you don't want to count nulls, use length(strip(list)).
|
|
\$ or \<
|
escaped delimiter prevents $ or < from starting an attribute expression and results in that single character.
|
|
<\ >, <\n>, <\t>, <\r>
|
special characters: space, newline, tab, carriage return.
|
|
<! comment !>, $! comment !$
|
Comments, ignored by StringTemplate
|
- 把资源文件的生成操作设为嵌入的资源
- 然后将下面这行
[assembly: WebResource("NPao.Control.Resource.DateDropDownList.js", "text/javascript")]
添加到在assemblyinfo.cs中。其实这个语句放任何cs文件里,保证放在最高级namespace外就行
DateDropDownList.js是资源名字,比如项目的Default namespace是“NPao.Control”,
而文件DateDropDownList.js放在/Resource目录中,那么完整资源名就是NPao.Control.Resource.DateDropDownList.js
- 然后在程序中调用如下:
Image1.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(this.GetType(), "wuChang.WebControls.images.MessagePanel_info.gif");
摘要: 最近在重构公司的电子商务网站,其中有个打折消费的功能.这里简单介绍下,比如,网站搞活动买二送一(以下称A),或者买二瓶其中价格低的一瓶半价(以下称B),.最初的设计是很粗糙的,因为之前网站是没有活动,后来增加一个活动,现在又要增加新的活动.从一开始的直接写代码,到后来的if else 判断打折条件,到现在又要添加新的打折,觉得这样的代码写的很粗糙,有种不爽的感觉.现在刚好有机会重构这里,就大概设计...
阅读全文
- 什么是对象?对象是一个自包含的实体,用一组可识别的特性和行为来标识.
- 什么是类? 类是具有相同属性和功能的对象的抽象的集合.
- 什么是实例?实例就是一个真实的对象.实例化就是创建对象的过程,用new关键字来创建.new关键字用来在内存中申请一个空间存放数据.
- 构造函数 默认一个无参数的构造函数,在new class的时候调用
- 方法重载 可在不改变原方法的基础上增加功能,方法名相同,参数类型或个数有所不同
- 字段是存储类要满足其设计所需要的数据,是与类相关的变量
- 属性是一个方法,但在调用他们的代码看来他是一个字段,属性适合以字段的方式使用方法调用的场合(使用属性可以设置符合要求的的字段的值)
- Public 允许任何类访问 private 仅允许同一个类的成员访问,他的子类也不能访问,定义变量时默认为private,protected的子类可以访问基类
- 封装:每个对象都包含它能进行操作所需要的所有信息,因此对象不必依赖其他对象来完成自己的操作 好处,减少耦合,内部可自由修改,具有清晰的对外接口
继承代表了一种 "is-a"的关系,还可以理解为是对被继承者的特殊化,除了具备被继承者的特性外,还具备有自己的独有个性,他定义类之间如何关联共享.
- 子类拥有父类非private的属性和功能
- 子类可以扩展父类没有的属性和功能
- 子类还可以以自己的方式实现父类的功能(方法重写)
- 子类不能继承基类的构造方法,只能被调用,可以使用base关键词
- 继承使得所有子类公共的部分都放在了父类,使得代码得到共享,避免重复
- 使得修改或扩展变得容易
- 缺点,父类变则子类不得不变,破坏封装,父类实现的细节暴露给子类
- 强耦合的关系,当2个类具备is-a的关系时,就可以考虑用继承
多态表示不同的对象可以执行相同的操作,但要通过他们自己的实现代码执行
- 子类以父类的身份出现
- 子类工作的时候以自己的方式来实现
- 子类以父类的身份出现的时候,子类特有的属性和方法不可以再使用
- 虚方法 virtual 为了让子类的实例完全接替来自父类的类成员,父类必须将该成员声明称虚拟的, 虚方法是按照运行时类型而非编译时类型进行动态绑定调用
- 子类可以选择使用override关键字,来实现替换父类的实现,方法重写
抽象类
- 类和方法前加上abstract,即抽象类和抽象方法
- 抽象类不能实例化
- 抽象方法是必须被子类重写的方法
- 如果类中包含有抽象方法,那么类就必须定义为抽象类,不论是否还包含有其他一般方法
- 抽象类拥有尽可能多的共同代码,拥有尽可能少的数据
- 抽象类通常代表一个抽象概念,他提供一个继承的出发点,当设计一个新的抽象类时,一定是用来继承的.
接口是把隐式公共方法和属性组合起来,以封装特定功能的一个集合
- 实现接口类就必须实现接口中的所以方法和属性
- 一个类可以实现多个接口
- 接口中的方法或属性前面不能有修饰符,方法没有方法体
抽象类与接口的区别
- 抽象类可以给出一些成员的实现,接口却不包含成员的实现
- 抽象类中的成员可以被子类实现,而接口的成员需要类完成实现
- 一个类只能继承一个抽象类,而可以接受多个接口
- 类是对对象的抽象,抽象类是对类的抽象,接口是对行为的抽象
- 如果行为跨越不同类的对象,可使用接口,对于一些相似的类对象,用继承抽象类
- 从设计角度讲,抽象类是从子类中发现了公共的东西,泛化出父类,然后子类继承父类,而接口是根本不知道子类的存在,方法如何实现还不确认,预先定义
- 通过重构改善既有代码设计
泛型是具有占位符的类接口结构和方法
- 使用泛型不需要装箱拆箱
委托与事件
- 委托是对函数的封装,可以当作给方法的特征指定一个名称.而事件是委托的一种特殊形式,当发生有意义的事情时,事件对象处理通知过程
- 委托是一种引用方法的类型,一旦为委托分配了方法,委托将与方法具有相同的行为
- 在发生其他类或对象关注的事情时,类或对象可通过事件通知他们
最近买了园子里一位大哥出的书,大话设计模式,之前也买过园子里的几本书,比如设计之道,道不远人等,怎么发现里面都有个道字
道不远人也是刚刚到手,还没来得及看,
大话设计模式已经由当当送出.
2本书拿到手上一比,道不远人那个厚啊,还是先从薄的开始看起吧^^
话说好记性不如烂笔头,之前看过很多书,当时看了现在就忘了,要记录下点学习笔记了,这个是开篇,要逐步记录下读书笔记
看看自己有没毅力哈
最近要给公司的电子商务网站添加个圈子的功能.网站功能本来就包含有新闻发布,会员管理,商品购物,后台管理等,现在又要再加上圈子的功能,网站项目越来越复
杂,每次编译生成的dll超过100k.这样每次修改任何一个功能中的任何一个小问题都要上传整个dll,并导致整个website的首次访问的重新编译.
之前也曾经想过,这些功能根据不同处于项目中的不同文件夹内,比如会员的会在member,后台管理的会在admin文件夹,新闻的会在news文件夹.这样的话如果vs支持按不同文件夹生成不同dll,那我每次修改不同功能的不同文件只要上传对应的dll就可以了,不再需要上传整个website的dll.
不过想法是美好的,事实是残酷的.vs并不支持这样的功能.所以在功能直接交互和文件共享并不多的功能上,我采取了重新建立一个projects的方法,比如把后台管理剥离出来,新建一个admin的website,这个新的projects放在website的根目录下,然后修改文件编译生成dll后的目录为..\bin并且删除项目中的web.config.编译后访问,呵呵,真的可以访问了,并且达到了拆分项目的要求.倒是并不完美,还有手动修改很多设置,并且这2个项目中不能共享相同的master,和usercontrol,甚至是图片,js等,如果直接使用相对路径,那么视图模式下将不能正常显示,如果vs直接提供新建子项目的功能并能解决共享这些文件,该有多好啊.
于是通过Google,找到一篇文章http://blogs.msdn.com/webdevtools/archive/2006/07/01/652986.aspx,Creating sub-projects in IIS with Web Application Projects,不幸的是文中提到的“Web Application Projects” add-in,我Download了,but can't install!
虽然这样的应用程序我们无法制作,但是我们可以按照他的思路自己修改配置啊.
发现他的方法,跟一开始我的做法是很类似的,不过他可以共享master和user control,为什么我的不能呢?
仔细翻看了一下,发现原来他在子项目中创建了虚拟目录比如 http://localhost/group,所以之前使用~/Group.Master,只能访问本项目中的master,而现在则可以访问根目录中的master了,试试usercontrol,也可以了,呵呵,原理奥妙都在这个虚拟目录中呀.
不过最后,还是觉得这样的方式不是很舒服,不知道大家有没什么好的办法,我在这里抛下砖.
本来想发在新手区的,但是我觉得这个应该是大部分程序员都会遇到的问题,把Web 应用程序分解为多个较小项目也有很多优点,不知道各位达人平时如何解决的?
如果大家觉得放在首页不合适的话,我也会移开.
本以为蜘蛛很简单,根据一个url,抓取到html内容,然后根据正则匹配数据入库.却发现,越看资料越复杂,蜘蛛应该根据抓取相似页面自动生成抓取模板,而且蜘蛛还要支持cookies和会自登录等多种协议.
页面解析方面,也不是简单的获得标题和内容那么简单,还要做dom解析,js解析,模拟浏览器的可视化抓取等等.
先从页面数据的抽取这方面入手研究吧.
本文仅记录一些简单的使用方法,供初学者参考。
以下例子采用 Lucene.NET 1.9 版本,可取去 Lucene.Net 下载。
1. 基本应用
using System;
using System.Collections.Generic;
using System.Text;
using Lucene.Net;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Standard;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.QueryParsers;
using Lucene.Net.Search;
using Lucene.Net.Store;
using Lucene.Net.Util;
namespace ConsoleApplication1.Lucene
{
public class LuceneTest
{
private const string FieldName = "name";
private const string FieldValue = "value";
private Directory directory = new RAMDirectory();
private Analyzer analyzer = new StandardAnalyzer();
public LuceneTest()
{
}
private void Index()
{
IndexWriter writer = new IndexWriter(directory, analyzer, true);
writer.maxFieldLength = 1000;
for (int i = 1; i <= 100; i++)
{
Document document = new Document();
document.Add(new Field(FieldName, "name" + i, Field.Store.YES, Field.Index.UN_TOKENIZED));
document.Add(new Field(FieldValue, "Hello, World!", Field.Store.YES, Field.Index.TOKENIZED));
writer.AddDocument(document);
}
writer.Optimize();
writer.Close();
}
private void Search()
{
Query query = QueryParser.Parse("name*", FieldName, analyzer);
IndexSearcher searcher = new IndexSearcher(directory);
Hits hits = searcher.Search(query);
Console.WriteLine("符合条件记录:{0}; 索引库记录总数:{1}", hits.Length(), searcher.Reader.NumDocs());
for (int i = 0; i < hits.Length(); i++)
{
int docId = hits.Id(i);
string name = hits.Doc(i).Get(FieldName);
string value = hits.Doc(i).Get(FieldValue);
float score = hits.Score(i);
Console.WriteLine("{0}: DocId:{1}; Name:{2}; Value:{3}; Score:{4}",
i + 1, docId, name, value, score);
}
searcher.Close();
}
}
}
除了 RAMDirectory,还可以使用 FSDirectory。(注意 FSDirectory.GetDirectory 的 create 参数,为 true 时将删除已有索引库文件,可以通过 IndexReader.IndexExists() 方法判断。)
从指定目录打开已有索引库。
private Directory directory = FSDirectory.GetDirectory("c:\index", false);
将索引库载入内存,以提高搜索速度。
private Directory directory = new RAMDirectory(FSDirectory.GetDirectory(@"c:\index", false));
//或
//private Directory directory = new RAMDirectory(c:\index");
2. 多字段搜索
使用 MultiFieldQueryParser 可以指定多个搜索字段。
Query query = MultiFieldQueryParser.Parse("name*", new string[] { FieldName, FieldValue }, analyzer);
IndexReader reader = IndexReader.Open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);
3. 多条件搜索
除了使用 QueryParser.Parse 分解复杂的搜索语法外,还可以通过组合多个 Query 来达到目的。
Query query1 = new TermQuery(new Term(FieldValue, "name1")); // 词语搜索
Query query2 = new WildcardQuery(new Term(FieldName, "name*")); // 通配符
//Query query3 = new PrefixQuery(new Term(FieldName, "name1")); // 字段搜索 Field:Keyword,自动在结尾添加 *
//Query query4 = new RangeQuery(new Term(FieldNumber, NumberTools.LongToString(11L)), new Term(FieldNumber, NumberTools.LongToString(13L)), true); // 范围搜索
//Query query5 = new FilteredQuery(query, filter); // 带过滤条件的搜索
BooleanQuery query = new BooleanQuery();
query.Add(query1, BooleanClause.Occur.MUST);
query.Add(query2, BooleanClause.Occur.MUST);
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);
4. 设置权重
可以给 Document 和 Field 增加权重(Boost),使其在搜索结果排名更加靠前。缺省情况下,搜索结果以 Document.Score 作为排序依据,该数值越大排名越靠前。Boost 缺省值为 1。
Score = Score * Boost
通过上面的公式,我们就可以设置不同的权重来影响排名。
如下面的例子中根据 VIP 级别设定不同的权重。
Document document = new Document();
switch (vip)
{
case VIP.Gold: document.SetBoost(2F); break;
case VIP.Argentine: document.SetBoost(1.5F); break;
}
只要 Boost 足够大,那么就可以让某个命中结果永远排第一位,这就是百度等网站的"收费排名"业务。明显有失公平,鄙视一把。
5. 排序
通过 SortField 的构造参数,我们可以设置排序字段,排序条件,以及倒排。
Sort sort = new Sort(new SortField(FieldName, SortField.DOC, false));
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query, sort);
排序对搜索速度影响还是很大的,尽可能不要使用多个排序条件。
6. 过滤
使用 Filter 对搜索结果进行过滤,可以获得更小范围内更精确的结果。
举个例子,我们搜索上架时间在 2005-10-1 到 2005-10-30 之间的商品。
对于日期时间,我们需要转换一下才能添加到索引库,同时还必须是索引字段。
// index
document.Add(FieldDate, DateField.DateToString(date), Field.Store.YES, Field.Index.UN_TOKENIZED);
//...
// search
Filter filter = new DateFilter(FieldDate, DateTime.Parse("2005-10-1"), DateTime.Parse("2005-10-30"));
Hits hits = searcher.Search(query, filter);
除了日期时间,还可以使用整数。比如搜索价格在 100 ~ 200 之间的商品。
Lucene.Net NumberTools 对于数字进行了补位处理,如果需要使用浮点数可以自己参考源码进行。
// index
document.Add(new Field(FieldNumber, NumberTools.LongToString((long)price), Field.Store.YES, Field.Index.UN_TOKENIZED));
//...
// search
Filter filter = new RangeFilter(FieldNumber, NumberTools.LongToString(100L), NumberTools.LongToString(200L), true, true);
Hits hits = searcher.Search(query, filter);
使用 Query 作为过滤条件。
QueryFilter filter = new QueryFilter(QueryParser.Parse("name2", FieldValue, analyzer));
我们还可以使用 FilteredQuery 进行多条件过滤。
Filter filter = new DateFilter(FieldDate, DateTime.Parse("2005-10-10"), DateTime.Parse("2005-10-15"));
Filter filter2 = new RangeFilter(FieldNumber, NumberTools.LongToString(11L), NumberTools.LongToString(13L), true, true);
Query query = QueryParser.Parse("name*", FieldName, analyzer);
query = new FilteredQuery(query, filter);
query = new FilteredQuery(query, filter2);
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);
7. 分布搜索
我们可以使用 MultiReader 或 MultiSearcher 搜索多个索引库。
MultiReader reader = new MultiReader(new IndexReader[] { IndexReader.Open(@"c:\index"), IndexReader.Open(@"\\server\index") });
IndexSearcher searcher = new IndexSearcher(reader);
Hits hits = searcher.Search(query);
或
IndexSearcher searcher1 = new IndexSearcher(reader1);
IndexSearcher searcher2 = new IndexSearcher(reader2);
MultiSearcher searcher = new MultiSearcher(new Searchable[] { searcher1, searcher2 });
Hits hits = searcher.Search(query);
还可以使用 ParallelMultiSearcher 进行多线程并行搜索。
8. 合并索引库
将 directory1 合并到 directory2 中。
Directory directory1 = FSDirectory.GetDirectory("index1", false);
Directory directory2 = FSDirectory.GetDirectory("index2", false);
IndexWriter writer = new IndexWriter(directory2, analyzer, false);
writer.AddIndexes(new Directory[] { directory });
Console.WriteLine(writer.DocCount());
writer.Close();
9. 显示搜索语法字符串
我们组合了很多种搜索条件,或许想看看与其对等的搜索语法串是什么样的。
BooleanQuery query = new BooleanQuery();
query.Add(query1, true, false);
query.Add(query2, true, false);
//...
Console.WriteLine("Syntax: {0}", query.ToString());
输出:
Syntax: +(name:name* value:name*) +number:[0000000000000000b TO 0000000000000000d]
呵呵,就这么简单。
10. 操作索引库
删除 (软删除,仅添加了删除标记。调用 IndexWriter.Optimize() 后真正删除。)
IndexReader reader = IndexReader.Open(directory);
// 删除指定序号(DocId)的 Document。
reader.Delete(123);
// 删除包含指定 Term 的 Document。
reader.Delete(new Term(FieldValue, "Hello"));
// 恢复软删除。
reader.UndeleteAll();
reader.Close();
增量更新 (只需将 create 参数设为 false,即可往现有索引库添加新数据。)
Directory directory = FSDirectory.GetDirectory("index", false);
IndexWriter writer = new IndexWriter(directory, analyzer, false);
writer.AddDocument(doc1);
writer.AddDocument(doc2);
writer.Optimize();
writer.Close();
11. 优化
批量向 FSDirectory 增加索引时,增大合并因子(mergeFactor )和最小文档合并数(minMergeDocs)有助于提高性能,减少索引时间。
IndexWriter writer = new IndexWriter(directory, analyzer, true);
writer.maxFieldLength = 1000; // 字段最大长度
writer.mergeFactor = 1000;
writer.minMergeDocs = 1000;
for (int i = 0; i < 10000; i++)
{
// Add Documentes...
}
writer.Optimize();
writer.Close();
相关参数说明
转自《深入 Lucene 索引机制》
利用 Lucene,在创建索引的工程中你可以充分利用机器的硬件资源来提高索引的效率。当你需要索引大量的文件时,你会注意到索引过程的瓶颈是在往磁盘上写索引文件的过程中。为了解决这个问题, Lucene 在内存中持有一块缓冲区。但我们如何控制 Lucene 的缓冲区呢?幸运的是,Lucene 的类 IndexWriter 提供了三个参数用来调整缓冲区的大小以及往磁盘上写索引文件的频率。
1.合并因子 (mergeFactor)
这个参数决定了在 Lucene 的一个索引块中可以存放多少文档以及把磁盘上的索引块合并成一个大的索引块的频率。比如,如果合并因子的值是 10,那么当内存中的文档数达到 10 的时候所有的文档都必须写到磁盘上的一个新的索引块中。并且,如果磁盘上的索引块的隔数达到 10 的话,这 10 个索引块会被合并成一个新的索引块。这个参数的默认值是 10,如果需要索引的文档数非常多的话这个值将是非常不合适的。对批处理的索引来讲,为这个参数赋一个比较大的值会得到比较好的索引效果。
2.最小合并文档数 (minMergeDocs)
这个参数也会影响索引的性能。它决定了内存中的文档数至少达到多少才能将它们写回磁盘。这个参数的默认值是10,如果你有足够的内存,那么将这个值尽量设的比较大一些将会显著的提高索引性能。
3.最大合并文档数 (maxMergeDocs)
这个参数决定了一个索引块中的最大的文档数。它的默认值是 Integer.MAX_VALUE,将这个参数设置为比较大的值可以提高索引效率和检索速度,由于该参数的默认值是整型的最大值,所以我们一般不需要改动这个参数。
1 联合两个索引查询,已解决:
IndexSearcher[] searchers = new IndexSearcher[2];
searchers[0] = new IndexSearcher(m_indexpath);
searchers[1] = new IndexSearcher(m_outindexpath);
MultiSearcher multiSearcher = new MultiSearcher(searchers);
2,还有个进行多条件搜索 and 与 or 的操作————
用 MultiFieldQueryParser
建议重新封装
MultiFieldQueryParser.Parser(p[],d[],f[],analyer) 成or 与 and操作合一
或者
BooleanQuery thisQuery = new BooleanQuery();
thisQuery.Add(query1,true,false);
thisQuery.Add(query2, false, false);
1,得到网页上的链接地址:
string matchString = @"<a[^>]+href=\s*(?:'(?<href>[^']+)'|""(?<href>[^""]+)""|(?<href>[^>\s]+))\s*[^>]*>";
2,得到网页的标题:
string matchString = @"<title>(?<title>.*)</title>";
3,去掉网页中的所有的html标记:
string temp = Regex.Replace(html, "<[^>]*>", ""); //html是一个要去除html标记的文档
4, string matchString = @"<title>([\S\s\t]*?)</title>";
Nutch 是基于 Lucene的。Lucene为 Nutch 提供了文本索引和搜索的API。一个常见的问题是;我应该使用Lucene还是Nutch?最简单的回答是:如果你不需要抓取数据的话,应该使用Lucene。常见的应用场合是:你有数据源,需要为这些数据提供一个搜索页面。在这种情况下,最好的方式是直接从数据库中取出数据并用Lucene API建立索引。Nutch 适用于你无法直接获取数据库中的网站,或者比较分散的数据源的情况下使用。
DotLucene的发展历史
Lucene-〉NLucene-〉Lucene.Net-〉DotLucene
Lucene 是一个基于 Java 的全文索引工具包,Lucene的贡献者 Doug Cutting 是一位资深全文索引/检索专家,曾经是 V-Twin 搜索引擎(Apple 的 Copland 操作系统的成就之一)的主要开发者,后在 Excite 担任高级系统架构设计师,目前从事于一些 Internet 底层架构的研究。他贡献出的 Lucene 的目标是为各种中小型应用程序加入全文检索功能。
Lucene 早先发布在作者自己的 http://www.lucene.com/,后来发布在 SourceForge,2001年年底成为 APACHE 基金会 Jakarta 的一个子项目。
已经有很多Java项目都使用了Lucene作为其后台的全文索引引擎,比较著名的有:
Jive:WEB论坛系统;
Eyebrows:邮件列表 HTML 归档/浏览/查询系统,本文的主要参考文档“TheLucene search engine: Powerful, flexible, and free”作者就是 EyeBrows 系统的主要开发者之一,而 EyeBrows 已经成为目前 APACHE 项目的主要邮件列表归档系统;
Cocoon:基于 XML 的 Web 发布框架,全文检索部分使用了Lucene;
Eclipse:基于 Java 的开放开发平台,帮助部分的全文索引使用了 Lucene。
以上信息来自http://www.chedong.com/tech/lucene.html
Lucene 本身不支持中文的索引,但它良好的架构设计,使得只需根据语言词法分析接口,增加一个中文解析器即可实现中文的索引。这一工作是由车东(http://www.chedong.com/)完成的:WebLucene 中提供了 CJKTokenizer,可以分析东亚文字
NLucene是将 Lucene 从 Java 移植到 .NET 的一个 SourceForge 项目,它从 Lucene 1.2 版本转化而来。
Lucene.Net因为 NLucene 项目到2002年就没有再推出新的版本,可Lucene 却一直在发展,于是有人把Lucene 1.3版移植到.NET就成了Lucene .NET。但是Lucene .Net发展到2.0版的时候变成了商业化的产品,脱离了开源项目。
DotLucene受到Lucene.Net脱离开源项目的影响,有人为了继续发展开源.Net搜索引擎,于是在Lucene.Net的原有基础上继续发展该项目,但是名字改成了DotLucene以区别于Lucene.Net。
目前基于Lucene.Net/DotLucene的项目有:
Lookout - Outlook插件,可以搜索邮件,联系人,计划任务,会议和文件夹。该公司已经被微软收购[免费]。
.Text - 著名的博客引擎[开源]。
Beagle – Mono基于DotLucene开发的桌面搜索引擎[开源]。
Ascirum - Windows SharePoint Services文档库的搜索解决方案 [商业]。
Cuyahoga - .NET 网站架构[开源]。
Tustena CRM - 客户关系管理服务器 [开源]。
Pali Text Reader - Pali 文本阅读程序软件是读取和为经典佛教pali 文本的学习工具[开源]。
SlopeTalk - 一个布鲁克林 (美国纽约市西南部的一区)斜坡公园的路线向导。
DotLucene官方网站:http://www.dotlucene.net
这几天看demo完成了一个简单的索引+搜索。网上大多数是dotLucene.net 的例子,而Lucene.Net 2.0 的很少,其实连 http://www.dotlucene.net/ 都关掉了,由于刚刚接触Lucene.net ,网上很多人说 Lucene.Net 从 2.0 开始就开始收费,其实,现在Lucene.net 又开始免费了。Lucene.net 现在成为apache 的开源项目 http://incubator.apache.org/projects/lucene.net.html 。我想也正因此,dotLucene.net 才关闭的吧。回想起这几天研究Lucene.net 很是奇怪,刚开始的2天,还在 dotlucene.net 上面找资料,可是这个星期一一看,竟然出现关闭页面。开始很紧张,以为唯一一个 .net 的开源Lucene也没了。后来一看作者的介绍才发现竟然在apache.org 有一个开源的项目。而且按照项目介绍,Lucene.net 是完全按照java版来翻译的,连索引文件都可以通用。这也坚定了我研究最新版的Lucene.net 的决心。
In addition to the APIs and classes port to C#, the algorithm of Java Lucene is ported to C# Lucene. This means an index created with Java Lucene is back-and-forth compatible with the C# Lucene; both at reading, writing and updating. In fact a Lucene index can be concurrently searched and updated using Java Lucene and C# Lucene processes.
今天全国默哀 网站首页都要变成灰色
给大家一个简单的解决办法 在首页的body中加上 style="FILTER: alphaopacity=80 gray"
大家也可以在自己的blog中定制css 使自己的blog也变成灰色的
暂时放下首页,一会撤下,大家一起来默哀!
公司是个电子商务网站,电子商务网站就要涉及到订单的处理及物流费用的统计.这里暂时说下物流费用的统计,订单的处理很早前就想写了,只是太懒惰了,呵呵.事先声明一下,本人只是新手,发的文章是希望大家指点的,光拍砖不给建议的,怕怕哦~~
先大概说下公司的情况,也好让大家明白这里物流计算的特殊性.我们公司是一家在线销售红酒的公司,众所周知,红酒,含有酒精且是易碎品,酒器酒具也是一样,各个地区,包括上海的不同区的快递费用都是不一一样的.而已根据不同地区,有的地方是按单收费,有的则是按瓶,而且不同地区达到不同金额则可以免除酒类的快递费用.而酒器酒具怎不能免除,因为酒器酒具属于易碎品,需要报价,而酒我们有安全包装.这样的话就会很麻烦,比如黄浦区的客户买了200元的酒和100元的酒具,那么黄浦区是超过100元免酒的运费,而酒具的不免.这些都是在一张订单里.如果是别的区则又是另外的规则.
首先分析一下,根据商品的不同物流分类别,根据商品单位的不同物流有不同的计算方法(按瓶,按单),不同地区有不同的价格,不同地区超过不同的价格则可以免除运费.我就按这样的要求设计了.

不知道大家有没更好的办法,尽情赐教~~
今天真是奇怪
http://www.cnblogs.com/netatomy/archive/2008/01/24/1050769.html 参考这个想给生成个CHM的帮助,
结果都生成完成后,跑到chm文件夹中什么文件都很齐全,唯独没有*.CHM这个文件.郁闷,难道是因为我装的是vs08或者我是vista?
实在没有办法,最后灵光一闪,所有文件都有,包括HTML,注释什么的都有了,我只要把他们都打包成chm文件就可以了啊,所以开始百度
最后找到了easy chm ,然后导入这些文件生成了帮助,大家看看,还不错吧,呵呵
如果谁遇到了和我一样的问题,可以跟我这个一样解决,或者哪位帅哥知道怎么解决,也有麻烦通告一下啊
摘要: 利用 SandCastle 编写软件 SDK 文档周融,2007 年 7 月(C) 2001-2007 保留所有权利。一直以来,独立软件开发商 (ISV) 开发的第三方程序集为了简化开发流程,往往会同时提供一套软件开发工具包 (SDK) 和文档库,该文档库包含它们发布的程序集的所有供开发人员使用的类型和模块,并且对如何使用它们做了详细的说明。Microsoft Developer Network ...
阅读全文
发现了一个asp.net 脚手架代码生成工具,它是一个免费的工具,自动生成asp.net mvc的CRUD页面,主要特性如下:
- Uses the LinqToSql data to generate source code.
- Ruby on Rails like CRUD pages creator with a single button click.
- Ruby on Rails like error reporting in the CRUD pages.
- Ability to create pages for selected tables.
- Create a common controller that links all the Selected table's List and Add action.
你可以在这里下载:Download
你也可以看他的视频教程:Screencast
项目网站:http://www.twinforms.com/aspmvc-home.htm
疑惑:
数据成员可以分静态变量、非静态变量两种.
静态成员:静态类中的成员加入static修饰符,即是静态成员.可以直接使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以静态成员不能访问非静态的成员..因为静态成员存在于内存,所以非静态成员可以直接访问类中静态的成员.
非成静态员:所有没有加Static的成员都是非静态成员,当类被实例化之后,可以通过实例化的类名进行访问..非静态成员的生存期决定于该类的生存期..而静态成员则不存在生存期的概念,因为静态成员始终驻留在内容中..
一个类中也可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数..
对于winApp来说,静态成员对于程序员本身省了很多事,而且因为静态成员驻留内存,在方法与方法之间传递共享数据的时候,所以静态成员成了我的首选..但是不要因为方便,大量使用,尤其是在内存紧张或者
用静态方法操作一些共享值的时候.或者要写多用户系统的时候,要慎之又慎.比如:
static int id = 0;
sql = "select * from table where id=" + id;
如果这样写的话,在单机测试的时候没有问题,但是在多人同时对数据进行测试的时候,就会有问题了.假如,A用户访问他的id是20,则id的值在内存中为20,而此时B用户访问,他的id是30,则id在内存中的值是30..A用户的id值则被更改了..如果此时你将这个方法用非静态成员来写,则不会出现这样的情况..因为非静态成员是你声明的时候,实例化的时候才会分配内存..所以A用户访问的时候,App会因为A实例化而给A用户的请求分配内存..而B用户访问的时候也一样会因为B用户的访问而分配内存..所以两个用户访问的是不同的内存块..所以不会出现数据覆盖和错乱的现象...
我想这样的情况应该能很好的说明静态变量和非静态成员的区别..
相对于webApp而言,在winApp下使用static的时候要比webApp下考虑的因素要少的多,因为webApp本来就是一个多用户的系统,所以使用static的时候更应该小心..
而我对static在webApp下的使用存在一个疑问,如果一个静态方法,例如:
static string aa(string str){
//经过一系列操作..
return str;
}
或者返回一个DataSet的静态方法
static DataSet aa(string str){
//经过一系列操作..
return DataSet;
}
这个时候,在访问量大的时候,程序出现了并发,会不会发生错乱??我以前的项目使用的公用函数类中使用了大量的静态方法,不过好在访问量不大,一直没有问题..在发这个文章之前,我查找了MSDN,CSDN,搜索了一些关于静态成员的文章,但是都没有一个明确的说明..虽然,自己在项目中也测试了这么长时间也没有问题..但是总觉得有这个可能发生..
不知道大家是否在项目中碰到类似的疑惑呢??请有过这方面经验的朋友指教..
答案:
不说是否滥用,如果你出现冲突,说明你没有理解静态成员变量和静态方法的区别,静态方法本身只是一段代码,不管怎么调用他都不会出现问题。但静态成员变量就不行了,他被所有用户共享,如果一个用户改变了他,肯定会影响到别人,这就是常说的并发冲突问题,一般来说在修改共享成员变量时要lock!
关于静态方法和实例方法的一些误区。
一、 静态方法常驻内存,实例方法不是,所以静态方法效率高但占内存。
事实上,方法都是一样的,在加载时机和占用内存上,静态方法和实例方法是一样的,在类型第一次被使用时加载。调用的速度基本上没有差别。
二、 静态方法在堆上分配内存,实例方法在堆栈上。
事实上所有的方法都不可能在堆或者堆栈上分配内存,方法作为代码是被加载到特殊的代码内存区域,这个内存区域是不可写的。
三、 实例方法需要先创建实例才可以调用,比较麻烦,静态方法不用,比较简单。
事实上如果一个方法与他所在类型的实例无关,那么它就应该是静态的,决不会有人把它写成实例方法。所以所有的实例方法都与实例有关,既然与实例有关,那么创建实例就是必然的步骤,没有麻烦简单一说。实际上上你可以把所有的实例方法都写成静态的,将实例作为参数传入即可。
有些方法看似与所在的实例无关,如IComparer.Compare方法,但实际上每一个实现这个接口的类都只会负责自己类型实例的比较,这是C#1.x规范中没有泛型所带来的历史遗留问题。
大部分静态方法是与类的实例有关的,如各种Parse方法,他做成静态的原因是他没有实例作为参数。其他的大多是出于语义或者其他目的的考虑。
一、共享文件夹
进入Vista系统,点击需要共享的文件夹,调用右键菜单,选择“共享”。进入“文件共享”对话框,添加新用户“Everyone”,
如图1。

图1
二、计算机管理设置
文件夹共享设置到此完成,不过实际工作中,XP用户依然有可能无法访问Vista共享文件夹。一般情况下,XP用户已经可以在“网络邻居”中找到安装Vista系统的电脑了,不过点击访问时,用户有可能遇到下面两种错误提示信息:
1.登录失败:禁用当前的帐户,如图4。

图4
2.登录失败:未授予用户在此计算机上的请求登录类型,图5。

图5
下面我们就针对两种错误信息,提供对应的解决方案。
系统提示:“登录失败:禁用当前的帐户”,这是因为Vista的“Guest(来宾帐户)”被禁用。这算个老问题了,就算是XP系统,要想实现局域网内其它电脑的匿名访问,你也必须开启“Guest”的权限。进入“控制面板”→“系统和维护”→“管理工具”,在“管理工具”列表中选择“计算机管理”。
进入“计算机管理”,在左侧任务列表中选择“系统工具”→“本地用户和组”→“用户”,然后我们在中间任务区中可以看到系统当前的用户帐户列表了,鼠标双击列表中的“Guest”,进入“属性”设置,如图6。

图6
在“Guest属性”对话框中,取消勾选“帐户已禁用”,点击“确定”完成,如图7。

图7
三、网络和共享中心设置
系统提示:“登录失败:未授予用户在此计算机上的请求登录类型”,这是Vista默认开启了“密码保护的共享”,这样只有具有计算机的用户帐户和密码的用户才能通过网络访问共享文件夹。而我们在实际工作中,往往希望局域网内的电脑不必键入任何密码就能访问共享文件夹,下面我们来取消该设置。
点击“开始”菜单,找到“网络”链接,鼠标右键点击,调用菜单选择“属性”,进入“网络和共享中心”。接下来我们在“共享和发现”中可以看到“密码保护的共享”状态为“启用”,如图8。

图8
下面我们要做的自然就是选择“关闭密码保护的共享”,点击“应用”按钮,系统依然会自动弹出“用户帐户控制(UAC)”对话框,确认操作后完成,如图9。

图9
至此,我们扫除了所有Vista中的文件共享障碍,局域网内其它电脑不需要输入任何帐号、密码,就能轻易访问Vista中的共享文件夹的资料了。
注:“Everyone”不必大家手工输入,可以在系统下拉列表中选择后添加。
我们还可以为“Everyone”指定“权限级别”,默认有三种权限“读者”、“参与者”、“共有者”,这三个权限的实质就是:“读取”、“更改”、“完全控制”,设置完成后,点击“共享”按钮完成,如图2。

图2
点击确认后,系统会自动弹出“用户帐户控制(UAC)”对话框,提示“Windows需要你的许可才能继续”,用户点击“继续”进入下一步。接下来,系统会自动开始文件夹共享设置,设置过程其中,有可能会出现“网络发现和文件共享”对话框,点击“是,启用所有公用网络的网络发现和文件共享”,如图3。

四、共享文件夹的高级设置
Vista中文件夹被共享后,文件夹图标会自动被添加上“两个漂亮的小人”的图标,我们取消文件夹共享的方法非常简单,依然右键选择文件夹,再次点击“共享”,然后在对话框中选择“停止共享”,如图10。

图10
点击“更改共享权限”就重新返回之前共享设置的对话框了,不过在这里我们发现Vista同XP中并不太一样。例如,我们无法为共享文件夹重新设置文件夹名称,其实在Vista中依然可以自由定制,不过是在“高级共享”属性中才能修改。
鼠标右键选择共享文件夹,在菜单中选择“属性”。进入“属性”对话框后,切换到“共享”选项卡,点击“高级共享”按钮,如图11。

图11
进入“高级共享”对话框,可以看到“共享名”设置,点击“添加”按钮,即可为文件夹增加新的“共享名”。在这里还可以设置文件夹同时共享的用户数量,默认值为“10”,你可以设置该值为所需数字,如图12。

最近公司给换了本本 acer 4710 内存加到2G 酷睿1代 2450 相当于2g 集成显卡 竟然跑上vista还可以 呵呵
不过vista也很麻烦 开始是sql2005的企业版不能安装 打了sp2也不可以 后来我就安装了客户端 然后再装了个express版 居然也可以跑了 呵呵
vs2008在vista下效果还是不错的 但是连接vss的时候就郁闷了 只能连接选择网络连接 后来百度下 发现前人已经给种好树了 呵呵
项目使用VSS2005和VS2008开发!有天早上不能访问VSS源代码管理器数据库,原以为是服务器不能访问了,检查后发现服务器访问正常,但在选择数据库的时候一直显示访问internet地址,怎么选也不起作用!最后在VS2008下找到了原因!
在VS2008的菜单“工具”——“选项”——“源代码管理器”——“插件选择”

里面的选项为Microsoft Visual SourceSafe(Interner)将其修改为Microsoft Visual SourceSafe
在打开项目显示原来的VSS代码库!这时选择别的VSS库也只能从本地或者局域网内选取