hiDotNet 博客首页 | hiDotNet 首页 | hiDotNet 论坛 | hiDotNet 知识库          

Powered By:

聚合

统计信息

  • 博客 - 14
  • 随笔 - 45
  • 文章 - 34
  • 评论 - 55565
  • Trackbacks - 24516

最近更新博客

最近更新随笔

Can you sell yourself in two minutes

Sunset

Q: Can you sell yourself in two minutes? Go for it.
    你能在两分钟內自我推荐吗?大胆试试吧!

A: With my qualifications and experience, I feel I am hardworking, responsible and diligent in any project I undertake. Your organization could benefit from my analytical and interpersonal skills.
    依我的资格和经验,我觉得我对所从事的每一个项目都很努力、负责、勤勉。我的分析能力和与人相处的技巧,对贵单位必有价值。

Q: Give me a summary of your current job description.
    对你目前的工作,能否做个概括的说明。

A: I have been working as a computer programmer for five years. To be specific, I do system analysis, trouble shooting and provide software support.
    我干了五年的电脑程序员。具体地说,我做系统分析,解决问题以及软件供应方面的支持。

Q: Why did you leave your last job?
    你为什么离职呢?

A: Well, I am hoping to get an offer of a better position. If opportunity knocks, I will take it.
    我希望能获得一份更好的工作,如果机会来临,我会抓住。

A: I feel I have reached the "glass ceiling" in my current job. I feel there is no opportunity for advancement.
    我觉得目前的工作,已经达到顶峰,即沒有升迁机会。

Q: How do you rate yourself as a professional?
    你如何评估自己是位专业人员呢?

A: With my strong academic background, I am capable and competent.
    凭借我良好的学术背景,我可以胜任自己的工作,而且我认为自己很有竞争力。

A: With my teaching experience, I am confident that I can relate to students very well.
    依我的教学经验,我相信能与学生相处的很好。

Q: What contribution did you make to your current (previous) organization?
    你对目前/从前的工作单位有何贡献?

A: I have finished three new projects, and I am sure I can apply my experience to this position.
    我已经完成三个新项目,我相信我能将我的经验用在这份工作上。

Q: What do you think you are worth to us?
    你怎么认为你对我们有价值呢?

A: I feel I can make some positive contributions to your company in the future.
    我觉得我对贵公司能做些积极性的贡献。

Q: What make you think you would be a success in this position?
    你如何知道你能胜任这份工作?

A: My graduate school training combined with my internship should qualify me for this particular job. I am sure I will be successful.
    我在研究所的训练,加上实习工作,使我适合这份工作。我相信我能成功。

Q: Are you a multi-tasked individual?Do you work well under stress or pressure?
    你是一位可以同时承担数项工作的人吗?你能承受工作上的压力吗?

A: Yes, I think so.

A: The trait is needed in my current(or previous) position and I know I can handle it well.
    这种特点就是我目前(先前)工作所需要的,我知道我能应付自如。

Q: What is your strongest trait(s)?
    你个性上最大的特点是什么?

A: Helpfulness and caring.
    乐于助人和关心他人。

A: Adaptability and sense of humor.
    适应能力和幽默感。

A: Cheerfulness and friendliness.
    乐观和友爱。

Q: How would your friends or colleagues describe you?
    你的朋友或同事怎样形容你?

A: (pause a few seconds)
    (稍等几秒钟再答,表示慎重考虑。)

    They say Mr. Chen is an honest, hardworking and responsible man who deeply cares for his family and friends.
    他们说陈先生是位诚实、工作努力,负责任的人,他对家庭和朋友都很关心。

A: They say Mr. Chen is a friendly, sensitive, caring and determined person.
    他们说陈先生是位很友好、敏感、关心他人和有决心的人。

Q: What personality traits do you admire?
    你欣赏哪种性格的人?)

A: I admire a person who is)honest, flexible and easy-going.
    诚实、不死板而且容易相处的人。

A: (I like) people who possess the "can do" spirit.
    有"实际行动"的人。

Q: What leadership qualities did you develop as an administrative personnel?
    作为行政人员,你有什么样的领导才能?

A: I feel that learning how to motivate people and to work together as a team will be the major goal of my leadership.
    我觉得学习如何把人们的积极性调动起来,以及如何配合协同的团队精神,是我行政工作的主要目标。

A: I have refined my management style by using an open-door policy.
    我以开放式的政策,改进我的行政管理方式。

Q: How do you normally handle criticism?
    你通常如何处理別人的批评?

A: Silence is golden. Just don't say anything; otherwise the situation could become worse. I do, however, accept constructive criticism.
    沉默是金。不必说什么,否则情况更糟,不过我会接受建设性的批评。

A: When we cool off, we will discuss it later.
    我会等大家冷靜下来再讨论。

Q: What do you find frustrating in a work situation?
    在工作中,什么事令你不高兴?

A: Sometimes, the narrow-minded people make me frustrated.
    胸襟狭窄的人,有时使我泄气。

A: Minds that are not receptive to new ideas.
    不能接受新思想的那些取。

Q: How do you handle your conflict with your colleagues in your work?
    你如何处理与同事在工作中的意见不和?

A: I will try to present my ideas in a more clear and civilized manner in order to get my points across.
    我要以更清楚文明的方式,提出我的看法,使对方了解我的观点。

Q: How do you handle your failure?
    你怎样对待自己的失敗?

A: None of us was born "perfect". I am sure I will be given
a second chance to correct my mistake.
    我们大家生来都不是十全十美的,我相信我有第二个机会改正我的错误。

Q: What provide you with a sense of accomplishment.
    什么会让你有成就感?

A: Doing my best job for your company.
    为贵公司竭力效劳。

A: Finishing a project to the best of my ability.
    尽我所能,完成一个项目。

Q: If you had a lot of money to donate, where would you donate it to?Why?
    假如你有很多钱可以捐赠,你会捐给什么单位?为什么?

A: I would donate it to the medical research because I want to do something to help others.
    我会捐给医药研究,因为我要为他人做点事。

A: I prefer to donate it to educational institutions.
    我乐意捐给教育机构。

Q: What is most important in your life right now?
    眼下你生活中最重要的是什么?

A: To get a job in my field is most important to me.
    对我来说,能在这个领域找到工作是最重要的。

A: To secure employment hopefully with your company.
    希望能在贵公司任职对我来说最重要。

Q: What current issues concern you the most?
    目前什么事是你最关心的?

A: The general state of our economy and the impact of China' entry to WTO on our industry.
    目前中国经济的总体情況以及中国入世对我们行业的影响。

Q: How long would you like to stay with this company?
    你会在本公司服务多久呢?

A: I will stay as long as I can continue to learn and to grow in my field.
    只要我能在我的行业力继续学习和长进,我就会留在这里。

Q: Could you project what you would like to be doing five years from now?
    你能预料五年后你会做什么吗?

A: As I have some administrative experience in my last job, I may use my organizational and planning skills in the future.
    我在上一个工作中积累了一些行政经验,我将来也许要运用我组织和计划上的经验和技巧。

A: I hope to demonstrate my ability and talents in my field adequately.
    我希望能充分展示我在这个行业的能力和智慧。

A: Perhaps, an opportunity at a management position would be exciting.
    也许有机会,我将会从事管理工作。

    (如果不愿正面回答,也可以说:)
    It would be premature for me to predict this.
    现在对此问题的预测,尚嫌过早。

    (甚至还可以打趣的说:)
    Hypothetically speaking, I might be able to do your current job as a director.
    (或 CEO 或 president)说不定,我也能做你现在主任的工作呢!

Q: What range of pay-scale are you interested in?
    你喜欢那一种薪水层次标准?

A: Money is important, but the responsibility that goes along with this job is what interests me the most.
    薪水固然重要,但这工作伴随而来的责任更吸引我。

A: (假如你有家眷,可以说:)
    To be frank and open with you, I like this job, but I have a family to support.
    坦白地说,我喜欢这份工作,不过我必须要负担我的家庭。

Other Tips  其它建议

Know something about the organization you are applying to.
了解一些你申请工作单位的情况。

Dress properly. Don't shake hand with the interviewer until he/she extends his/her hand.
穿着要得体,人家伸手时才握手。

Don't sit down until invited to do so by the interviewer.
人家未请,先別坐下。

Make eye-contact with the interviewer during the interview.
面试时,眼睛要看着对方。

Listen actively and stay calm.
注意听,保持冷静。

If invited to a meal, be especially careful about your table manners.
被邀吃饭时,要特別注意餐桌礼节。

Don't talk with your mouth full.
嘴里有食物,不可开口说话。

Don't make much noise while you eat.
吃东西不要出声音。

Don't blow your nose or use the toothpick at table.
不要拧鼻涕或用牙签剔牙。

Don't appear to be pushy or overly anxious to get a job.
不必过分表现急着要工作。

Be honest but not too modest.
要诚实,但不必太谦虚。

Don't put yourself down or cut yourself up.
不可妄自菲薄或自贬。

Try to avoid discussing politics or religion with your interviewer.
避免与面试人谈政治或宗教。

2008/7/3 11:40 作者: Databinder

URL重写

重写是截取传入 Web 请求并自动将请求重定向到其他 URL 的过程。
   比如浏览器发来请求hostname/101.aspx ,服务器自动将这个请求中定向为http://hostname/list.aspx?id=101。

url重写的优点在于:
     缩短url,隐藏实际路径提高安全性
     易于用户记忆和键入。 
     易于被搜索引擎收录

二 实现url重写的基本方法
    下载MS的URLRewriter.dll,放到你的web程序的bin下
下载地址1:http://www.rickel.cn/uploads/DevTools/MSDNURLRewriting.msi
下载地址2:download.microsoft.com/download/0/4/6/0463611e-a3f9-490d-a08c-877a83b797cf/MSDNURLRewriting.msi

下载完成后,在web.config里设置如下:


<?xml version="1.0" encoding="utf-8" ?>
<!--overred-->
<configuration>
     <configSections>
         <section name="RewriterConfig"type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter" />
     </configSections>
     <RewriterConfig>
         <Rules>
             <RewriterRule>
                 <LookFor>~/d(\d+)\.aspx</LookFor>
                 <SendTo>~/default.aspx?id=$1</SendTo>
             </RewriterRule>
         </Rules>
     </RewriterConfig>
     <system.web>
         <httpHandlers>
             <add verb="*" path="*.aspx" type="URLRewriter.RewriterFactoryHandler, URLRewriter" />
         </httpHandlers>
    </system.web>
</configuration>


其中
<section name="RewriterConfig" type="URLRewriter.Config.RewriterConfigSerializerSectionHandler, URLRewriter" />

用于指定配置节"RewriterConfig"的处理程序类的名称为”URLRewriter.Config.RewriterConfigSerializerSectionHandler”,该类存在于bin目录下的URLRewriter .dll文件中

关键的是这两句
<LookFor>~/d(\d+)\.aspx</LookFor>
<SendTo>~/default.aspx?id=$1</SendTo>

<LookFor>~/d(\d+)\.aspx</LookFor>表示,用户输入的url,d(\d+)\.aspx是 url中文件名匹配的正则表达式(此处为字母d开头,后面跟一个或多个数字,并以.aspx结尾。用户也可根据自己的需要自行设定)。
<SendTo>~/default.aspx?id=$1</SendTo>,表示当服务器接收到符合上面条件的请求后如何重写url。此处表示访问defalutl.aspx并传入参数id,其值$1将用用户请求的文件名中的第一个数字来表示。
例如用户输入 hostname/d11.aspx,服务器会把他重写为http://hostname/default.aspx?id=11。换句话说用户输入http: //hostname/d11.aspx,实际访问的是http://hostname/default.aspx?id=11。这样就起到了隐藏真实文件名,并便于用户记忆的作用。

处理回发
在重写后的url里如果产生回发,例如有一个按钮,又调用了该被重写的aspx,用户浏览器中将会显示该aspx文件实际的地址,也就是http: //hostname/default.aspx?id=11。但从用户的角度考虑,如 果单击按钮时突然看到 URL 更改会使他们感到不安。因此必须解决这个问题。
解决方法有二:
(1)自己定义一个Actionlessform类,在aspx中不再使用系统提供的form 标记

namespace ActionlessForm 
{
     public class Form : System.Web.UI.HtmlControls.HtmlForm
     {
        protected override void RenderAttributes(HtmlTextWriter writer)
         {
             writer.WriteAttribute("name", this.Name);
             base.Attributes.Remove("name");
             writer.WriteAttribute("method", this.Method);
             base.Attributes.Remove("method");
             this.Attributes.Render(writer);
             base.Attributes.Remove("action");
             if (base.ID != null)
                 writer.WriteAttribute("id", base.ClientID);
          }
     }
}

创建此类并对其进行编译之后,要在 ASP.NET Web 应用程序中使用它,应首先将其添加到 Web 应用程序的 References 文件夹中。然后,要使用它来代替 HtmlForm 类,做法是在 ASP.NET 网页的顶部添加以下内容:

<%@ Register TagPrefix="skm" Namespace="ActionlessForm" Assembly="ActionlessForm" %>
然后,将 <form runat="server">(如果有)替换为:<skm:Form id="Form1" method="post" runat="server"> 
并将右边的 </form> 标记替换为:</skm:Form>

个人并不推荐该方法
(2)第二种方法就是继承page,这样你不需要在aspx页中改任何东西。
代码:
using System;
using System.IO;
using System.Web;
using System.Web.UI;
namespace URL
{
     public class OLPage : Page
     {
         public OLPage()
         {}
         protected override void Render(HtmlTextWriter writer)
         {
             if (writer is System.Web.UI.Html32TextWriter)
             {
                 writer = new FormFixerHtml32TextWriter(writer.InnerWriter);
             }
             else
             {
                 writer = new FormFixerHtmlTextWriter(writer.InnerWriter);
             }
             base.Render(writer);
         }
     }

     internal class FormFixerHtml32TextWriter : System.Web.UI.Html32TextWriter
     {
         private string _url; // 假的URL

     internal FormFixerHtml32TextWriter(TextWriter writer):base(writer)
     {
         _url = HttpContext.Current.Request.RawUrl;
     }

     public override void WriteAttribute(string name, string value, bool encode)
     {
         if (_url != null && string.Compare(name, "action", true) == 0)
         {
             value = _url;
         }
         base.WriteAttribute(name, value, encode);

         }
     }

internal class FormFixerHtmlTextWriter : System.Web.UI.HtmlTextWriter
{
     private string _url;
     internal FormFixerHtmlTextWriter(TextWriter writer):base(writer)
     {
         _url = HttpContext.Current.Request.RawUrl;
     }
    
     public override void WriteAttribute(string name, string value, bool encode)
     {
         if (_url != null && string.Compare(name, "action", true) == 0)
         {
             value = _url;
         }
         base.WriteAttribute(name, value, encode);
     }
}

}

把这个文件编译成dll,并在你的项目中引用它。


然后把项目中的所有aspx文件对应的cs文件中的继承page类的代码改写为继承OLPage。
例如
public class WebForm1:page
改写为
public class WebForm1:URL.OLPage

这样就解决回发问题。
编译*.dll方法:/t:library name.cs

2008/5/13 15:31 作者: Databinder

常用IL指令

为了今后分析IL代码。先把一个最最常用的指的功能列出来一下:

ldstr

功能:将对字符串的对象引用推送到堆栈上,ldstr 指令推送对表示在元数据中存储特定字符串新字符串对象对象引用(O 类型)。ldstr 指令分配必需的内存量并执行将字符串从在文件中使用的形式转换为在运行时要求的字符串格式所需的任何格式转换。

搞个示例:Console.WriteLine("Hi Flashccie");

ldstr "Hi Flashccie"
call void [mscorlib]System.Console::WriteLine(string)
ret

ldc.i4 num,,,,idc.i4.0,,,,idc.i4.1................

功能:将值 num 推送到堆栈上,对于整数 -128 到 127 有特殊的简短编码(并因此更有效),对于整数 -1 到 8 尤其有特殊的简短编码。所有简短编码都将 4 字节整数推送到堆栈上。如:ldc.i4.0 ,ldc.i4.1,.....等

较长的编码用于 8 字节整数以及 4 和 8 字节浮点数,并且用于不适合短格式的 4 字节值。有三种方法可以将 8 字节整数常数推送到堆栈上

1. 使用 ldc.i8指令用于必须以超过 32 位表示的常数。

2. 使用 idc.i4 指令(后跟 conv.i8)用于需要 9 到 32 位的常数。

3. 使用短格式指令(后跟 conv.i8)用于可以 8 位或更少位表示的常数。

 

stloc index

功能:从堆栈中弹出值并将其放在局部变量 index 中。(index最大:65534,从0开始)

stloc 指令从计算堆栈中弹出位于顶部的值并将其移动到局部变量号 index 中,其中局部变量从 0 向上进行编号。值的类型必须与当前方法的本地签名所指定的局部变量的类型匹配。

在将值保存到只能容纳长度小于 4 个字节的整数值的局部变量中时,会在将该值从堆栈移动到局部变量中时将其截断。将浮点值从其本机大小(F 类型)舍入到与该参数关联的大小。

怎么理解呢?

比如你在一个方法中定义下以下几个变量:

int i;
int i0=new Int();
哪么就会生成以下IL代码:

    .locals init (
        [0] int32 num,
        [1] int32 num2)

L_0000: nop
   
//初始化i0为0
L_0001: ldc.i4.0 //将0推上栈顶
L_0002: stloc.1 //从堆栈顶部弹出一个值到索引号为1的变量中去

 

 

未完....基本的指令,最少也要求能把简单的一个程序搞完才行。不过,指令相对也不会很多。很晚了。睡去了。。

2007/11/8 1:51 作者: 轻舞flash

自己重新重写Equals

今天在项目中我自己写了个集合类,由于要存储非常多的数据,所以我想把集合类下载到用户本地,然后在本地再取对象,这样就减少了频繁读取数据库的次数,可是在用到ArrayList的contains的时候,我的对象明明在集合里存在,但是还是返回False ,后来想到ArrayList是引用类型,在每一次实例化的时候对象的内存地址都不一样,本来想遍历集合,但考虑到效率不高,在网上找到可以重写Equals方法,在C#的容器中,常用的三个容器数组,ArrayList, Hashtable..数组比较简单,实现某种单一数据的存储,但是并不能自由插入,移除和容纳不同的对象..,所以ArrayList是数组的替代品, 并且由于ArrayList可以自由的添加,删除,插入,读取,给我们提供了足够大的自由性,颇得我的青睐..不过使用中,难免有些缺点,感觉最麻烦的就是检测某对象是否在Items中..因为每一个new出来的Class在内存中的表现不相同,即便是同一个类,你new出来两个,然后再判断,也是会一样的!!所以每次使用ArrayList.Contains()检测对象的时候,难免都得不到自己想要的结果..因为每个Class都是继承自Object类..而ArrayList.Contains()的实现是IList.Contains,而此方法是调用Class中的Equals方法判断是否相等,这个时候,可以在自己的对象中覆写Object.Equals方法,以达到自己的目的..注意,如果你覆写了Equals方法,则也要覆写GetHashCode(),因为Equals是用获取Object.GetHashCode()来做判断的.看看下面的代码就明白:

 1using System;
 2
 3namespace HashCode_Test
 4{
 5/// <summary>
 6///        给你的类加入Equals,测试类
 7/// </summary>

 8public class Class2
 9{
10    int myHashCode = 0;
11    public Class2( int id )    //传递进一个int,作为GetHashCode的值
12    {
13        myHashCode = id;
14    }

15        
16    //覆写GetHashCode,关键的一步
17    public override int GetHashCode()    
18    {
19        return myHashCode;
20    }

21        
22    //这步,可有可无,主要是做测试结果用的
23    public override string ToString()    
24    {
25        return DateTime.Now.ToString();
26    }

27        
28    /// <summary>
29    ///        重载了Equals方法,这步和GetHashCode配合起来才会有效果
30    /// </summary>
31    /// <param name="o">要检测的对象</param>
32    /// <returns>返回是否相同</returns>

33    public override bool Equals( object o )    
34    {
35        return o.GetHashCode() == myHashCode;
36    }

37
38    //在这里使用运算符重载,主要是为了进一步演示Equals
39    public static bool operator ==(object c1, Class2 c2) 
40    {
41        return c1.GetHashCode().Equals( c2.GetHashCode() );
42    }

43    
44    //当你重载了==运算符后,必须要重载!=运算符
45    public static bool operator !=(object c1, Class2 c2) 
46    {
47        return c1.GetHashCode().Equals( c2.GetHashCode() );
48    }

49        
50}

51}

这里是测试代码:

 1System.Collections.ArrayList arr = new System.Collections.ArrayList();
 2
 3int i = 0;
 4for ( i = 0; i < 4 ; i ++ ) {
 5    Class2 class2 = new Class2(i);        //我们添加四个对象
 6    arr.Add( class2 );
 7}

 8
 9for ( i = 0; i < 4 ; i ++ ) 
10{
11    Class2 class2 = new Class2(i);        //重新创建四个对象,判断是否和容器中的对象相等
12    Console.WriteLine( i + ":" + arr.Contains(class2));//全部输出true
13}

14
15
16
17Class2 class2_1 = new Class2(1);    //再创建对象1,并添加到容器中,以判断是否有多个对象1存在
18arr.Add( class2_1  );                
19
20for ( i = 0;i<arr.Count;i++  ) {
21    Class2 class2_3 = new Class2(1);//这个时候我们要检测出容器中有多少个对象1
22    if ( arr[i].Equals( class2_3 ) ) {//我们用Equals来检测是否相等
23        Console.WriteLine( "我用Equals找到\t"  );
24    }

25    if ( arr[i] == class2_3  )            //我们用==来检测相等
26    {
27        Console.WriteLine( "我用==找到\t"  );
28    }

29    Console.WriteLine( arr[i].ToString() + "\t HashCode:" + arr[i] .GetHashCode());            //这里输出HashCode和ToString()查看
30    
31}

32


相 信上面的代码很容易看的懂..在我的Class2类中覆写了GetHashCode() ,ToString() ,Equals(object o),并重载了==运算符和!=运算符..将传递的id作为HashCode,然后判断当前传递的对象Object.GetHashCode是否等于当前 对象的GetHashCode..这样就解决了ArrayList.Contains不能对Class做出正确判断的问题..

另外,还有 一个容器Hashtable的使用和判断,并不能用上面的方法解决..因为Hashtable.Contains的实现方法是 IDictionary.Contains来做判断..需要实现IDictionary接口的方法才可以.因为牵涉到的内容比较多.所以不能在这里全部写 完..关于具体的方法和实现,我会找时间写出来的..

最后大家可以自己做一个没有实现Equals方法的类,再用ArrayList.Contains来做判断..可以看到结果都是flase..和上面的代码是个对比..
这个方法不仅可以用在ArrayList,而且也可以在多个地方使用,比如两个Class之间的关联?Class1和Class2是否关联??

Learn Scott:希望本文能对你有所帮助。

2007/7/3 22:14 作者: Databinder

mssql中的uniqueidentifier数据类型

最近新换了一个工作,在一个全国连锁的服装公司总部做开发,管理全国的分店进销存等的管理,以前从来没有用过uniqueidentifier这个数据类型,在分布式开发中比较常用,下面是此数据类型的相关介绍。
全局唯一标识符

尽管 IDENTITY 属性自动为表生成行号,但不同表的标识符列可以生成相同的行号。这是因为 IDENTITY 属性只须在所使用的表上保持唯一。如果应用程序需要生成在整个数据库或世界各地所有网络计算机的全部数据库中均为唯一的标识符列,请使用 ROWGUIDCOL 属性、uniqueidentifier 数据类型和 NEWID 函数。

使用 ROWGUIDCOL 属性定义全局唯一标识符列时应注意;

  • 一个表只能有一个 ROWGUIDCOL 列,且该列必须定义为 uniqueidentifier 数据类型。

  • SQL Server 不为该列自动生成值。若要插入全局唯一数值,应为列创建 DEFAULT 定义,以使用 NEWID 功能生成全局唯一数值。

  • 在设置 ROWGUIDCOL 属性后,使用 ROWGUIDCOL 关键字可在选择列表中引用该列。这与使用 IDENTITYCOL 关键字引用 IDENTITY 列相似。

  • 可使用 OBJECTPROPERTY 函数确定表是否含有 ROWGUIDCOL 列,使用 COLUMNPROPERTY 函数确定 ROWGUIDCOL 列的名称。

  • 由于 ROWGUIDCOL 属性不强制唯一性,所以应使用 UNIQUE 约束以确保插入 ROWGUIDCOL 列的值是唯一的。

 

uniqueidentifier 数据类型存储 16 字节的二进制值,该值的使用与全局唯一标识符 (GUID) 一样。GUID 是一个唯一的二进制数字;世界上的任何两台计算机都不会生成重复的 GUID 值。GUID 主要用于在拥有多个节点、多台计算机的网络中,分配必须具有唯一性的标识符。

uniqueidentifier 列的 GUID 值通常由以下方式获得:

  • 在 Transact-SQL 语句、批处理或脚本中调用 NEWID 函数。

  • 在应用程序代码中,调用返回 GUID 值的应用程序 API 函数或方法。

Transact-SQL NEWID 函数以及应用程序 API 函数和方法从它们网卡上的标识数字以及 CPU 时钟的唯一数字生成新的 uniqueidentifier 值。每个网卡都有唯一的标识号。由 NEWID 返回的 uniqueidentifier 使用服务器上的网卡生成。由应用程序 API 函数和方法返回的 uniqueidentifier 使用客户机上的网卡生成。

一般不将 uniqueidentifier 定义为常量,因为很难保证实际创建的 uniqueidentifier 具有唯一性。指定 uniqueidentifier 常量的方法有两种:

  • 字符串格式
    '6F9619FF-8B86-D011-B42D-00C04FC964FF'
    
  • 二进制格式
    0xff19966f868b11d0b42d00c04fc964ff
    

uniqueidentifier 数据类型不象IDENTITY 属性那样为新插入的行自动生成新的ID。为了得到新的 uniqueidentifier 值,表必须具有一个指定 NEWID 函数的 DEFAULT 子句,或使用 NEWID 函数的 INSERT 语句:

CREATE TABLE MyUniqueTable
   (UniqueColumn   UNIQUEIDENTIFIER      DEFAULT NEWID(),
   Characters      VARCHAR(10) )
GO
INSERT INTO MyUniqueTable(Characters) VALUES ('abc')
INSERT INTO MyUniqueTable VALUES (NEWID(), 'def')
GO

uniqueidentifier 列可以包含多次出现的 uniqueidentifier 值,除非也对此列指定了 UNIQUE 或 PRIMARY KEY 约束。当有多行引用源表中的同一主键时,引用其它表的 uniqueidentifier 主键的外键列将包含多次出现的个别 uniqueidentifier 值。

一个表可以有多个 uniqueidentifier 列。每个表中可以指定一个具有 ROWGUIDCOL 属性的 uniqueidentifier 列。ROWGUIDCOL 属性表明此列的 uniqueidentifier 值唯一地标识表中的行。但是,该属性并没有执行该唯一性。唯一性必须通过其它机制来执行,比如为列指定 PRIMARY KEY 约束。ROWGUIDCOL 属性主要用于 SQL Server 复制。

uniqueidentifier 数据类型的主要优点是保证由 Transact-SQL NEWID 函数或应用程序 GUID 函数生成的值在全球是唯一的。

 uniqueidentifier 数据类型的具有几个缺点:

  • 值长且难懂。这使用户难以正确键入它们,并且更难记住。

  • 这些值是随机的,而且它们不能接受任何使它们对用户变得更有意义的模式。

  • 没有任何方式可以决定生成 uniqueidentifier 值的顺序。它们不适用于那些依赖递增的键值的现有应用程序。

  • uniqueidentifier 数据类型具有 16 个字节,与其它那些诸如 4 字节的整数相比要相对大一些。这意味着使用 uniqueidentifier 键建立的索引可能会比使用 int 键实现的索引相对慢一些。

 

在设计分布式数据库时非常有用。

2007/6/22 10:55 作者: Databinder

SQL引发的血案

先看如下2中SQL写法:
(1)
declare @monthstart datetime
declare @monthend datetime
declare @minID int
declare @maxID int

set @monthstart= ‘2006-06-20 17:02:00’
set @monthend= ‘2006-07-20 17:02:00’

select @minID = min(postid),@maxID = max(postId) from table_posts where postdate between @monthstart and @monthend
 select @minID,@maxId

(2)
declare @minID int
declare @maxID int
select @minID = min(postid),@maxID = max(postId) from table_posts where postdate between '2006-06-20 17:02:00' and '2006-07-20 17:02:00'
select @minID,@maxID

这2条语句执行结果会有区别么?
有?回复告诉俺啥区别被。
没有。俺也这么想滴。

再描述一下俺查询滴数据量。俺查询滴那个表的数据量是近200万,不算多。

好啦,现在答案揭晓:第一条执行速度N慢,相对于第二条来说,多浪费20多秒的时间。
你别问俺为啥,俺也郁闷,至今未找到根子。不过在轻舞flash老哥的帮助下,还是找到了两者差距的所在。第一条逻辑读9万多,比第二条多9万多。汗一个。。。。
不是啥子数据库服务器的缘故,就算是俺也不知道,因为服务器不是俺设置的。

但你非得在查询条件中使用变量怎么办?牛人自有牛人的办法。还是flash老哥给的方法,贴出来共享。不过上面的问题谁碰到过可要联系俺啊。

另类解决方案闪亮登场:
declare @monthstart datetime
declare @monthend datetime
declare @minD int
declare @maxID int
declare @sqlcom varchar(8000)
set @monthstart='2006-06-20 17:02:00'
set @monthend='2006-07-20 17:02:00'

set @sqlcom='select min(postid) as minId, max(postId) as maxId from forums_posts where postdate between '''+Convert(varchar(16),@monthstart,121) +''' and '''+ Convert(varchar(16),@monthend ,121)+''''
print @sqlcom

exec(@sqlcom)

走过,路过,要记得留过。。。
鄙视看帖不回的,俺多辛苦的文章啊!

PS:
可能是表的问题,因为我在另一个表执行类似第一条那样的语句,速度很快。另一个表的字段同样有索引。
PS:
以上2种不同的语句,如果不带Min、Max函数,则他们时间上相差无几。而且读盘一样。难道是Min、Max函数搞怪?

2007/6/20 18:34 作者: wangzhe

Google 博客搜索 Ping 服务应用

Google Ping 介绍

通 过 Google“博客搜索”Ping API, 用户可以程序化的方式将博客内容的更新通知给 Google“博客搜索”引擎。这对于经常更新博客内容的用户尤其有用。博客服务提供商的管理人员也可以利用此API将其平台上的博客内容变化向 Google 通告,以便 Google“博客搜索”及时抓取来自这一服务提供商的最新内容。为设置对 Google“博客搜索”的自动 Ping 机制,请按照如下所述设置XML-RPC客户端或REST客户端以发送请求。您可以任选一种方法进行通知;两者都将按照相同的方式进行处理。


 设置XML-RPC客户

XML-RPC客户的请求应包含如下元素:

RPC端点: http://blogsearch.google.com/ping/RPC2
调用方法名: weblogUpdates.extendedPing
参数: (应按照如下所列的相同顺序传送)

  • 站点名
  • 站点URL
  • 需要检查更新的页面URL
  • 相应的RSS、RDF或Atom种子的URL
  • 可选 页面内容的分类名称(或标签)。您可以指定多个值,之间用'|'字符进行分隔。

XML-RPC响应中将返回含有两个元素的<struct> :

  • flerror (Boolean):当有错误发生时设为true/1
  • message (string) :"Thanks for the ping." (如果成功) 或者一个错误信息(如果不成功)。

XML-RPC请求的例子


POST /RPC2 HTTP/1.0
User-Agent: request
Host: blogsearch.google.com
Content-Type: text/xml
Content-length: 447

<?xml version="1.0"?>
<methodCall>
<methodName>weblogUpdates.extendedPing</methodName>
<params>
<param>
<value>Official Google Blog</value>
</param>
<param>
<value>http://googleblog.blogspot.com/</value>
</param>
<param>
<value>http://googleblog.blogspot.com/</value>
</param>
<param>
<value>http://googleblog.blogspot.com/atom.xml</value>
</param>
</params>
</methodCall>

XML-RPC响应的例子


HTTP/1.1 200 OK
Connection: close
Content-Length: 451
Content-Type: text/xml
Date: Sun, 30 Sep 2001 20:02:30 GMT
Server: Apache

<?xml version="1.0"?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>flerror</name>
<value>
<boolean>0</boolean>
</value>
</member>
<member>
<name>message</name>
<value>Thanks for the ping.</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>

  设置REST客户

REST客户的请求中包含如下元素:

URL: http://blogsearch.google.com/ping

参数:

  • name = 博客的名字
  • url = 博客的URL
  • changesURL = RSS、RDF或Atom种子的URL (可选)
响应中将返回文本内容,在成功的时候是"Thanks for the ping.",在失败时是一条错误消息。

例子:



  changes.xml的格式

Google 将所接受的“博客搜索” Ping 记录以XML格式发布到http://blogsearch.google.com/changes.xml。changes.xml文件格式包含一个根元素<weblogUpdates>和一个或多个的<weblog>元素。

<weblogUpdates version="2" updated="Wed, 30 May 2006 14:10:00 GMT" count="1384779">
<weblog name="Some Blog"
url="http://googleblog.blogspot.com"
rssUrl="http://googleblog.blogspot.com/atom.xml"
when="1"/>
...
</weblogUpdates>

<weblogUpdates>元素

  • version:用来指示一个主要的格式变化,目前的版本是2。
  • updated:以 HTTP 1.0格式表示的日期时间。它指示了该文件上一次更新的时间。
  • count:一个递增的数字,表示了changes.xml文件的版本。新版本changes.xml文件通常具有更大的count值。

<weblog>元素

  • name:Blog的名称。
  • url: Blog的url。
  • rssUrl: 相应的RSS、Atom或其它种子的URL。
  • when: <weblogUpdates>元素的updated属性对应的时间减去相应的 Ping 发生的时间的差值,单位为秒。
====================================================================

下面实现如何使用XML RPC编程实现Google Ping服务.

首先,下载CookComputing.XmlRpc

我使用的是2.0版本.最新版为2.1.0

1.建立xml rpc客户端

 public class GoogleXmlRpc
    {
        /// <summary>
        /// 返回值,用于处理Google Ping返回值的结构
        /// </summary>
        public struct ReturnValue
        {
            public bool flerror;
            public string message;
        }

        [XmlRpcUrl("http://blogsearch.google.com/ping/RPC2")]
        public interface IGooglePing : IXmlRpcProxy
        {
            [XmlRpcMethod("weblogUpdates.extendedPing")]
            ReturnValue Ping(string websiteName, string websiteUrl, string changedUrl, string feedUrl);
        }
       
    }


2.向Google发出一个ping通告

在你的程序添加文章或更新文章时,发出ping通告.

        string websiteName="venjiang 的博客";                                                 // 博客名称
        string websiteUrl="http://blog.hidotnet.com/venjiang/";      // 博客网站地址
        string changeUrl = "http://blog.hidotnet.com/venjiang/";                      // 要更新的地址
        string feedUrl = "http://blog.hidotnet.com/venjiang/Rss.aspx";          // 聚合地址rss或atom

        GoogleXmlRpc.IGooglePing proxy = (GoogleXmlRpc.IGooglePing)XmlRpcProxyGen.Create(typeof(GoogleXmlRpc.IGooglePing));   // 创建代理类

       // 最新版本,支持泛型,可以直接使用:

       // GoogleXmlRpc.IGooglePing proxy =XmlRpcProxyGen.Create<GoogleXmlRpc.IGooglePing>();

        GoogleXmlRpc.ReturnValue returnValue = proxy.Ping(websiteName, websiteUrl, changeUrl, feedUrl);   // ping

        if (returnValue.flerror)
            Response.Write( "Google Ping 出错!");
        else
            Response.Write "Google Ping 成功!";


3.查看google 更新列表

下载:http://blogsearch.google.com/changes.xml 你可以看到你的博客相关信息已加入更新列表,目前google更新列表,有一定延迟.

2007/6/14 17:02 作者: venjiang

关于The project file '' has been renamed or is no longer in the solution.的错误

有一个solution,里面有5个project,其中有一个project我删掉了,打开solution的时候提示无法加载,我就把这个project给Remove掉了,结果发现无法编译,提示如下:

The project file '' has been renamed or is no longer in the solution.

仔细想了一下,IDE无法编译,肯定是别的项目有引用这个project的DLL,于是我把别的project所有引用在bin文件夹中的的全部删掉,还是发现无法编译。郁闷。到google上查了一下,只找到一个方法说是重新建立这个project,我晕。

难道要我重新返工到移除项目以前(移除项目前是可以编译的,虽然项目加载不到)?

不死心,在应用这个项目的DLL的项目的References中,我找到了这个引用,显示的是引用项目,把这个DLL的引用移除掉,OK,可以编译了,看来以后引用项目的时候,在bin文件删除的仅仅是物理的copy到本地的dll文件,而要删除引用,还是要在References中把这个引用彻底移除掉。

2007/6/12 9:00 作者: Databinder

今天是2007年6月6日,开博纪念

现在是2007年6月6日9点15分,以后就在博客苑落户了,以前从来没有系统的写过什么东西,要好好锻炼一下自己的文笔了。

文章浅薄,各位前辈见笑了。

//多好的日子啊,66大顺。

2007/6/6 9:16 作者: Blog Author

程序错误:将截断字符串或二进制数据。

今日同事说论坛后台编辑不了,我跟踪一下,发现程序并无异常报告。分析后认为是数据库错误,于是执行SQL语句排错。经测试,发现修改字段时,使用较长的字符串时报如下错误:

将截断字符串或二进制数据。
语句已终止。

记得以前也碰到过这样的错误,确实是数据库错误。从错误信息提示分析,容易让人以为是非法字符引起的,我初步也这么认为(呵呵,以前碰到这个错误的原因不记得了!),于是排除几个认为非法的字符(还好仅仅是几个字符,不然我也不会找到真正的原因了。),F5,错误信息依旧,于是看某个字段的长度,将测试字符串缩短后F5,执行成功!看来报这个错是输入的数据超过字段长度的缘故了。从错误提示信息分析,根据“截断”2字就容易让我以为是输入了非法字符,但经过这次测试,我觉得“截断”应该是某个东西过长,过大,而被截断一部分的意思,而不是我们理解的“过滤掉”这个意思。

我根据自己想法进行了几个测试。首先在输入数据末尾使用空格,以此是输入数据超过字段长度,F5,以为会报错,显示执行成功!换一种方式,将空格放输入数据中间,报错!难道SQl中有Trim?呵呵,哪位高人指点一二?

2007/6/1 18:27 作者: wangzhe

利用userData实现客户端保存表单数据[转的]

对于多数网页制作的朋友,实现在客户端保存在网页表单上的信息,比较多的是采用Cookie技术来实现,这些功能例如:下拉列表框选择的选项,文本框输入的数据等。事实上,我们可以利用微软DHTML默认行为中的userData行为来实现这个功能。 


因为很多网友问到这样的问题,整理了一下,并提供了三个示例。下面将就该行为的使用做一个介绍: 


UserData 行为(userData Behavior): 


1、说明: 

userData行为通过将数据写入一个UserData存储区(UserData store)来保存数据,userData可以将数据以XML格式保存在客户端计算机上,如果你用的是 Windows 2000 或者 Windows XP,是保存在C:\Documents and Settings\Liming\UserData\文件夹下(如果操作系统不是安装在C盘,那么C就应该是操作系统所在的分区)。 


该数据将一直存在,除非你人为删除或者用脚本设置了该数据的失效期。 


userData行为提供了一个比Cookie更具有动态性和更大容量的数据结构。每页的UserData存储区数据大小可以达到64 Kb,每个域名可以达到640 Kb。 

userData行为通过sessions为每个对象分配UserData存储区。使用save和load方法将UserData存储区数据保存在缓存(cache)中。一旦UserData存储区保存以后,即使IE浏览器关闭或者刷新了,下一次进入该页面,数据也能够重新载入而不会丢失。 

出于安全的考虑,相同协议使用同一个文件夹保存UserData存储区数据。 

For security reasons, a UserData store is available only in the same directory and with the same protocol used to persist the store. 


在HTML、HEAD、TITLE和STYLE标记上应用了userData行为后使用save和load方法将会出错。 
Setting the userData behavior (proposed) class on the HTML, HEAD, TITLE, or STYLE object causes an error when the save or load method is called. 


必须在行内或者文档的HEAD部分宣告如下样式: 


   <STYLE> 
      .userData {behavior:url(#default#userdata);} 
   </STYLE> 


userData行为可用于Microsoft? Win32?和Unix平台上的IE 5.0以上版本,不支持Netscape。 


2、语法: 

HTML     <ELEMENT STYLE="behavior:url('#default#userData')" ID=sID> 

Script     object.style.behavior = "url('#default#userData')" 

             object.addBehavior ("#default#userData") 

注:sID参数是一个可以描述该标记的唯一id。ID是可选的,但如果有,可以在脚本中方便地对该标记加以控制。 


3、成员: 


expires 

  设置或取得使用userData行为保存数据的失效日期。 

    脚本语法:对象ID.expires = 参数 

    参数是一个使用UTC(Universal Time Coordinate,世界调整时间)格式表示失效日期的字符串。该属性可以读写,没有默认值。浏览器会对比这个日期和当前日期,如果到期,该数据就自动失效。 


getAttribute() 
  取得指定的属性值。 


load(存储区名) 
  从UserData存储区载入存储的对象数据。 


removeAttribute() 
  从对象中删除指定的属性值。 


save(存储区名) 
  将对象数据存入一个UserData存储区。 


setAttribute() 
  设置指定的属性值。 


XMLDocument 
  取得存储该对象数据的XML DOM引用。 


具体用法可以查看MSDN(http://msdn.microsoft.com) 4、示例

示例一:文本框标记的应用(Microsoft)
<HTML>
            <HEAD>
            <STYLE>
            .userData {behavior:url(#default#userdata);}
            </STYLE>
            <SCRIPT>
            function fnSaveInput(){
            var oPersist=oPersistForm.oPersistInput;
            oPersist.setAttribute("sPersist",oPersist.value); //将oPersist.value存储为sPersist属性
            oPersist.save("oXMLBranch");  //存储在名为oXMLBranch的UserData存储区
            }
            function fnLoadInput(){
            var oPersist=oPersistForm.oPersistInput;
            oPersist.load("oXMLBranch");  //载入在名为oXMLBranch的UserData存储区
            oPersist.value=oPersist.getAttribute("sPersist"); //将sPersist属性赋值给oPersist.value
            }
            </SCRIPT>
            </HEAD>
            <BODY>
            <FORM ID="oPersistForm">
            <INPUT CLASS="userData" TYPE="text" ID="oPersistInput">
            <INPUT TYPE="button" VALUE="Load" onclick="fnLoadInput()">
            <INPUT TYPE="button" VALUE="Save" onclick="fnSaveInput()">
            </FORM>
            </BODY>
            </HTML>
 [Ctrl+A 全选,提示:你可修改代码后运行] 
 
 
示例二:Checkbox标记的应用
<style>
            .userData {behavior:url(#default#userdata);}
            </style>
            <input type=checkbox id=chkbox1 class=userData>
            <script>
            var obj=document.all.chkbox1;
            obj.attachEvent('onclick',saveChecked)
            function saveChecked(){
            obj.setAttribute("bCheckedValue",obj.checked);
            obj.save("oChkValue");
            }
            window.attachEvent('onload',loadChecked)
            function loadChecked(){
            obj.load("oChkValue");
            var chk=(obj.getAttribute("bCheckedValue")=="true")?true:false;
            obj.checked=chk;
            }
            </script>
 [Ctrl+A 全选,提示:你可修改代码后运行] 
 
 
示例三:Select标记的应用 <style>
            .userData {behavior:url(#default#userdata);}
            </style>
            <select id="select1"  class="userData">
            <option>option1</option>
            <option>option2</option>
            <option>option3</option>
            <option>option4</option>
            </select>
            <script>
            var obj=document.all.select1;
            obj.attachEvent('onchange',saveSelectedIndex)
            function saveSelectedIndex(){
            obj.setAttribute("sSelectValue",obj.selectedIndex);
            obj.save("oSltIndex");
            }
            window.attachEvent('onload',loadSelectedIndex)
            function loadSelectedIndex(){
            obj.load("oSltIndex");
            obj.selectedIndex=obj.getAttribute("sSelectValue");
            }
            </script>
 [Ctrl+A 全选,提示:你可修改代码后运行]  

2007/3/15 16:50 作者: wangzhe

初识Web Garden与Web Farms

        今天跟老板讨论工作的时候,俺问老板是不是可以使用Cache来暂时保存数据,然后再一次性插入数据库中,以避免频繁操作数据库导致的性能问题。老板否定了俺的说法。老板说Cache不靠谱,容易丢失,并且网站配置使用了Web Garden,而且还是多服务器,Cache不能共享,俺一下就蔫巴了,还真是个问题。。。。

不过俺没搞懂老板说的Web Garden是虾米咚咚,于是Google一把,终于明白了,原来Web GardenIIS6的一个功能。

 

Google一把,搜到MSDN的关于Web Garden的英文文档(http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/659f2e2c-a58b-4770-833b-df96cabe569e.mspx?mfr=true),大概浏览了一下,加上老板所说,对Web Garden有了初步的了解。同时也获得了另一个名词:Web Farms

Web GardenIIS6 Web Garden 指的是一个应用程序可以成多个进程(w3wp.exe)来执行,一次请求使用其中的一个。用这个的主要目的是提高程序的可用性。当其中一个进程发生错误,那么也不会影响其他进程。发生错误的进程可以根据规则关闭,而其他的进程则可以继续工作。(引用别人滴,俺自己还没理顺怎么解释它。)

Web Farms:这个嘛,没找到资料,但大部分程序都是用这个方式的。

 

写的仓促,看过的人若不知所云,当俺是火星人好了。

2007/3/15 13:12 作者: wangzhe

Lucene的学习 ---转

这几天在学习Lucene,先转贴子看看。用来记录一下

转自:http://www.360doc.com/showWeb/0/0/208704.aspxssswwww2221htttp:://

Lucene的学习

       通过这几天的看书和学习,对 Lucene 有了更进一步的认识,所以总结一下这些天的学习成果把 Lucene 的学习心得也学出来。

1          Lucene 的认识

提到 Lucene 很多人都知道这个开源的搜索工具,其魅力也是很大的。它让我们对搜索引擎的认识不在那么神秘,也不会在觉得百度和 google 的技术多么的高深没测,其实其原理都是一样的,只是他们要做的更好,走的更远罢了。

Lucene 可以对任何的数据做索引和搜索,说这样的话其实不过分,真的就是这样,只要你能处理好这些数据,交给 Lucene 去建立索引它都可以帮你把这些数据给检索出来,是不是很好玩了。真正好玩的地方还在后面呢。

2          Lucene 的学习

前面已经对 Lucene 有了一些了解,现在我们想象它怎么去搜索这些数据呢,如果知道倒排索引,你就知道了,其实 lucene 检索的是它自己建立的索引,从索引中的到数据的指针,从而得到数据。其实就这么简单。

提到索引,现在的索引技术中有:倒排索引、后缀数组和签名文件这三种,其中后缀数组这种技术虽然检索速度也很快,但是它的数据结构构造和维护都是相当麻烦的所以不可取了。我也懒得去看了。至于签名文件嘛,那是 80 年代的玩意了,现在已经过时了。现在可是倒排索引的天下啊!相信百度和 google 都是这种技术。

3          索引的建立

 

我们从索引的建立入手:

我们建立一个 lucene 的索引时必须先建立该索引文件存放的位置,看一下代码:

IndexWriter writer = null;

writer = new IndexWriter("c:\\index", new CJKAnalyzer(), true);

这段代码就时建立一个索引前所必须的操作,先声明这个 IndexWriter ,实例化它你必须传入三个参数。他们分别代表:你要建立索引文件的存放位置、你要使用索引建立的分词方法、是否重新建立索引。这样你就告诉 lucene 我要在 c 盘的 index 目录下建立索引文件,我要使用车东老师的二分词算法做分析器、我要在这个目录下删除以前的索引或任何文件创立我的索引文件。

索引的建立有三种方式,让我一一道来:

1 new IndexWriter(new RAMDirectory(), new StandardAnalyzer(), true);

在内存中建立索引,速度最快但是耗资源,而且重启就没了。

2 new IndexWriter(FSDirectory.getDirectory(path, true), new StandardAnalyzer(), true);

在文件系统中建立索引,这里有两个参数,分别是:建立索引的路径、是否要删除当前目录下的文件重新建立索引。

3 new IndexWriter("c:\\index", new CJKAnalyzer(), true);

最常见的一种,在制定目录下建立索引,看了源码你就知道这种方法也是用的第二种方式。 Lucene 的源码:

public IndexWriter(String path, Analyzer a, boolean create)

       throws IOException {

 this(FSDirectory.getDirectory(path, create), a, create, true);

  }

我想的没错。

Indexwriter 性能调整参数:

第一个优化的参数: mergeFactor 这个参数用于控制 lucene 在把索引从内存写入到磁盘上的文件系统时内存最大的 Document 对象的数量。这个数要根据你的计算机设置,默认情况下是 10

    第二个优化的参数 maxMergeFactor 这个参数用来设置当有多少个 Segment 时进行合并操作。当然我们知道当索引文件太多的话其检索的速度就会很慢,所以我们要当文件数量一定时让它进行索引的合并。这样就可以加快索引速度,但是这个值要根据你的情况而定。当文档数量较多时我们将值设大些,当文档数量较少时我们将值设小些。

第三个优化的参数: minMergeDocs 这个参数用于控制内存中文档的数量。

 

这样我们建立索引已经完成,接下来我们要建立 Document 对象,因为你必须告诉我要搜索什么吧!好了,看看源码:

File file = new File("1.txt");

Document doc = new Document();

doc.add(Field.UnIndexed("filename", file.getName()));

FileInputStream fis = new FileInputStream(file);

byte[] b = new byte[fis.available()];

fis.read(b);

String content = new String(b);

doc.add(Field.Text("content", content));

fis.close();

以上我们就完成了将 1.txt 文件放到我们的 Document 对象了。这里我们用了 Field.Text(); 这样的操作和 doc.add(); 这样的方法建立的。这也是建立索引的必须。

稍微介绍一下 Field ,它就是你要建立索引的字段。它分别有

 

类型/方法

是否分词

是否索引

是否存储

常用实例

Keyword(String,String)

Keyword(String,Date)

电话号码,身份证,人名,地名,日期

Unindexed(String,String)

文档类型,文档名称

UnStored(String,String)

文档的标题和内容

Text(String,String)

文档的标题和内容

Text(String,Reader)

文档的标题和内容

    这样我们要建什么样的索引就对号入座吧,只要最后我们使用 doc.add(Field.Text("content", content)); 把它添加到 Document 中就可以了。

    这时我们的文档已经建立好了,现在就开始向索引中添加文档吧!这里我们使用

writer.addDocument(doc); 来向 Indexwriter 索引中添加构造好的文档。

这样我们是不是就可以说我们已经建立完了索引呢,其实不然,我们还要优化优化,这样才快嘛!对不对?

    writer.optimize(); 这样一句话就可以实现索引优化了,具体的优化过程我就不说了,是不是很简单。但是一定不要忘了哦。调用这个方法时最好建立一个合适的周期。定期进行优化。

    好了,这样我们就完成了索引的建立了。

    下面我们看看缩影的合并吧!

当我们在很多地方建立了很多的索引后,想要合并这些索引我们怎么办呢?

    使用 IndexWriter.assIndexs(New Directory[]{path});

就可以对 path 路径下的索引合并到当前的索引中了。

    下面再看看索引的删除吧!

    有一些过时的索引我们需要删除,怎么办呢?

IndexReader reader = IndexReader.open("c:\\index");

    reader.delete(0);

这样我们就可以按照文档的顺序删除对应的文档了,但是这样不太现实,不对吗?我们怎么会知道文档的顺序呢?

下面我们看看第二中方法:

IndexReader reader = IndexReader.open("c:\\index");

reader.delete(new Term("name","word1"));

reader.close();

按照字段来删除对应的文档,这样合理多了。以后要删除时就按照词条的方式去删除吧 !

索引锁: write.lock , commit.lock.

write.lock 是为了避免几个线程同时修改一个索引文档而设置。当实例一个 indexwrite 时建立和使用 indexReader 删除文档时建立。

Commit.lock 该锁主要在 segment 在建立,合并或读取时生成。

4          Lucene 的搜索

 

以上完成了索引的建立和一些关于索引的知识,但是光有索引是不行的,我们真正要做的检索,这才是我们的关键。现在我们看看 lucene 的检索吧。

认识检索从检索的工具开始吧! IndexSearcher 类是 lucene 用于检索的工具类,我们在检索之前要得到这个类的实例。

第一步我们看以下代码:

IndexSearcher searcher = new IndexSearcher("c:\\index");

创建 IndexSearcher 实例需要告诉 lucene 索引的位置,就是你 IndexWrite 的文件路径。

Query query = null;

Hits hits = null;

query = QueryParser.parse(key1, "name", new StandardAnalyzer());

hits = searcher.search(query);

if (hits != null) {

           if (hits.length() == 0) {

              System.out.println(" 没有找到任何结果 ");

           } else {

              System.out.print(" 找到 ");

              for (int i = 0; i < hits.length(); i++) {

                  Document d = hits.doc(i);

                  String dname = d.get("title");

                  System.out.print(dname + "   " );

              }

           }

       }

}

以上就是一个完整的检索过程,这里我们看见了个 Query Hits ,这两个类就是比较关键的了,我们先从检索结果的 Hits 类说起。

我们使用 Hits 经常使用的几个方法有:

length() :  返回搜索结果的总数量。

Doc(int n) : 放回第 n 个文档。

Id(int n) : 返回第 n 个文档的内部编号。

Sorce(int n) : 返回第 n 个文档的得分。

看见这个 Sorce(int n) 这个方法,是不是就可以联想到搜索引擎的排序问题呢,像百度的推广是怎么做出来的呢 , 可想而知吧,那就说明必定存在一中方法可以动态的改变某片文档的得分。对了, lucene 中可以使用 Document setBoost 方法可以改变当前文档的 boost 因子。

下面我们看看:

Document doc1 = new Document();

doc1.add(Field.Text("contents", "word1 word"));

doc1.add(Field.Keyword("path", "path\\document1.txt"));

 doc1.setBoost(1.0f);

 

  这样我们就在改变了篇文档的评分了,当 boost 的值越大它的分值就越高,其出现的位置就越靠前。

让我们再来看看 lucene 为我们提供的各种 Query 吧。

第一、    按词条搜索 - TermQuery
query = new TermQuery(new Term("name","word1"));

hits = searcher.search(query);

这样就可以把 field name 的所有包含 word1 的文档检索出来了。

第二、   “与或”搜索 - BooleanQuery

它实际是一个组合 query 看看下面的代码:

query1 = new TermQuery(new Term("name","word1"));

query2 = new TermQuery(new Term("name","word2"));

query = new BooleanQuery();

query.add(query1, false, false);

query.add(query2, false, false);

hits = searcher.search(query);

看看 booleanQuery 的用法吧:

true & true : 表明当前加入的字句是必须要满足的。相当于逻辑与。

false & true : 表明当前加入的字句是不可一被满足的, 相当于逻辑非。

false & false : 表明当前加入的字句是可选的,相当于逻辑或。

true & true : 错误的情况。

Lucene 可以最多支持连续 1024 query 的组合。

第三、   在某一范围内搜索 - RangeQuery

IndexSearcher searcher = new IndexSearcher("c:\\index");

     Term beginTime = new Term("time","200001");

     Term endTime = new Term("time","200005");

     Hits hits = null;

     RangeQuery query = null;

     query = new RangeQuery(beginTime, endTime, false);

     hits = searcher.search(query);

RangeQuery 的构造函数的参数分别代表起始、结束、是否包括边界。这样我们就可以按照要求检索了。

第四、   使用前缀检索 - PrefixQuery

这个检索的机制有点类似于 indexOf() 从前缀查找。这个常在英文中使用,中文中就很少使用了。代码如下:

IndexSearcher searcher = new IndexSearcher("c:\\index");

       Term pre1 = new Term("name", "Da");

       query = new PrefixQuery(pre1);

       hits = searcher.search(query);

第五、   多关键字的搜索 - PhraseQuery

可以多个关键字同时查询。使用如下:

query = new PhraseQuery();

       query.add(word1);

       query.add(word2);

       query.setSlop(0);

       hits = searcher.search(query);

       printResult(hits, "'david' 'mary' 紧紧相隔的 Document");

       query.setSlop(2);

       hits = searcher.search(query);

       printResult(hits, "'david' 'mary' 中相隔两个词的短语 ");

    这里我们要注意 query.setSlop(); 这个方法的含义。

query.setSlop(0);  紧紧相连 (这个的条件比较苛刻)

query.setSlop(2);  相隔

第六、   使用短语缀搜索 - PharsePrefixQuery

使用 PharsePrefixQuery 可以很容易的实现相关短语的检索功能。

实例:

query = new PhrasePrefixQuery();

       // 加入可能的所有不确定的词

Term word1 = new Term("content", "david");

       Term word2 = new Term("content", "mary");

       Term word3 = new Term("content", "smith");

       Term word4 = new Term("content", "robert");

       query.add(new Term[]{word1, word2});

       // 加入确定的词

       query.add(word4);

       query.setSlop(2);

       hits = searcher.search(query);

       printResult(hits, " 存在短语 'david robert' 'mary robert' 的文档 ");

第七、   相近词语的搜索 - fuzzyQuery

可以通俗的说它是一种模糊查询。

 

 

实例:

Term word1 = new Term("content", "david");

       Hits hits = null;

       FuzzyQuery query = null;

       query = new FuzzyQuery(word1);

       hits = searcher.search(query);

       printResult(hits," 'david' 相似的词 ");

第八、   使用通配符搜索 - WildcardQuery

实例:

IndexSearcher searcher = new IndexSearcher("c:\\index");

       Term word1 = new Term("content", "*ever");

       Term word2 = new Term("content", "wh?ever");

       Term word3 = new Term("content", "h??ever");

       Term word4 = new Term("content", "ever*");

       WildcardQuery query = null;

       Hits hits = null;

       query = new WildcardQuery(word1);

       hits = searcher.search(query);

       printResult(hits, "*ever");

       query = new WildcardQuery(word2);

       hits = searcher.search(query);

       printResult(hits, "wh?ever");     

       query = new WildcardQuery(word3);

       hits = searcher.search(query);

       printResult(hits, "h??ever");     

       query = new WildcardQuery(word4);

       hits = searcher.search(query);

       printResult(hits, "ever*");

    由上可以看出通配符?代便 1 个字符, * 代表 0 到多个字符。

Lucene 现在支持以上八中的搜索方式,我们可以根据需要选择适合自己的搜索方式。当然上面提供的一些可能对英文还是比较有效,中文就不可取了,所以我们开始想想百度,我们只在一个输入框中搜索结果。有了这个疑问我们揭开下一章的讨论吧!

查询字符串的解析:这个就是我们经常在一个输入框中输入我们要检索的文字,交给搜索引擎去帮我们分词。

QueryParser 类就是对查询字符串的解析类。

看看它的用法:

 

query = QueryParser.parse(key1, "name", new StandardAnalyzer());

hits = searcher.search(query);

它直接返回一个 Query 对象。需要传入的参数分别是:

用户需要查询的字符串、需要检索的对应字段名称、采用的分词类。

Analyzer analyzer = new CJKAnalyzer();

String[] fields = {"filename", "content"};

Query query = MultiFieldQueryParser.parse(searchword, fields, analyzer);

Hits hits = searcher.search(query);

QueryParser 的“与” “或”:

QueryParser 之间默认是或,我们想改变为与的话加入以下代码:

QueryParser.setOperator(QueryParser.DEFAULT_OPERATOR_AND);

就可以了。

5          高级搜索技巧

前面我们已经介绍了一般情况下 lucene 的使用技巧,现在我们探讨一下高级搜索的技巧吧!

1、 对搜索结果进行排序:

1) 使用 sort 类排序:

    Sort sort = new Sort();

        hits = searcher.search(query,sort);

这种方式是使用默认的 sort 排序方式进行排序。默认的 sort 排序是按照相关度进行排序。即通过 luence 的评分机制进行排序。

2) 对某一字段进行排序

       Sort sort = new Sort( content );

      hits = searcher.search(query,sort);

3) 对多个字段进行排序

Sort sort = new Sort(new SortField[]{new SortField("title"),new SortField("contents")});

hits = searcher.search(query,sort);

2、 多域搜索和多索引搜索:

在使用 luecene 时,如果查询的只是某些 terms ,而不关心这些词条到时来自那个字段中时。这时可以使用 MultiFieldQueryParser 类。这个用于用户搜索含有某个关键字是否存在在字段中,他们之间的关系使用 OR 连接。即不管存在在哪一个字段都会显示显示出来。

使用 MultiSearcher 可以满足同时多索引的搜索需求。

Searcher[] searchers = new Searcher[2];

searchers[0] = new IndexSearcher(indexStoreB);

searchers[1] = new IndexSearcher(indexStoreA);

        // 创建一个多索引检索器

Searcher mSearcher = new MultiSearcher(searchers);

3、     对搜索结果进行过滤:

1)     对时间进行过滤

         通常情况下我们对搜索结果要进行过滤显示,即只显示过滤后的结果。

doc.add(Field.Keyword("datefield", DateField.timeToString(now - 1000)));

DateFilter df1 = DateFilter.Before("datefield", now);

2)         查询过滤器

通过查询过滤器可以过滤一部分的信息。

Filter filter = new Filter()

        {

       public BitSet bits (IndexReader reader) throws IOException

          {

            BitSet bitset = new BitSet(5);

            bitset.set (1);

            bitset.set (3);

            return bitset;

          }

        };

        // 生成带有过滤器的查询对象

        Query filteredquery = new FilteredQuery (query, filter);

       // 返回检索结果

        Hits hits = searcher.search (filteredquery);

 

这样我们就可以使用自己定义的过滤方式去过滤信息了。

3)     带缓存的过滤器:

使用待缓存的过滤器我们可以重用过滤功能,如下:

MockFilter filter = new MockFilter();

 CachingWrapperFilter cacher = new CachingWrapperFilter(filter);

        cacher.bits(reader);

以上介绍完了现在学习 luence ,没有太详细的介绍它的实现,因为它对于我们来说是一个工具,既然是工具我们就要会用就可以了。

2007/3/12 17:59 作者: 轻舞flash

测试使用新的缓存机制

测试使用新的缓存机制,前台是否即时更新.
临时解决访问速度慢问题.
前台不能即时呈现时请点击右侧刷新按钮,
如果发现更多问题,请即时联系我.

2007/3/10 1:04 作者: venjiang

关于方法重写的。。。大家说说

namespace flaseccie
{
using System;
using System.Collections;
public interface ICommon
{
void DoIt();
}
public class Base:ICommon
{
void ICommon.DoIt(){Console.WriteLine("1");}
public virtual void DoIt(){Console.WriteLine("2");}
}
public class Derived:Base,ICommon
{
void ICommon.DoIt(){Console.WriteLine("3");}
public new virtual void DoIt()
{
Console.WriteLine("4");
}
}
public class ReallyDerived:Derived
{
public override void DoIt()
{
Console.WriteLine("5");
}
}
public class MyClass
{
public static void Main()
{
ReallyDerived reDervied=new ReallyDerived();
Derived derived=reDervied;
Base base =reDervied;
ICommon icommon =reDervied;
reDervied.DoIt();
derived.DoIt();
base .DoIt();
icommon .DoIt();
Console.Read();
}
}
}
把你觉得的输入的结果写出来看看。然后解说一下。。。呵。。。

 

看完上面的后。再看下下面的。

 

namespace flaseccie
{
using System;
using System.Collections;
public interface ICommon
{
void DoIt();
}
public class Base:ICommon
{
void ICommon.DoIt(){Console.WriteLine("1");}
public virtual void DoIt(){Console.WriteLine("2");}
}
public class Derived:Base,ICommon
{
void ICommon.DoIt(){Console.WriteLine("3");}
public override void DoIt()
{
Console.WriteLine("4");
}
}
public class ReallyDerived:Derived
{
public override void DoIt()
{
Console.WriteLine("5");
}
}
public class MyClass
{
public static void Main()
{
ReallyDerived reDervied=new ReallyDerived();
Derived derived=reDervied;
Base base =reDervied;
ICommon icommon =reDervied;
reDervied.DoIt();
derived.DoIt();
base .DoIt();
icommon .DoIt();
Console.Read();
}
}
}


这样子又是多少呢?

2007/3/9 18:22 作者: Blog Author

基于灰度颜色个数的视频截图选取[转]

前几天在帮师兄做一个视频截图的模块,采用了directshow的接口来访问视频文 件。开发工具使用的是visual c++ 2005 express 和visual c# 2005 express,vc++写的一个封装了对directshow的接口访问的dll,然后在c#做的界面程序里面调用。
 
1. 关于directshow的视频截图方法
directshow以前是属于directx内的一个部分,后来microsoft 把directshow归入了platform sdk内了。关于directshow如何来截取视频文件内部的图片picture,在网上可以搜索到很多。在msdn关于directshow sdk的教程里面,也有专门举例如何使用directshow的imediadet接口来截视频流内的截图的:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wcedshow/html/_dxce_dshow_directshow.asp
使用directshow来访问视频文件就可以避免去了解各种视频压缩文件格式,编码格式等等很繁琐甚至是困难的问题了。
 
2. 选择哪个时间点来截视频图片呢?
但是,选取哪个时间点的视频图片呢?我们在看windows浏览器里面视频文件的微缩 图都是视频文件的第一帧,但是如果第一帧是全黑或者全白呢?那么我们看到的这个截下来的视频图片并没有任何意义。甚至比如电影开头的演员字幕等帧,对于观 众来说都没有多大的意义。一部电影的截图选择,如果按照精彩镜头来分,那么需要计算机去理解该电影的内容,这个工作在现阶段来说,涉及到计算机视觉,数字 图像,人工智能等前沿技术,不大可能做得出来。
考虑到全黑,全白,以及片头字幕等没有意义的帧图片的特点,就是颜色个数相对较少,相对单调。于是,可以通过一个颜色个数的阈值,来对所有帧图片进行筛选。将颜色个数小于阈值的剔除。一般使用颜色丰富的图片,肯定帧图片更加丰富。
但是,在24位真彩色中,r,g,b都是0-255,任何一个分量相差了一点点,视觉 上来说,差异并不大,但是对于计算机来说,就完全是两个颜色了,这种过于精确的颜色统计,对于人来说并不见得好。于是,我选择使用颜色的灰度值来代替真彩 色rgb的统计。关于rgb到灰度值的公式,选择的是最简单的:
gray(灰度) = (r + g + b) / 3
 
3. 实现一个测试算法的demo
       好了,大体的截图选取算法思想就是这样了。下面我就一步一步来把这个算法实现的demo,通过visual c++ 2005 express和visual c# 2005 express开发工具做出来。
       首先是做封装directshow的win32 dll。
       microsoft那里下载的visual c++ 2005 express并没有附带platform sdk,windows的最新platform sdk可以直接从microsoft的msdn那里下载到(我选择的是windows 2003 server rc2)。按照msdn上所述的,搭建起visual c++ 2005 express内的platform sdk设置后就可以开发win32的程序了。
       下面是封装的dll的程序代码:
// moviegrabberdll.cpp : 定义 dll 应用程序的入口点。
//
 
#include 
"stdafx.h"
#include 
"moviegrabberdll.h"
bool apientry dllmain( handle hmodule, 
                       dword ul_reason_for_call, 
                       lpvoid lpreserved
                        )
{
     
switch (ul_reason_for_call)
     
{
     
case dll_process_attach: 
     
case dll_thread_attach:
     
case dll_thread_detach:
     
case dll_process_detach:
         
break;
     }

    
return true;
}

 
/**
* 抓取视频的截图
* @param apath 视频文件的位置
* @return
*/

moviegrabberdll_api handle grabmovieframe(lpctstr apath,
int graycolorcountthreshold)
{
     hresult hr;
     
// 定义imediadet接口实例
     ccomptr< imediadet > pdet;
     hr 
= pdet.cocreateinstance(__uuidof(mediadet));
     
if (failed(hr))
         
return null;
 
     
// 将影片文件名转换成bstr类型
     ccombstr openbstr(apath);
     
// 设置imediadet接口的文件关联
     hr = pdet->put_filename(openbstr);
     
if (failed(hr))
         
return null;
 
     
// 从影片中检索视频流和音频流
     long lstreams;
     hr 
= pdet->get_outputstreams(&lstreams);
     
if (failed(hr))
         
return null;
 
     
// 取出影片的视频流,因为帧的信息是保存在视频流中的
     bool bfound = false;
     
for (int i=0; i<lstreams; i++)
     
{
         guid major_type;
         hr 
= pdet->put_currentstream(i);
         
if (succeeded(hr))
              hr 
= pdet->get_streamtype(&major_type);
         
if (failed(hr))
              
break;
         
if (major_type == mediatype_video)
         
{
              bfound 
= true;
              
break;
         }

     }

     
if (!bfound)
         
return null;
 
     
long width = 0, height = 0// 存储位图的宽和高(单位:象素)
     am_media_type mt;
     hr 
= pdet->get_streammediatype(&mt);
     
if (succeeded(hr))
     
{
         
if ((mt.formattype == format_videoinfo) && 
              (mt.cbformat 
>= sizeof(videoinfoheader)))
         
{
              
// 得到videoinfoheader结构指针,videoinfoheader结构包含一些与视频
              
// 有关的信息,其中含有bitmapinforheader结构
              videoinfoheader *pvih = (videoinfoheader*)(mt.pbformat);
              width 
= pvih->bmiheader.biwidth;
              height 
= pvih->bmiheader.biheight;
              
if(height < 0 ) height *= -1;
         }

         
else
              hr 
= vfw_e_invalidmediatype;
         myfreemediatype(mt); 
// 释放am_media_type结构
     }

     
if (failed(hr))
         
return null;
     
return (handle)lookforsuitablemovieframe(pdet,width,height,graycolorcountthreshold);
}

 
/**
* 写入合适视频帧截图到磁盘
* @param pdet directshow的imediadet接口
* @param width 截图的长
* @param height 截图的宽
* @param graycolorcountthreshold 灰度颜色个数阈值
*/

hbitmap lookforsuitablemovieframe(imediadet
* pdet,int width,int height,int graycolorcountthreshold)
{
     
long size;
     
double time = 0.0;
     
double totaltime;
 
     
// 获取整个视频的时间长度
     pdet->get_streamlength(&totaltime);
     
// 每1秒,截取视频截图
     for(time=0.0; time <totaltime; time+= 1.0
     
{
         
// 获取bitmap的buffer大小
         hresult hr = pdet->getbitmapbits(time, &size, 0, width, height);
         
if (succeeded(hr)) 
         
{
              
char *pbuffer = new char[size];
              
if (!pbuffer)
                   
return null;
              hr 
= pdet->getbitmapbits(time, 0, pbuffer, width, height);
              
if (succeeded(hr))
              
{
                   
// find the address of the start of the image data.
                   void *pdata = pbuffer + sizeof(bitmapinfoheader);
                   
if(issuitablemovieframe(pdata,width,height,graycolorcountthreshold))
                   
{
                       bitmapinfoheader 
*bmih = (bitmapinfoheader*)pbuffer;
                       hdc hdcdest 
= getdc(0);
 
                       bitmapinfo bmi;
                       zeromemory(
&bmi, sizeof(bitmapinfo));
                       copymemory(
&(bmi.bmiheader), bmih, sizeof(bitmapinfoheader));
                       hbitmap hbitmap 
= createdibitmap(hdcdest, bmih, cbm_init, 
                            pdata, 
&bmi, dib_rgb_colors);
 
                       delete[] pbuffer;
                       
return hbitmap;
                   }

              }

              delete[] pbuffer;
         }

     }

     
return null;
}

 
/**
* 检测一个位图是否是合适的视频截图
* @param pdata 位图的点色数组
* @param width 位图的长
* @param height 位图的宽
* @param graycolorcountthreshold 灰度颜色个数阈值
*/

bool issuitablemovieframe(void* pdata,int width,int height,int graycolorcountthreshold)
{
     byte
* pixels = (byte*)pdata;
     
int numgraycolor = 0;
     
int size = width*height;
     
int graycolor;
     
int i,j;
     
int* appearedcolors = new int[graycolorcountthreshold];
     
int numappearedcolors = 0;
     
for(i=0;i<size; i++
     
{
         
// 计算当前点的灰度值,采用的rgb转换灰度的公式是gray = (r+g+b)/3
         graycolor = (pixels[i*3+pixels[i*3+1]+pixels[i*3+2])/3;
         
// 检测该灰度色是否之前出现过
         for(j=0;j<numappearedcolors; j++
         
{
              
if(graycolor == appearedcolors[j])
                   
break;
         }

         
if(j == numappearedcolors) // 如果是新的灰度颜色值
         {
              numappearedcolors
++;
              
if(numappearedcolors == graycolorcountthreshold) // 如果灰度颜色个数满足阈值
              {
                   delete[] appearedcolors;
                   
return true// 返回信息,合适
              }

              
else
              
{
                   appearedcolors[j] 
= graycolor; // 记录下该灰度颜色值
              }

         }

     }

     delete[] appearedcolors;
     
return false// 返回信息,不合适
}

 
void myfreemediatype(am_media_type& mt)
{
     
if(mt.cbformat != 0)
     
{
         cotaskmemfree((pvoid)mt.pbformat);
         mt.cbformat 
= 0;
     }

 
     
if (mt.punk != null)
     
{
         mt.punk
->release();
         mt.punk 
= null;
     }

}
 
其中,为了使用directshow,我们除了需要windows.h外,还需要dshow.h,qedit.h和atlbase.h三个头文件,最后再加上一个strmiids.lib库文件。
 
接下来就开启visual c# 2005 express来做一个简单的界面程序。为什么选择c# 来开发界面程序呢?原因很简单,因为c#很简单,同时visual c# 2005 express这样免费又功能强大的工具可以使用。
界面程序很简单,就下面这个样子:
 
       c# 部分调用前面写好的dll函数,实现ddshow的抓图。 moviegrabberdll.cs源代码如下:
using system;
using system.collections.generic;
using system.text;
using system.runtime.interopservices;
using system.drawing;
 
namespace moviegrabbercsharp
{
    
class moviegrabberdll
    
{
        [dllimport(
"moviegrabberdll.dll")]
        
public static extern int fnmoviegrabberdll();
 
        [dllimport(
"moviegrabberdll.dll")]
        
public static extern intptr grabmovieframe(string apath, int graycolorcountthreshold);
 
        
public static bitmap grabmovieframebitmap(string apath,int graycolorcountthreshold)
        
{
            intptr hbitmap 
= grabmovieframe(apath, graycolorcountthreshold);
            
if(hbitmap == intptr.zero)
                
return null;
            
return bitmap.fromhbitmap(hbitmap);
        }

 
        
public static bitmap grabmovieframebitmap(string apath)
        
{
            
return grabmovieframebitmap(apath, 8);
        }

    }

}

 
窗口类mainform.cs的源代码如下:
using system;
using system.collections.generic;
using system.componentmodel;
using system.data;
using system.drawing;
using system.text;
using system.windows.forms;
 
namespace moviegrabbercsharp
{
    
public partial class mainform : form
    
{
        
public mainform()
        
{
            initializecomponent();
        }

 
        
private void openmoviefilepathbutton_click(object sender, eventargs e)
        
{
            openfiledialog dlg 
= new openfiledialog();
            
if (dlg.showdialog() == dialogresult.ok)
            
{
                moviefilepathtextbox.text 
= dlg.filename;
            }

 
        }

 
        
private void grabberbutton_click(object sender, eventargs e)
        
{
            bitmap bitmap 
= moviegrabberdll.grabmovieframebitmap(moviefilepathtextbox.text);
            
if (bitmap != null)
            
{
                messagebox.show(
"抓图成功!");
                grabberpicturebox.sizemode 
= pictureboxsizemode.stretchimage;
                grabberpicturebox.image 
= bitmap;
                grabberpicturebox.invalidate();
                grabberpicturebox.refresh();
            }

            
else
            
{
                messagebox.show(
"失败!");
            }

        }

 
        
private void exitbutton_click(object sender, eventargs e)
        
{
            
this.close();
        }

    }

}

 
编译完成后,我们使用windows里面的一个intro.wmv视频文件来做测试, 具体路径是:c:\windows\system32\oobe\imagee\intro.wmv。之所以选择这个文件作为视频测试文件,因为这个视频 是大家安装完成后winxp后都会自动启动的windows xp的介绍视频,而且这个视频的开始部分是全黑,然后渐渐变亮,再到windows xp的动画部分。如果用windows自带的浏览器看微缩图显示,就是下面这个结果:
       可以看到,这个intro.wmv的微缩图是完全的一张黑色图片,我们并不能看到任何关于视频文件有意义的内容。
       下面启动我们刚才编写的demo视频截图工具来截一下图片,同样这个视频文件,可以看到这个的结果。
      
 
       其中,程序里面默认给出的灰度颜色个数阈值是8,那么就是说,至少图片要有8个不同的颜色灰度值才会截取,而之前的全黑,全白就自然滤过了。

http://www.z6688.com/info/48101-1.htm

2007/2/4 21:04 作者: jacky

FFmpeg相关下载

FFmpeg
http://ffdshow.faireal.net/mirror/ffmpeg/

pthread32
http://www.signal.uu.se/Toolbox/dream/download.html
ftp://sourceware.org/pub/pthreads-win32/

2007/2/4 20:27 作者: jacky

转换视频文件为flv媒体格式[转]

视频转换的方法找了不少,最后整个过程记录如下:

转换环境: window2003
转换工具: FFMpeg
转换步骤:
1/ 从 http://ffdshow.faireal.net/mirror/ffmpeg/ 下载最新版本的 FFMpeg.exe (才知道.7z也是种压缩格式)
2/ 解压缩到本地c:\FFMpeg.

3/ 转换视频文件Command Line格式:
转换视频:
ffmpeg.exe -i "e:\input\06.asf" "e:\output\06.mpg" //非flv格式
ffmpeg.exe -i "e:\input\06.asf" -y -ab 56 -ar 22050 -b 500 -r 15 -s 320*240 test.flv //Flv格式
视频抓图:

ffmpeg.exe -i "e:\input\06.asf" -y -f image2 -t 0.001 -s 300*200 "e:\output\02.jpg" //获取静态图


ffmpeg.exe -i "e:\input\06.asf" -vframes 30 -y -f gif "e:\output\02.gif" //获取动态图

4/ 转换为flv文件后,使用Flash编写客户端浏览工具:
4.1/ 新建fla文件,窗口->组建->把FLVPlayback拖拉到画布上.Alt+F7 Skin参数选择播放器外观.
4.2/ 选中FLVPlayback,属性->参数里面把实例名字修改为 FFPlay.图层关键帧写入代码:
FFPlay.contentPath = FilePath;
5/ 嵌入网页的组建增加:<param name="FlashVars" value="FilePath=flv文件路径">和embed里面增加:FlashVars="FilePath=flv文件路径" .前者是for ie的后者是for ff的.

PS.
1/对ffmpeg无法解析的文件格式(WMV9,rm,rmvb),可以先用别的工具转换为avi或者mpg格式.
2/对转换为flv后,客户端工具播放没有时间轴的情况,需要使用 flvmdi.exe 把flv文件增加时间头信息,命令为:

flvmdi.exe "filename.flv" /k




















我也开始研究ffmpeg这个强大的转换工具了
www.uume.com上传视频时应该也是用的这个
刚试着把4M大的avi转成flv,结果flv的体积达到了7M之多,看来是命令行的参数不合适
现转一些有用的东东
部分参数说明
ffmpeg.exe -i F:\闪客之家\闪客之歌.mp3 -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:\11.flv
ffmpeg -i F:\01.wmv -ab 56 -ar 22050 -b 500 -r 15 -s 320x240 f:\test.flv
使用-ss参数 作用(time_off set the start time offset),可以从指定时间点开始转换任务。如:
转换文件格式的同时抓缩微图:
ffmpeg -i "test.avi" -y -f image2 -ss 8 -t 0.001 -s 350x240 'test.jpg'
对已有flv抓图:
ffmpeg -i "test.flv" -y -f image2 -ss 8 -t 0.001 -s 350x240 'test.jpg'
-ss后跟的时间单位为秒
Ffmpeg转换命令
ffmpeg -y -i test.mpeg -bitexact -vcodec h263 -b 128 -r 15 -s 176x144 -acodec aac -ac 2 -ar 22500
-ab 24 -f 3gp test.3gp
或者
ffmpeg -y -i test.mpeg -ac 1 -acodec amr_nb -ar 8000 -s 176x144 -b 128 -r 15 test.3gp
 
 
ffmpeg参数设定解说
-bitexact 使用标准比特率
-vcodec xvid 使用xvid压缩
-s 320x240 指定分辨率
-r 29.97 桢速率(可以改,确认非标准桢率会导致音画不同步,所以只能设定为15或者29.97)
画面部分,选其一
-b <比特率> 指定压缩比特率,似乎ffmpeg是自动VBR的,指定了就大概是平均比特率,比如768,1500这样的
就是原来默认项目中有的
-qscale <数值> 以<数值>质量为基础的VBR,取值0.01-255,约小质量越好
-qmin <数值> 设定最小质量,与-qmax(设定最大质量)共用,比如-qmin 10 -qmax 31
-sameq 使用和源同样的质量
声音部分
-acodec aac 设定声音编码
-ac <数值> 设定声道数,1就是单声道,2就是立体声,转换单声道的TVrip可以用1(节省一半容量),高品质
的DVDrip就可以用2
-ar <采样率> 设定声音采样率,PSP只认24000
-ab <比特率> 设定声音比特率,前面-ac设为立体声时要以一半比特率来设置,比如192kbps的就设成96,转换
君默认比特率都较小,要听到较高品质声音的话建议设到160kbps(80)以上
-vol <百分比> 设定音量,某些DVDrip的AC3轨音量极小,转换时可以用这个提高音量,比如200就是原来的2倍
这样,要得到一个高画质音质低容量的MP4的话,首先画面最好不要用固定比特率,而用VBR参数让程序自己去
判断,而音质参数可以在原来的基础上提升一点,听起来要舒服很多,也不会太大(看情况调整
 
 
例子:ffmpeg -y -i "1.avi" -title "Test" -vcodec xvid -s 368x208 - r 29.97 -b 1500 -acodec aac -ac 2 -ar 24000 -ab 128 -vol 200 -f psp -muxvb 768 "1.***"

解释:以上命令可以在Dos命令行中输入,也可以创建到批处理文件中运行。不过,前提是:要在ffmpeg所在的目录中执行(转换君所在目录下面的cores子目录)。
参数:
-y(覆盖输出文件,即如果1.***文件已经存在的话,不经提示就覆盖掉了)
-i "1.avi"(输入文件是和ffmpeg在同一目录下的1.avi文件,可以自己加路径,改名字)
-title "Test"(在PSP中显示的影片的标题)
-vcodec xvid(使用XVID编码压缩视频,不能改的)
-s 368x208(输出的分辨率为368x208,注意片源一定要是16:9的不然会变形)
-r 29.97(帧数,一般就用这个吧)
-b 1500(视频数据流量,用-b xxxx的指令则使用固定码率,数字随便改,1500以上没效果;还可以用动态码率如:-qscale 4和-qscale 6,4的质量比6高)
-acodec aac(音频编码用AAC)
-ac 2(声道数1或2)
-ar 24000(声音的采样频率,好像PSP只能支持24000Hz)
-ab 128(音频数据流量,一般选择32、64、96、128)
-vol 200(200%的音量,自己改)
-f psp(输出psp专用格式)
-muxvb 768(好像是给PSP机器识别的码率,一般选择384、512和768,我改成1500,PSP就说文件损坏了)
"1.***"(输出文件名,也可以加路径改文件名)

P.S. 版主机器强劲的话,可以多开几个批处理文件,让它们并行处理。
E:\ffmpeg.exe -i I:\1.wmv -b 360 -r 25 -s 320x240 -hq -deinterlace -ab 56 -ar 22050 -ac 1 D:\2.flv


















下边是截图CatchImg方法,可从大多数的视频文件中截图成功,大家可测试;
如果截图不成功,大多是因为视频本身的问题,如编码标准或加了密.
但从在线录制的视频Flv文件中截图,还未发现截图失败;

/// <summary>
/// @从视频文件截图,生成在视频文件所在文件夹
/// 在Web.Config 中需要两个前置配置项:
/// 1.ffmpeg.exe文件的路径
/// <add key="ffmpeg" value="E:\ffmpeg\ffmpeg.exe" />
/// 2.截图的尺寸大小
/// <add key="CatchFlvImgSize" value="240x180" />
/// 3.视频处理程序ffmpeg.exe
/// </summary>
/// <param name="vFileName">视频文件地址,如:/Web/FlvFile/User1/00001.Flv</param>
/// <returns>成功:返回图片虚拟地址; 失败:返回空字符串</returns>
public string CatchImg(string vFileName)
{
//取得ffmpeg.exe的路径,路径配置在Web.Config中,如:<add key="ffmpeg" value="E:\ffmpeg\ffmpeg.exe" />
string ffmpeg=System.Configuration.ConfigurationSettings.AppSettings["ffmpeg"];

if ( (!System.IO.File.Exists(ffmpeg)) || (!System.IO.File.Exists(vFileName)) )
{
return "";
}

//获得图片相对路径/最后存储到数据库的路径,如:/Web/FlvFile/User1/00001.jpg
string flv_img = System.IO.Path.ChangeExtension(vFileName,".jpg") ;

//图片绝对路径,如:D:\Video\Web\FlvFile\User1\0001.jpg
string flv_img_p = HttpContext.Current.Server.MapPath(flv_img);

//截图的尺寸大小,配置在Web.Config中,如:<add key="CatchFlvImgSize" value="240x180" />
string FlvImgSize=System.Configuration.ConfigurationSettings.AppSettings["CatchFlvImgSize"];

System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(ffmpeg);
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;

//此处组合成ffmpeg.exe文件需要的参数即可,此处命令在ffmpeg 0.4.9调试通过
startInfo.Arguments = " -i " + vFileName + " -y -f image2 -t 0.001 -s " + FlvImgSize + " " + flv_img_p ;

try
{
System.Diagnostics.Process.Start(startInfo);
}
catch
{
return "";
}

///注意:图片截取成功后,数据由内存缓存写到磁盘需要时间较长,大概在3,4秒甚至更长;
///这儿需要延时后再检测,我服务器延时8秒,即如果超过8秒图片仍不存在,认为截图失败;
///此处略去延时代码.如有那位知道如何捕捉ffmpeg.exe截图失败消息,请告知,先谢过!
if ( System.IO.File.Exists(flv_img_p))
{
return flv_img;                                            
}

return "";
}

顺便也探讨个问题,就是我无法从ffmpeg.exe捕捉截图失败消息~
不知大家可否有办法取得,我目前只能通过检测图片是否生成来判断成功与否,但时间较慢,因为这个检测程序就让用户要多等大概4,5秒时间.。

2007/2/4 20:19 作者: jacky

安装Visual Studio 2005 Service Pack 1

前几日jacky告诉我vs2k5 sp1出了,随即下载.今日抽空赶紧安装.

准备环境:

Microsoft? Visual Studio? 2005 Service Pack 1

下面为中文版
下载地址:
Microsoft? Visual Studio? 2005 Service Pack 1
下载地址:
http://www.microsoft.com/downloads/details.aspx?FamilyID=bb4a75ab-e2d4-4c96-b39d-37baf6b5b1dc&DisplayLang=zh-cn

  • 安装要求:
    • 目标计算机上必须安装了受支持的 Visual Studio® 2005 产品副本。
    • 目标计算机上安装了 Microsoft® Windows® Installer 3.1 或更高版本。
    • 至少 192MB 的 RAM。建议使用 256MB 或更大内存。
    • 硬盘空间至少为 6.2GB
      • 如果目标计算机上安装了多个 Visual Studio® 2005 产品,硬盘空间要求也会相应大大增加。


  • 安装可能出现问题解决办法:
    http://support.microsoft.com/kb/925336 

    几个朋友提示安装过程费了些周折,为避免安装出现问题,请按上面的方法,先修改本地安全策略.
    M$这个要求有6G空间,这个实在有些愁人,一些朋友也因空间问题安装出错,抓紧整理我的硬盘空间,但资料实在太多,一时半日无法整理出6G空间.一个补丁400M,干嘛要求这么多空间,M$不是在折腾我们嘛. 决定尝试安装.

    安装前环境:
    剩余空间:
    C: 3.88G
    D: 3.57G

    Visual Studio 2005 安装在D盘,临时文件夹在C盘,如果你有修改系统临时文件夹路径,确保所在盘有足够空间.
    Visual Studio 2005我是重新安装的,没有安装VB,VC++,其余都有安装.上面所列硬盘空间容量为安装VS2005后剩余.

    安装过程中:
    剩余空间:
    C: 2.54G
    临时文件写入,然后开始收集信息,过程比较漫长.这个时间你可以去看电视了.或者干脆小睡一会儿,不知道M$花这么长时间收集什么,小心把电脑里的MM搜集走. 在这个过程中,临时文件夹写入450多M,C盘其它地方写入不到1G, 任务管理器查看,整个SP1补丁被全部载入内存,安装程序占用CPU 50%左右.为避免出现什么异外,建议不要开太多程序.


    搜集完信息,开始安装....

    这个时间不准确,可以去抽颗烟,喝杯咖啡.

    安装完成后:
    剩余空间:
    C: 2.98G
    D: 3.56G


    VS2005版本


    总结:
    整个过程安装比较顺利,可以看到在搜集信息时,C盘写入1.34G,安装完成后,删除了临时文件,减少450M,D盘,也就是VS2005所在文件夹写入信息并不多.这样看来,如果只安装C#版本的VS,打补丁,C盘有1.5G应该足够了,VS2005安装所在目录并不需要太多空间.当然,如果你的VS2005安装的组件比较多的话,相应空间要求会提高不少.但至少6G这个要求并不是必须的.

    测试:
    终于可以在中文版上运行Web Application Project了.
    新建:


    项目解决方案:


    编译:


    运行:


    另.打开先前M$提供的Web Application Project 项目,可以成功加载.

    至此,Visual Studio? 2005 Service Pack 1安装完毕.

    2006/12/18 3:02 作者: venjiang

    Sharepoint v3, 如何设置Forms验证模式

    *from link: http://www.bentan.cn/Blog/Lists/Posts/Post.aspx?ID=2
    *作者: Ben,
    benjamine65@hotmail.com

    *参考网站: http://www.bentan.cn

    *本文使用Windows Sharepoint Services v3 beta 2英文版, 版本号: 12.0.0.4017

       

    众所周知, Sharepoint3在同系列Office 2007 beta2出来的时候已经被推出了. 其中它的新feature包括支持工作流WWF; 支持Blog等Web2网站; 支持RSS订阅; 支持Mobile设备访问等, 无论在性能上还是服务架构上设计都有所提高. 但今天要谈的并不是她这些方面的特性, 而是作者在Sharepoint2梦寐的功能: 支持Forms验证.

    1    简介如何安装Sharepoint v3

    准备的安装软件:

              Sharepoint v3 Beta2安装程序

              (如果是标准安装可以忽略)SQL Server 2005 (作者使用的是EXPRESS版本)

              WWF Components Beta 2.2

    安装环境需求:

         (请参考微软相关网站介绍)

    安装步骤:

         A. (如果是标准安装可以忽略)安装SQL Server 2005

         B. 安装WWF Component

         C. 运行Sharepoint v3安装向导step by step直至完成安装(本文是根据Advanced方式安装)

       

    2    配置Sharepoint 3.0 Central Administration网站

    2.1     从"管理工具"点击SharePoint 3.0 Central Administration图标进入

    2.2     因为第一次运行SharePoint 3.0 Central Administration, 会有提示出现, 这里要按向导完成SharePoint 3.0 Central Administration网站的创建.

       

    * 这里需要注意的,如果你之前安装而又删除了Sharepoint 3.0的其它beta版本, 或者相同的beta版本, 在此向导最后一步的创建SharePoint 3.0 Central Administration网站数据库时会出现the language is not supported on the server的错误. 这是因为删除时将注册表的语言key值给删除了, 要将以下存成.reg文件, 并执行合并到注册表:

    Windows Registry Editor Version 5.00

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\12.0\ServerLanguage]

    "1033"=""

       

    3    创建Web Application

    3.1     进入SharePoint 3.0 Central Administration

    3.2       进入Application Management 配置页面

    3.3     在SharePoint Web Application Management类下点击Create or extend Web application进行创建Web application. 这一步骤是自动在IIS上创建一个Sharepoint网站目录,或者扩展现有的IIS网站目录

       

    4    设置Forms验证 (两步曲)

    4.1     在SharePoint 3.0 Central Administration设置

    4.1.1             进入: Central Administration > Application Management > Authentication Providers.

    4.1.2             选择你要设置的Web application

    4.1.3             providers列表中只有一项membership provider, 这membership provider与ASP.NET 2的membership provider是相同概念. 现在Sharepoint v3默认的membership provider是Windows验证方式, 点击Windows列表链接可以进入设置.

    4.1.4             在Edit Authentication页面里, 设置Authentication Type项为Forms;如果允许匿名访问的就在将Anonymous Access项的Enable anonymous access的选项打上钩; Membership Provider Name项目值为: AspNetSqlMembershipProvider, 然后按Save保存设置.

    4.2       修改SharePoint 3.0 Central Administration的Web.config. 因为将会在下一步骤创建site collection时要选择site collection的管理员, 所以要配置一下membership的数据库路径: 将

      <connectionStrings>

        <remove name="LocalSqlServer" />

        <add name="LocalSqlServer" connectionString="Data Source=数据库服务器地址;database=步骤2创建的Central Administration网站数据库名;uid=登录用户名;pwd=数据库登录密码" />

      </connectionStrings>

    加在Web.config的<configuration>键下.

       

    * 因为ASP.NET 2中Web.config默认的forms membership provider是AspNetSqlMembershipProvider, 而AspNetSqlMembershipProvider使用的SQL链接地址默认是LocalSqlServer的Connection String.

       

    4.3     IISRESET

       

    5     创建membership数据库和用户(两步曲)

    5.1       创建membership数据结构

    运行.net framework 2的命令行aspnet_regsql.exe工具来创建membership数据结构

    5.2       利用ASP.NET 2程序添加membership用户

    用Visual Studio 2005创建一个web site项目, 按4.2步骤的web.config配置方法同样修改这个web site项目的web.config文件; 运行membership管理, 并在security管理里添加用户.

       

    6     创建Sharepoint site collection (两步曲)

    到这步骤为止, Sharepoint的环境才算配置完成, 现在就是创建Sharepoint site collection.

    6.1     在SharePoint 3.0 Central Administration设置

    6.1.1             进入: Central Administration > Application Management > Create Site Collection.

    6.1.2             输入相关的Title, Web Site Address, Site Collection Administrator(这里输入5.2步骤里添加到membership管理的用户名)和网站模板

    6.1.3             按OK完成

    6.2     修改web.config文件 (按4.2步骤的web.config配置方法同样修改当前sharepoint site collection的IIS目录下的web.config文件), OK后再运行一下IISRESET就可以用5.2步骤添加的用户身份进forms验证方式访问此Sharepoint网站了

       

       

    总结

    :

    1.        在Sharepoint 3.0里, Central Administration网站也是一个完整的Sharepoint网站, 而且必须要先创建这个Sharepoint网站.

    2.        创建sharepoint网站要经两个步骤: 第一要创建扩展web application目录(即IIS网站); 第二步就是创建Sharepoint site collection.

    3.        配置forms验证, 因为要在Central Administration网站的web.config文件也要添加membership数据库链接地址.

       

       

    后话

       

    由于Sharepoint v3的forms验证是ASP.NET 2的AspNetSqlMembershipProvider实现的, 所以用户注册管理等backend管理可以用ASP.NET 2开发实现.

    2006/11/23 15:50 作者: Ben

    用Beta2的Key激活Vista RTM的方法

    分享一下Vista的喜悦, 共享激活方法.

    前提:

    先准备要替换RTM的两个文件pkeyconfig.xrm-ms和tokens.dat. (如果你想要这两个文件的话, 请留言)

       

    步骤:

    1. 安装RTM版,安装开始时要key验证, 就输入这个key: YFKBB-PQJJV-G996G-VWGXY-2V3X8, (key验证通过后它会问你安装哪个版本Vista, 我选择是Ultimate)

       

    2. 启动Vista, 进入c:\Windows\System32\Licensing\pkeyconfig目录, 将pkeyconfig.xrm-ms文件的权限分配给administrator是Full Control(很BT, Vista里就算你是admdinistrator登录进入, 也是受限权限用户来的),

    方法: 右击pkeyconfig.xrm-ms文件 -> Properties -> Security -> Advanced -> Owner -> Edit -> 选择administrator -> OK. 到这里, 按提示, 全部按OK关闭开它的Properties窗口, 再重新打开它的Properties窗口 -> Security -> Advanced -> Edit -> 选择administrator, 点Edit -> 分配Full Control权限并OK关闭属性窗口

       

    3.重启进入安全模式, 用我提供的这个pkeyconfig.xrm-ms覆盖步骤2里的pkeyconfig.xrm-ms文件.

    确保Software Licensing当前状态是停止的

       

    进入C:\Windows\ServiceProfiles\NetworkService\AppData\Roaming\Microsoft\SoftwareLicensing, 用我提供的 tokens.dat 替换里面的 tokens.dat 文件.

       

    4. 重启以正式模式启动

    在输入用户名密码后, 它会要求你输入Product Key来激活, 顺便找一个试用Key输入去就OK了. 听说H7RPG-XDMJM-WTY9D-VYJ3C-CB3KJ这个Key可以用, 我没试过, 我是用beta 2光盘盒上的key.

       

    然后它自动联网去激活Vista.

    2006/11/23 15:43 作者: Ben

    Amazing VISTA !!

    昨晚在Vista诱惑驱动下, 奋战几个小时, 终于将Vista RTM和日常使用开发的工具"完好"的安装起来, 为什么这里特别说"完好"呢, 因为Vista不是什么软件都兼容的, 下面列出几个使用后感:

    1. 安装Vista前, 建议先找个Windows Vista Upgrade Advisor来看看你的机器能不能使用Vista的主要功能;
    2. 安装好后安装daemon虚拟光驱3.*版本会蓝屏死机, 即使进入安全模式也启动不起来, 只能用安装盘来repair windows
    3. Vista的backup和restore功能非常漂亮,用户可以自定义restore point, 系统还会自动的在每次安装一些应用软件的时候保存restore point, 我的蓝屏问题全靠这个智能的功能避免了重装之苦. 而且 restore的速度也不赖.
    4. 安装SQL Server 2005 Express要打SP1
    5. ActiveSync不用安装了, 因为它自带有了同步工具, 只需上网升级一下同步工具, 让它有支持PPC/Smartphone的就OK了,安装了ActiveSync的就算了, 反安装它就会连系统自带的一个似类叫ISAP.dll文件删除, Vista的同步工具将不能启动, 只能又通过restore来恢复了
    6. 输入法. 这个现象很奇怪, 如果用Run as Administrator的模式打开IE, 然后在网页里的输入框或右上角的查找框里用极点, 陈桥输入中文就很正常, 但如果是普通模式打开IE时极点与陈桥都出错了, 除了微软自带的那些输入法… 真郁闷…
    7. 安装了Office 2007, 发觉Word 2007的博客文章发布功能真是Cool J, 可以不用打开网页写文章了, 只需点击"发布"一下.
    8. 用了几天, 发觉分的系统区20G不够用…建议分它25到30G的最好了.

    2006/11/23 15:34 作者: Ben

    Windows Vista RC1(5744)全体验(一)

    安装环境:VMWare 5.5.2

    虚拟光驱:Alcohol 120%

    Windows Vista版本:vista_5744.16384.061003-1945_x86fre_client-lrmcfre_en_cn_dvd.iso

     

    用VMWare直接载入ISO作为一个驱动器使用,装了N次都没成功,后来改用虚拟机在HOST中先LOAD,再把该光区添加到虚拟机中,安装成功。

    废话不多说,直接看图

     

    载入文件,开始安装

     

     

    输入序列号:

     

    接受License

     

     

    选择安装方式

     

    选择磁盘分区

     

    创建了个新磁盘分区

     

    开始安装……

     

    重新载入,有乱码……

     

    变中文的了……

    继续安装……

     

    选择登陆用户名,个人图片

    选择墙纸,安全设置:

    设置时区

    非常感谢:

    继续……

    登陆……

    桌面~

     

     

    关机

     

    个人感觉性能还是不错的。

    1、安装比以前的系统快多了。

    2、P4 2.0G,1G的内存可以跑得很好了~

     

    其他待续……:)

    2006/11/14 10:47 作者: jacky

    hiDotNet 旗下产品 Opensoft .NET Framework 2.0 公开发布测试。

    欢迎访问开软系统框架测试平台。
    hiDotNet 旗下产品 Opensoft .NET Framework 2.0 公开发布测试。

    本示例只选用了框架的部分控件作为基本功能演示,且控件的示例都以最简单最常用功能为基础,
    Opensoft .NET Framework 2.0 版本中已包含基本 Web 扩展控件 27 个,Callback 控件 8 个,Service 控件 1 个。
    最终发布版本会增加更多控件及常用方法的封装类。
    每个控件命名空间下包含一个基类,继承该基类即已实现控件的大部分功能,
    开发人员只需要在相应的方法中写入自己需要的内容即可实现对框架中控件功能的扩展。

    给开发人员的说明:
    OSDN 中包含基础类的文档说明以及使用示例,由于控件示例代码较多,故不包含在 OSDN 中,
    而被单独放在 Examples 站点中,这样可以方便开发人员直接预览使用效果。

    最后,欢迎您试用 Opensoft .NET Framework 2.0,对于您提出的合理建议都将可能被收录到下一个版本中。
    使用 Opensoft .NET Framework 的开发人员可以在开软客户服务中心:(QQ群 - 6531718)获取在线帮助,
    或登陆论坛 bbs.hidotnet.com 发表意见及建议。
    hiDotNet 博客苑 随时欢迎您登陆。

    2006/11/3 21:40 作者: Dolphin

    BlogML 2.0 is Released

    BlogML是什么?
    BlogML是blog内容的XML格式存储,你能够使用它归档blog内容,或者作为博客转换/迁移的标准格式.当前已有数个blog引擎提供了这个支持.
    • Community Server
    • Das Blog
    • Subtext
    • SingleUserBlog


    你能够在这里下载 BlogML 2.0.

    2006/10/25 11:15 作者: venjiang

    Windows Live Writer测试

    风景PP奉上一张:

    2006/10/17 23:37 作者: jacky

    开张篇

    这段时间忙得一塌糊涂

    这不, 现在一身疲惫才回到家

    不过刚回来就接到VJ的很一个好消息

    就是hiDotNet的Blog开张了

    就抢鲜开了个好ID

    顺祝在兄弟的努力下

    本Blog越搞越大, 再热, 再火, 再...

     

    2006/10/11 22:47 作者: Ben

    2008 年后的计划。

    2006/10/11 22:04 作者: kki

    关于Cache的疑惑

    Cache.Insert("CacheKey", value, null, DateTime.Now.AddSeconds(30), TimeSpan.Zero, CacheItemPriority.Normal, null);

    Cache.Insert("CacheKey", value, null, DateTime.Now.AddSeconds(30), System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);

    前者很少有命中.
    后者才是按时间命中.

    System.Web.Caching.Cache.NoSlidingExpiration实际也是设置为TimeSpan.Zero.
    MSDN如是说:
    使用后,该字段将 slidingExpiration 参数设置成 TimeSpan.Zero 字段,该字段具有常数值零。缓存项依照与 Insert 或 Add 方法调用相关的 absoluteExpiration 参数设置过期。

    无法同时设置 absoluteExpiration 和 slidingExpiration 参数。如果要让缓存项在特定时间过期,可将 absoluteExpiration 参数设置为特定时间,并将 slidingExpiration 参数设置为 NoSlidingExpiration。

    如果要让缓存项自最后一次访问该项后的某段时间之后过期,可将 slidingExpiration 参数设置为过期间隔,并将 absoluteExpiration 参数设置为 NoAbsoluteExpiration。

    MSDN:示例
    Cache.Insert("DSN", connectionString, null, DateTime.Now.AddMinutes(2), TimeSpan.Zero, CacheItemPriority.High, onRemove);
     

    而这种方法,用户访问后,立即过期,缓存实际上根本无法命中.
    MSDN上的示例都是如此.

    ?????
     

    2006/10/11 16:35 作者: venjiang

    hiDotNet博客开通

    测试期...

    目标,将建立成高负载的博客系统,分布式缓存策略等.

    开篇纪念.

    2006/10/11 16:26 作者: venjiang

    blog诞生纪念帖~

    恭喜一下先。

    2006/10/11 16:11 作者: jacky