Let's Go!

发布新日志

  • csdn开源频道--自己找宝

    2010-12-21 00:10:54

     

    csdn开源频道

    http://www.oschina.net/project/search?q=%E8%B0%83%E8%AF%95&sort=default&lang=19

    JFreeChart主要用来各种各样的图表,这些图表包括:饼图、柱状图(普通柱状图以及堆栈柱状图)、线图、区域图、分布图、混合图、甘特图以及一些仪表盘等等。

    http://www.oschina.net/p/jfreechart

    demo

    http://www.jfree.org/jfreechart/samples.html

     

    LogMiner 是一个功能强大的 Apache 和 IIS 或者其他Web服务器(使用combined日志模式或者是扩展 W3C日志格式)的日志分析工具,它可以生成关于访问者、点击、流量、导航路径、浏览器、操作系统等方面数据的详细报表。

    http://www.oschina.net/p/logminer

     

     

    Ganglia是一个跨平台可扩展的,高 性能计算系统下的分布式监控系统,如集群和网格。它是基于分层设计,它使用广泛的技术,如XML数据代表,便携数据传输,RRDtool用于数据存储和可 视化。它利用精心设计的数据结构和算法实现每节点间并发非常低的。它已移植到广泛的操作系统和处理器架构上,目前在世界各地成千上万的集群正在使用。它已 被用来连结大学校园和世界各地,可以处理2000节点的规模。

    http://www.oschina.net/p/ganglia

     

    mina

  • JAVA 正则表达式 (超详细)

    2010-12-20 16:26:41

     

    JAVA正则表达式超详细.rar(327 KB)
    再次标记一下,java 正则表达式里,点 . 是通配符, * 只是用来表示数量的

    转自:

    http://blog.csdn.net/allwefantasy/archive/2008/10/25/3136570.aspx

    缺少图片,可以看原文,或者下载附件。

    < src="http://blog.csdn.net/js/LoadFeedbackCount.js" type=text/javascript>
    ____---------------------------________________
    (PS:这篇文章为转载,我不喜欢转载的但我觉得这篇文章实在是超赞了,就转了过来,这篇可以说是学习JAVA正则表达的必读篇。作者是个正真有功力的人,阅读愉快)
    <>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}
      在Sun的Java JDK 1.40版本中,Java自带了支持正则表达式的包,本文就抛砖引玉地介绍了如何使用java.util.regex包。

      可粗略估计一下,除了偶尔用Linux的外,其他Linu x用户都会遇到正则表达式。正则表达式是个极端强大工具,而且在字符串模式-匹配和字符串模式-替换方面富有弹性。在Unix世界里,正则表达式几乎没有什么限制,可肯定的是,它应用非常之广泛。

      正则表达式的引擎已被许多普通的Unix工具所实现,包括grep,awk,vi和Emacs等。此外,许多使用比较广泛的脚本语言也支持正则表达式,比如Python,Tcl,JavaScript,以及最著名的Perl。

      我很早以前就是个Perl方面的黑客,如果你和我一样话,你也会非常依赖你手边的这些强大的text-munging工具。近几年来,像其他程序开发者一样,我也越来越关注Java的开发。

      Java作为一种开发语言,有许多值得推荐的地方,但是它一直以来没有自带对正则表达式的支持。直到最近,借助于第三方的类库,Java开始支持正则表达式,但这些第三方的类库都不一致、兼容性差,而且维护代码起来很糟糕。这个缺点,对我选择Java作为首要的开发工具来说,一直是个巨大的顾虑之处。

      你可以想象,当我知道Sun的Java JDK 1.40版本包含了java.util.regex(一个完全开放、自带的正则表达式包)时,是多么的高兴!很搞笑的说,我花好些时间去挖掘这个被隐藏起来的宝石。我非常惊奇的是,Java这样的一个很大改进(自带了java.util.regex包)为什么不多公开一点呢?!

      最近,Java双脚都跳进了正则表达式的世界。java.util.regex包在支持正则表达也有它的过人之处,另外Java也提供详细的相关说明文档。使得朦朦胧胧的regex神秘景象也慢慢被拨开。有一些正则表达式的构成(可能最显著的是,在于糅合了字符类库)在Perl都找不到。

      在regex包中,包括了两个类,Pattern(模式类)和Matcher(匹配器类)。Pattern类是用来表达和陈述所要搜索模式的对象,Matcher类是真正影响搜索的对象。另加一个新的例外类,PatternSyntaxException,当遇到不合法的搜索模式时,会抛出例外。

      即使对正则表达式很熟悉,你会发现,通过java使用正则表达式也相当简单。要说明的一点是,对那些被Perl的单行匹配所宠坏的Perl狂热爱好者来说,在使用java的regex包进行替换操作时,会比他们所以前常用的方法费事些。

      本文的局限之处,它不是一篇正则表达式用法的完全教程。如果读者要对正则表达进一步了解的话,推荐阅读Jeffrey Frieldl的Mastering Regular Expressions,该书由O’Reilly出版社出版。我下面就举一些例子来教读者如何使用正则表达式,以及如何更简单地去使用它。

      设计一个简单的表达式来匹配任何电话号码数字可能是比较复杂的事情,原因在于电话号码格式有很多种情况。所有必须选择一个比较有效的模式。比如:(212) 555-1212, 212-555-1212和212 555 1212,某些人会认为它们都是等价的。

      首先让我们构成一个正则表达式。为简单起见,先构成一个正则表达式来识别下面格式的电话号码数字:(nnn)nnn-nnnn。

      第一步,创建一个pattern对象来匹配上面的子字符串。一旦程序运行后,如果需要的话,可以让这个对象一般化。匹配上面格式的正则表达可以这样构成:(\d{3})\s\d{3}-\d{4},其中\d单字符类型用来匹配从0到9的任何数字,另外{3}重复符号,是个简便的记号,用来表示有 3个连续的数字位,也等效于(\d\d\d)。\s也另外一个比较有用的单字符类型,用来匹配空格,比如Space键,tab键和换行符。

      是不是很简单?但是,如果把这个正则表达式的模式用在java程序中,还要做两件事。对java的解释器来说,在反斜线字符(\)前的字符有特殊的含义。在java中,与regex有关的包,并不都能理解和识别反斜线字符(\),尽管可以试试看。但为避免这一点,即为了让反斜线字符(\)在模式对象中被完全地传递,应该用双反斜线字符(\)。此外圆括号在正则表达中两层含义,如果想让它解释为字面上意思(即圆括号),也需要在它前面用双反斜线字符(\)。也就是像下面的一样:

      \\(\\d{3}\\)\\s\\d{3}-\\d{4}

      现在介绍怎样在java代码中实现刚才所讲的正则表达式。要记住的事,在用正则表达式的包时,在你所定义的类前需要包含该包,也就是这样的一行:

      import java.util.regex.*;

      下面的一段代码实现的功能是,从一个文本文件逐行读入,并逐行搜索电话号码数字,一旦找到所匹配的,然后输出在控制台。

      BufferedReader in;

      Pattern pattern = Pattern.compile("\\(\\d{3}\\)\\s\\d{3}-\\d{4}");

      in = new BufferedReader(new FileReader("phone"));

      String s;

      while ((s = in.readLine()) != null)

      {

      Matcher matcher = pattern.matcher(s);

      if (matcher.find())

      {

      System.out.println(matcher.group());

      }

      }

      in.close();

      对那些熟悉用Python或Javascript来实现正则表达式的人来说,这段代码很平常。在Python和Javascript这些语言中,或者其他的语言,这些正则表达式一旦明确地编译过后,你想用到哪里都可以。与Perl的单步匹配相比,看起来多多做了些工作,但这并不很费事。

      find()方法,就像你所想象的,用来搜索与正则表达式相匹配的任何目标字符串,group()方法,用来返回包含了所匹配文本的字符串。应注意的是,上面的代码,仅用在每行只能含有一个匹配的电话号码数字字符串时。可以肯定的说,java的正则表达式包能用在一行含有多个匹配目标时的搜索。本文的原意在于举一些简单的例子来激起读者进一步去学习java自带的正则表达式包,所以对此就没有进行深入的探讨。

      这相当漂亮吧! 但是很遗憾的是,这仅是个电话号码匹配器。很明显,还有两点可以改进。如果在电话号码的开头,即区位号和本地号码之间可能会有空格。我们也可匹配这些情况,则通过在正则表达式中加入\s?来实现,其中?元字符表示在模式可能有0或1个空格符。

      第二点是,在本地号码位的前三位和后四位数字间有可能是空格符,而不是连字号,更有胜者,或根本就没有分隔符,就是7位数字连在一起。对这几种情况,我们可以用(-|)?来解决。这个结构的正则表达式就是转换器,它能匹配上面所说的几种情况。在()能含有管道符|时,它能匹配是否含有空格符或连字符,而尾部的?元字符表示是否根本没有分隔符的情况。

      最后,区位号也可能没有包含在圆括号内,对此可以简单地在圆括号后附上?元字符,但这不是一个很好的解决方法。因为它也包含了不配对的圆括号,比如"(555" 或 "555)"。相反,我们可以通过另一种转换器来强迫让电话号码是否带有有圆括号:(\(\d{3}\)|\d{3})。如果我们把上面代码中的正则表达式用这些改进后的来替换的话,上面的代码就成了一个非常有用的电话号码数字匹配器:

      Pattern pattern =

      Pattern.compile("(\\(\\d{3}\\)|\\d{3})\\s?\\d{3}(-|)?\\d{4}");

      可以确定的是,你可以自己试着进一步改进上面的代码。

      现在看看第二个例子,它是从Friedl的中改编过来的。其功能是用来检查文本文件中是否有重复的单词,这在印刷排版中会经常遇到,同样也是个语法检查器的问题。

      匹配单词,像其他的一样,也可以通过好几种的正则表达式来完成。可能最直接的是\b\w+\b,其优点在于只需用少量的regex元字符。其中 \w元字符用来匹配从字母a到u的任何字符。+元字符表示匹配匹配一次或多次字符,\b元字符是用来说明匹配单词的边界,它可以是空格或任何一种不同的标点符号(包括逗号,句号等)。

      现在,我们怎样来检查一个给定的单词是否被重复了三次?为完成这个任务,需充分利用正则表达式中的所熟知的向后扫描。如前面提到的,圆括号在正则表达式中有几种不同的用法,一个就是能提供组合类型,组合类型用来保存所匹配的结果或部分匹配的结果(以便后面能用到),即使遇到有相同的模式。在同样的正则表达中,可能(也通常期望)不止有一个组合类型。在第n个组合类型中匹配结果可以通过向后扫描来获取到。向后扫描使得搜索重复的单词非常简单:\b(\w+)\s+\1\b。

      圆括号形成了一个组合类型,在这个正则表示中它是第一组合类型(也是仅有的一个)。向后扫描\1,指的是任何被\w+所匹配的单词。我们的正则表达式因此能匹配这样的单词,它有一个或多个空格符,后面还跟有一个与此相同的单词。注意的是,尾部的定位类型(\b)必不可少,它可以防止发生错误。如果我们想匹配"Paris in the the spring",而不是匹配"Java's regex package is the theme of this article"。根据java现在的格式,则上面的正则表达式就是:Pattern pattern =Pattern.compile("\\b(\\w+)\\s+\\1\\b");

      最后进一步的修改是让我们的匹配器对大小写敏感。比如,下面的情况:"The the theme of this article is the Java's regex package.",这一点在regex中能非常简单地实现,即通过使用在Pattern类中预定义的静态标志CASE_INSENSITIVE :

      Pattern pattern =Pattern.compile("\\b(\\w+)\\s+\\1\\b",

      Pattern.CASE_INSENSITIVE);

      有关正则表达式的话题是非常丰富,而且复杂的,用Java来实现也非常广泛,则需要对regex包进行的彻底研究,我们在这里所讲的只是冰山一角。即使你对正则表达式比较陌生,使用regex包后会很快发现它强大功能和可伸缩性。如果你是个来自Perl或其他语言王国的老练的正则表达式的黑客,使用过regex包后,你将会安心地投入到java的世界,而放弃其他的工具,并把java的regex包看成是手边必备的利器。

     

    CharSequence
    JDK 1.4定义了一个新的接口,叫CharSequence。它提供了String和StringBuffer这两个类的字符序列的抽象:

    interface CharSequence {  charAt(int i);  length();  subSequence(int start, int end);  toString();}为了实现这个新的CharSequence接口,String,StringBuffer以及CharBuffer都作了修改。很多正则表达式的操作都要拿CharSequence作参数。

    Pattern和Matcher
    先给一个例子。下面这段程序可以测试正则表达式是否匹配字符串。第一个参数是要匹配的字符串,后面是正则表达式。正则表达式可以有多个。在Unix/Linux环境下,命令行下的正则表达式还必须用引号。

    //: c12:TestRegularExpression.java// Allows you to easly try out regular expressions.// {Args: abcabcabcdefabc "abc+" "(abc)+" "(abc){2,}" }import java.util.regex.*;publicclass TestRegularExpression {publicstaticvoid main(String[] args) {if(args.length < 2) {      System.out.println("Usage:\n" +"java TestRegularExpression " +"characterSequence regularExpression+");      System.exit(0);    }    System.out.println("Input: \"" + args[0] + "\"");for(int i = 1; i < args.length; i++) {      System.out.println("Regular expression: \"" + args[i] + "\"");      Pattern p = Pattern.compile(args[i]);      Matcher m = p.matcher(args[0]);while(m.find()) {        System.out.println("Match \"" + m.group() +"\" at positions " +          m.start() + "-" + (m.end() - 1));      }    }  }} ///:~

    Java的正则表达式是由java.util.regex的Pattern和Matcher类实现的。Pattern对象表示经编译的正则表达式。静态的compile( )方法负责将表示正则表达式的字符串编译成Pattern对象。正如上述例程所示的,只要给Pattern的matcher( )方法送一个字符串就能获取一个Matcher对象。此外,Pattern还有一个能快速判断能否在input里面找到regex的

    staticboolean matches(?regex, ?input)以及能返回String数组的split( )方法,它能用regex把字符串分割开来。

    只要给Pattern.matcher( )方法传一个字符串就能获得Matcher对象了。接下来就能用Matcher的方法来查询匹配的结果了。

    boolean matches()boolean lookingAt()boolean find()boolean find(int start)matches( )的前提是Pattern匹配整个字符串,而lookingAt( )的意思是Pattern匹配字符串的开头。

    find( )
    Matcher.find( )的功能是发现CharSequence里的,与pattern相匹配的多个字符序列。例如:

    //: c12:FindDemo.javaimport java.util.regex.*;import com.bruceeckel.simpletest.*;import java.util.*;publicclass FindDemo {privatestatic Test monitor = new Test();publicstaticvoid main(String[] args) {    Matcher m = Pattern.compile("\\w+")      .matcher("Evening is full of the linnet's wings");while(m.find())      System.out.println(m.group());int i = 0;while(m.find(i)) {      System.out.print(m.group() + " ");      i++;    }    monitor.expect(new String[] {"Evening","is","full","of","the","linnet","s","wings","Evening vening ening ning ing ng g is is s full " +"full ull ll l of of f the the he e linnet linnet " +"innet nnet net et t s s wings wings ings ngs gs s "    });  }} ///:~

    "\\w+"的意思是"一个或多个单词字符",因此它会将字符串直接分解成单词。find( )像一个迭代器,从头到尾扫描一遍字符串。第二个find( )是带int参数的,正如你所看到的,它会告诉方法从哪里开始找——即从参数位置开始查找。

    Groups
    Group是指里用括号括起来的,能被后面的表达式调用的正则表达式。Group 0 表示整个表达式,group 1表示第一个被括起来的group,以此类推。所以;

    A(B(C))D里面有三个group:group 0是ABCD, group 1是BC,group 2是C。

    你可以用下述Matcher方法来使用group:

    public int groupCount( )返回matcher对象中的group的数目。不包括group0。

    public String group( ) 返回上次匹配操作(比方说find( ))的group 0(整个匹配)

    public String group(int i)返回上次匹配操作的某个group。如果匹配成功,但是没能找到group,则返回null。

    public int start(int group)返回上次匹配所找到的,group的开始位置。

    public int end(int group)返回上次匹配所找到的,group的结束位置,最后一个字符的下标加一。

    //: c12:Groups.javaimport java.util.regex.*;import com.bruceeckel.simpletest.*;publicclass Groups {privatestatic Test monitor = new Test();staticpublicfinal String poem ="Twas brillig, and the slithy toves\n" +"Did gyre and gimble in the wabe.\n" +"All mimsy were the borogoves,\n" +"And the mome raths outgrabe.\n\n" +"Beware the Jabberwock, my son,\n" +"The jaws that bite, the claws that catch.\n" +"Beware the Jubjub bird, and shun\n" +"The frumious Bandersnatch.";publicstaticvoid main(String[] args) {    Matcher m =      Pattern.compile("(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))___FCKpd___6quot;)        .matcher(poem);while(m.find()) {for(int j = 0; j <= m.groupCount(); j++)        System.out.print("[" + m.group(j) + "]");      System.out.println();    }    monitor.expect(new String[]{"[the slithy toves]" +"[the][slithy toves][slithy][toves]","[in the wabe.][in][the wabe.][the][wabe.]","[were the borogoves,]" +"[were][the borogoves,][the][borogoves,]","[mome raths outgrabe.]" +"[mome][raths outgrabe.][raths][outgrabe.]","[Jabberwock, my son,]" +"[Jabberwock,][my son,][my][son,]","[claws that catch.]" +"[claws][that catch.][that][catch.]","[bird, and shun][bird,][and shun][and][shun]","[The frumious Bandersnatch.][The]" +"[frumious Bandersnatch.][frumious][Bandersnatch.]"    });  }} ///:~

    这首诗是Through the Looking Glass的,Lewis Carroll的"Jabberwocky"的第一部分。可以看到这个正则表达式里有很多用括号括起来的group,它是由任意多个连续的非空字符 ('\S+')和任意多个连续的空格字符('\s+')所组成的,其最终目的是要捕获每行的最后三个单词;'$'表示一行的结尾。但是'$'通常表示整个字符串的结尾,所以这里要明确地告诉正则表达式注意换行符。这一点是由'(?m)'标志完成的(模式标志会过一会讲解)。

    start( )和end( )
    如果匹配成功,start( )会返回此次匹配的开始位置,end( )会返回此次匹配的结束位置,即最后一个字符的下标加一。如果之前的匹配不成功(或者没匹配),那么无论是调用start( )还是end( ),都会引发一个IllegalStateException。下面这段程序还演示了matches( )和lookingAt( ):

    //: c12:StartEnd.javaimport java.util.regex.*;import com.bruceeckel.simpletest.*;publicclass StartEnd {privatestatic Test monitor = new Test();publicstaticvoid main(String[] args) {    String[] input = new String[] {"Java has regular expressions in 1.4","regular expressions now expressing in Java","Java represses oracular expressions"    };    Pattern      p1 = Pattern.compile("re\\w*"),      p2 = Pattern.compile("Java.*");for(int i = 0; i < input.length; i++) {      System.out.println("input " + i + ": " + input[i]);      Matcher        m1 = p1.matcher(input[i]),        m2 = p2.matcher(input[i]);while(m1.find())        System.out.println("m1.find() '" + m1.group() +"' start = "+ m1.start() + " end = " + m1.end());while(m2.find())        System.out.println("m2.find() '" + m2.group() +"' start = "+ m2.start() + " end = " + m2.end());if(m1.lookingAt()) // No reset() necessary        System.out.println("m1.lookingAt() start = "          + m1.start() + " end = " + m1.end());if(m2.lookingAt())        System.out.println("m2.lookingAt() start = "          + m2.start() + " end = " + m2.end());if(m1.matches()) // No reset() necessary        System.out.println("m1.matches() start = "          + m1.start() + " end = " + m1.end());if(m2.matches())        System.out.println("m2.matches() start = "          + m2.start() + " end = " + m2.end());    }    monitor.expect(new String[] {"input 0: Java has regular expressions in 1.4","m1.find() 'regular' start = 9 end = 16","m1.find() 'ressions' start = 20 end = 28","m2.find() 'Java has regular expressions in 1.4'" +" start = 0 end = 35","m2.lookingAt() start = 0 end = 35","m2.matches() start = 0 end = 35","input 1: regular expressions now " +"expressing in Java","m1.find() 'regular' start = 0 end = 7","m1.find() 'ressions' start = 11 end = 19","m1.find() 'ressing' start = 27 end = 34","m2.find() 'Java' start = 38 end = 42","m1.lookingAt() start = 0 end = 7","input 2: Java represses oracular expressions","m1.find() 'represses' start = 5 end = 14","m1.find() 'ressions' start = 27 end = 35","m2.find() 'Java represses oracular expressions' " +"start = 0 end = 35","m2.lookingAt() start = 0 end = 35","m2.matches() start = 0 end = 35"    });  }} ///:~

    注意,只要字符串里有这个模式,find( )就能把它给找出来,但是lookingAt( )和matches( ),只有在字符串与正则表达式一开始就相匹配的情况下才能返回true。matches( )成功的前提是正则表达式与字符串完全匹配,而lookingAt( )成功的前提是,字符串的开始部分与正则表达式相匹配。

    匹配的模式(Pattern flags)
    compile( )方法还有一个版本,它需要一个控制正则表达式的匹配行为的参数:

    Pattern Pattern.compile(String regex, int flag)flag的取值范围如下: 编译标志 效果
    Pattern.CANON_EQ 当且仅当两个字符的"正规分解(canonical decomposition)"都完全相同的情况下,才认定匹配。比如用了这个标志之后,表达式"a\u030A"会匹配"?"。默认情况下,不考虑"规范相等性(canonical equivalence)"。
    Pattern.CASE_INSENSITIVE
    (?i) 默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。这个标志能让表达式忽略大小写进行匹配。要想对Unicode字符进行大小不明感的匹配,只要将UNICODE_CASE与这个标志合起来就行了。
    Pattern.COMMENTS
    (?x) 在这种模式下,匹配时会忽略(正则表达式里的)空格字符(注:不是指表达式里的"\\s",而是指表达式里的空格,tab,回车之类)。注释从#开始,一直到这行结束。可以通过嵌入式的标志来启用Unix行模式。
    Pattern.DOTALL
    (?s) 在这种模式下,表达式'.'可以匹配任意字符,包括表示一行的结束符。默认情况下,表达式'.'不匹配行的结束符。
    Pattern.MULTILINE
    (?m) 在这种模式下,'^'和'$'分别匹配一行的开始和结束。此外,'^'仍然匹配字符串的开始,'$'也匹配字符串的结束。默认情况下,这两个表达式仅仅匹配字符串的开始和结束。
    Pattern.UNICODE_CASE
    (?u) 在这个模式下,如果你还启用了CASE_INSENSITIVE标志,那么它会对Unicode字符进行大小写不明感的匹配。默认情况下,大小写不明感的匹配只适用于US-ASCII字符集。
    Pattern.UNIX_LINES
    (?d) 在这个模式下,只有'\n'才被认作一行的中止,并且与'.','^',以及'$'进行匹配。

    在这些标志里面,Pattern.CASE_INSENSITIVE,Pattern.MULTILINE,以及Pattern.COMMENTS 是最有用的(其中Pattern.COMMENTS还能帮我们把思路理清楚,并且/或者做文档)。注意,你可以用在表达式里插记号的方式来启用绝大多数的模式。这些记号就在上面那张表的各个标志的下面。你希望模式从哪里开始启动,就在哪里插记号。

    可以用"OR" ('|')运算符把这些标志合使用:

    //: c12:ReFlags.javaimport java.util.regex.*;import com.bruceeckel.simpletest.*;publicclass ReFlags {privatestatic Test monitor = new Test();publicstaticvoid main(String[] args) {    Pattern p =  Pattern.compile("^java",      Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);    Matcher m = p.matcher("java has regex\nJava has regex\n" +"JAVA has pretty good regular expressions\n" +"Regular expressions are in Java");while(m.find())      System.out.println(m.group());    monitor.expect(new String[] {"java","Java","JAVA"    });  }} ///:~

    这样创建出来的正则表达式就能匹配以"java","Java","JAVA"...开头的字符串了。此外,如果字符串分好几行,那它还会对每一行做匹配(匹配始于字符序列的开始,终于字符序列当中的行结束符)。注意,group( )方法仅返回匹配的部分。

    split( )
    所谓分割是指将以正则表达式为界,将字符串分割成String数组。

    String[] split(CharSequence charseq)String[] split(CharSequence charseq, int limit)这是一种既快又方便地将文本根据一些常见的边界标志分割开来的方法。

    //: c12:SplitDemo.javaimport java.util.regex.*;import com.bruceeckel.simpletest.*;import java.util.*;publicclass SplitDemo {privatestatic Test monitor = new Test();publicstaticvoid main(String[] args) {    String input ="This!!unusual use!!of exclamation!!points";    System.out.println(Arrays.asList(      Pattern.compile("!!").split(input)));// Only do the first three:    System.out.println(Arrays.asList(      Pattern.compile("!!").split(input, 3)));    System.out.println(Arrays.asList("Aha! String has a split() built in!".split(" ")));    monitor.expect(new String[] {"[This, unusual use, of exclamation, points]","[This, unusual use, of exclamation!!points]","[Aha!, String, has, a, split(), built, in!]"    });  }} ///:~

    第二个split( )会限定分割的次数。

    正则表达式是如此重要,以至于有些功能被加进了String类,其中包括split( )(已经看到了),matches( ),replaceFirst( )以及replaceAll( )。这些方法的功能同Pattern和Matcher的相同。

    替换操作
    正则表达式在替换文本方面特别在行。下面就是一些方法:

    replaceFirst(String replacement)将字符串里,第一个与模式相匹配的子串替换成replacement。

    replaceAll(String replacement),将输入字符串里所有与模式相匹配的子串全部替换成replacement。

    appendReplacement(StringBuffer sbuf, String replacement)对sbuf进行逐次替换,而不是像replaceFirst( )或replaceAll( )那样,只替换第一个或全部子串。这是个非常重要的方法,因为它可以调用方法来生成replacement(replaceFirst( )和replaceAll( )只允许用固定的字符串来充当replacement)。有了这个方法,你就可以编程区分group,从而实现更强大的替换功能。

    调用完appendReplacement( )之后,为了把剩余的字符串拷贝回去,必须调用appendTail(StringBuffer sbuf, String replacement)。

    下面我们来演示一下怎样使用这些替换方法。说明一下,这段程序所处理的字符串是它自己开头部分的注释,是用正则表达式提取出来并加以处理之后再传给替换方法的。

    //: c12:TheReplacements.javaimport java.util.regex.*;import java.io.*;import com.bruceeckel.util.*;import com.bruceeckel.simpletest.*;/*! Here's a block of text to use as input to    the regular expression matcher. Note that we'll    first extract the block of text by looking for    the special delimiters, then process the    extracted block. !*/publicclass TheReplacements {privatestatic Test monitor = new Test();publicstaticvoid main(String[] args) throws Exception {    String s = TextFile.read("TheReplacements.java");// Match the specially-commented block of text above:    Matcher mInput =      Pattern.compile("/\\*!(.*)!\\*/", Pattern.DOTALL)        .matcher(s);if(mInput.find())      s = mInput.group(1); // Captured by parentheses// Replace two or more spaces with a single space:    s = s.replaceAll(" {2,}", " ");// Replace one or more spaces at the beginning of each// line with no spaces. Must enable MULTILINE mode:    s = s.replaceAll("(?m)^ +", "");    System.out.println(s);    s = s.replaceFirst("[aeiou]", "(VOWEL1)");    StringBuffer sbuf = new StringBuffer();    Pattern p = Pattern.compile("[aeiou]");    Matcher m = p.matcher(s);// Process the find information as you// perform. the replacements:while(m.find())      m.appendReplacement(sbuf, m.group().toUpperCase());// Put in the remainder of the text:    m.appendTail(sbuf);    System.out.println(sbuf);    monitor.expect(new String[]{"Here's a block of text to use as input to","the regular expression matcher. Note that we'll","first extract the block of text by looking for","the special delimiters, then process the","extracted block. ","H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO","thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE'll","fIrst ExtrAct thE blOck Of tExt by lOOkIng fOr","thE spEcIAl dElImItErs, thEn prOcEss thE","ExtrActEd blOck. "    });  }} ///:~

    用TextFile.read( )方法来打开和读取文件。mInput的功能是匹配'/*!' 和 '!*/' 之间的文本(注意一下分组用的括号)。接下来,我们将所有两个以上的连续空格全都替换成一个,并且将各行开头的空格全都去掉(为了让这个正则表达式能对所有的行,而不仅仅是第一行起作用,必须启用多行模式)。这两个操作都用了String的replaceAll( )(这里用它更方便)。注意,由于每个替换只做一次,因此除了预编译Pattern之外,程序没有额外的开销。

    replaceFirst( )只替换第一个子串。此外,replaceFirst( )和replaceAll( )只能用常量(literal)来替换,所以如果每次替换的时候还要进行一些操作的话,它们是无能为力的。碰到这种情况,得用 appendReplacement( ),它能在进行替换的时候想写多少代码就写多少。在上面那段程序里,创建sbuf的过程就是选group做处理,也就是用正则表达式把元音字母找出来,然后换成大写的过程。通常你得在完成全部的替换之后才调用appendTail( ),但是如果要模仿replaceFirst( )(或"replace n")的效果,你也可以只替换一次就调用appendTail( )。它会把剩下的东西全都放进sbuf。

    你还可以在appendReplacement( )的replacement参数里用"$g"引用已捕获的group,其中'g' 表示group的号码。不过这是为一些比较简单的操作准备的,因而其效果无法与上述程序相比。

    reset( )
    此外,还可以用reset( )方法给现有的Matcher对象配上个新的CharSequence。

    //: c12:Resetting.javaimport java.util.regex.*;import java.io.*;import com.bruceeckel.simpletest.*;publicclass Resetting {privatestatic Test monitor = new Test();publicstaticvoid main(String[] args) throws Exception {    Matcher m = Pattern.compile("[frb][aiu][gx]")      .matcher("fix the rug with bags");while(m.find())      System.out.println(m.group());    m.reset("fix the rig with rags");while(m.find())      System.out.println(m.group());    monitor.expect(new String[]{"fix","rug","bag","fix","rig","rag"    });  }} ///:~

    如果不给参数,reset( )会把Matcher设到当前字符串的开始处。
     


      如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语,那么“正则表达式”(Regular Expression)就是一个字符构成的串,它定义了一个用来搜索匹配字符串的模式。
    许多语言,包括Perl、 PHP、Python、JavaScript和JScript,都支持用正则表达式处理文本,一些文本编辑器用正则表达式实现高级“搜索-替换”功能。那么Java又怎样呢?本文写作时,一个包含了用正则表达式进行文本处理的Java规范需求(Specification Request)已经得到认可,你可以期待在JDK的下一版本中看到它。
    然而,如果现在就需要使用正则表达式,又该怎么办呢?你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识,然后以Jakarta-ORO API为例介绍如何使用正则表达式。
    一、正则表达式基础知识
    我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说:
     
    1.1 句点符号
    假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、“ten”、 “tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符:
     
    1.2 方括号符号
    为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符:
     
    1.3 “或”符号
    如果除了上面匹配的所有单词之外,你还想要匹配“toon”,那么,你可以使用“|”操作符。“|” 操作符的基本意义就是“或”运算。要匹配“toon”,使用“t(a|e|i|o|oo)n”正则表达式。这里不能使用方扩号,因为方括号只允许匹配单个字符;这里必须使用圆括号“()”。圆括号还可以用来分组,具体请参见后面介绍。
     
    1.4 表示匹配次数的符号
    表一显示了表示匹配次数的符号,这些符号用来确定紧靠该符号左边的符号出现的次数:

     
    假设我们要在文本文件中搜索美国的社会安全号码。这个号码的格式是999-99-9999。用来匹配它的正则表达式如图一所示。在正则表达式中,连字符(“-”)有着特殊的意义,它表示一个范围,比如从0到9。因此,匹配社会安全号码中的连字符号时,它的前面要加上一个转义字符“\”。
     
     
    图一:匹配所有123-12-1234形式的社会安全号码
     
    假设进行搜索的时候,你希望连字符号可以出现,也可以不出现——即,999-99-9999和999999999都属于正确的格式。这时,你可以在连字符号后面加上“?”数量限定符号,如图二所示:
     
     
    图二:匹配所有123-12-1234和123121234形式的社会安全号码
     
    下面我们再来看另外一个例子。美国汽车牌照的一种格式是四个数字加上二个字母。它的正则表达式前面是数字部分“[0-9]{4}”,再加上字母部分“[A-Z]{2}”。图三显示了完整的正则表达式。
     
     
    图三:匹配典型的美国汽车牌照号码,如8836KV
     
    1.5 “否”符号
    “^”符号称为“否”符号。如果用在方括号内,“^”表示不想要匹配的字符。例如,图四的正则表达式匹配所有单词,但以“X”字母开头的单词除外。
     
     
    图四:匹配所有单词,但“X”开头的除外
     
    1.6 圆括号和空白符号
    假设要从格式为“June 26, 1951”的生日日期中提取出月份部分,用来匹配该日期的正则表达式可以如图五所示:
     
     
    图五:匹配所有Moth DD,YYYY格式的日期
     
    新出现的“\s”符号是空白符号,匹配所有的空白字符,包括Tab字符。如果字符串正确匹配,接下来如何提取出月份部分呢?只需在月份周围加上一个圆括号创建一个组,然后用ORO API(本文后面详细讨论)提取出它的值。修改后的正则表达式如图六所示:
     
     
    图六:匹配所有Month DD,YYYY格式的日期,定义月份值为第一个组
     
    1.7 其它符号
    为简便起见,你可以使用一些为常见正则表达式创建的快捷符号。如表二所示:
    表二:常用符号
     
     
    例如,在前面社会安全号码的例子中,所有出现“[0-9]”的地方我们都可以使用“\d”。修改后的正则表达式如图七所示:
     
     
    图七:匹配所有123-12-1234格式的社会安全号码
     
    二、Jakarta-ORO库
    有许多源代码开放的正则表达式库可供Java程序员使用,而且它们中的许多支持Perl 5兼容的正则表达式语法。我在这里选用的是Jakarta-ORO正则表达式库,它是最全面的正则表达式API之一,而且它与Perl 5正则表达式完全兼容。另外,它也是优化得最好的API之一。
    Jakarta-ORO库以前叫做OROMatcher,Daniel Savarese大方地把它赠送给了Jakarta Project。你可以按照本文最后参考资源的说明下载它。
    我首先将简要介绍使用Jakarta-ORO库时你必须创建和访问的对象,然后介绍如何使用Jakarta-ORO API。
    ▲ PatternCompiler对象
    首先,创建一个Perl5Compiler类的实例,并把它赋值给PatternCompiler接口对象。Perl5Compiler是PatternCompiler接口的一个实现,允许你把正则表达式编译成用来匹配的Pattern对象。
     
    ▲ Pattern对象
    要把正则表达式编译成Pattern对象,调用compiler对象的compile()方法,并在调用参数中指定正则表达式。例如,你可以按照下面这种方式编译正则表达式“t[aeio]n”:
     
    默认情况下,编译器创建一个大小写敏感的模式(pattern)。因此,上面代码编译得到的模式只匹配“tin”、“tan”、 “ten”和“ton”,但不匹配“Tin”和“taN”。要创建一个大小写不敏感的模式,你应该在调用编译器的时候指定一个额外的参数:
     
    创建好Pattern对象之后,你就可以通过PatternMatcher类用该Pattern对象进行模式匹配。
    ▲ PatternMatcher对象
    PatternMatcher 对象根据Pattern对象和字符串进行匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给PatternMatcher接口。 Perl5Matcher类是PatternMatcher接口的一个实现,它根据Perl 5正则表达式语法进行模式匹配:
     
    使用PatternMatcher对象,你可以用多个方法进行匹配操作,这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串:
    · boolean matches(String input, Pattern pattern):当输入字符串和正则表达式要精确匹配时使用。换句话说,正则表达式必须完整地描述输入字符串。
    · boolean matchesPrefix(String input, Pattern pattern):当正则表达式匹配输入字符串起始部分时使用。
    · boolean contains(String input, Pattern pattern):当正则表达式要匹配输入字符串的一部分时使用(即,它必须是一个子串)。
    另外,在上面三个方法调用中,你还可以用PatternMatcherInput对象作为参数替代String对象;这时,你可以从字符串中最后一次匹配的位置开始继续进行匹配。当字符串可能有多个子串匹配给定的正则表达式时,用PatternMatcherInput对象作为参数就很有用了。用 PatternMatcherInput对象作为参数替代String时,上述三个方法的语法如下:
    · boolean matches(PatternMatcherInput input, Pattern pattern)
    · boolean matchesPrefix(PatternMatcherInput input, Pattern pattern)
    · boolean contains(PatternMatcherInput input, Pattern pattern)
    三、应用实例
    下面我们来看看Jakarta-ORO库的一些应用实例。
    3.1 日志文件处理
    任务:分析一个Web服务器日志文件,确定每一个用户花在网站上的时间。在典型的BEA WebLogic日志文件中,日志记录的格式如下:
     
    分析这个日志记录,可以发现,要从这个日志文件提取的内容有两项:IP地址和页面访问时间。你可以用分组符号(圆括号)从日志记录提取出IP地址和时间标记。
    首先我们来看看IP地址。IP地址有4个字节构成,每一个字节的值在0到255之间,各个字节通过一个句点分隔。因此,IP地址中的每一个字节有至少一个、最多三个数字。图八显示了为IP地址编写的正则表达式:
     
     
    图八:匹配IP地址
     
    IP地址中的句点字符必须进行转义处理(前面加上“\”),因为IP地址中的句点具有它本来的含义,而不是采用正则表达式语法中的特殊含义。句点在正则表达式中的特殊含义本文前面已经介绍。
    日志记录的时间部分由一对方括号包围。你可以按照如下思路提取出方括号里面的所有内容:首先搜索起始方括号字符(“[”),提取出所有不超过结束方括号字符(“]”)的内容,向前寻找直至找到结束方括号字符。图九显示了这部分的正则表达式。
     
     
    图九:匹配至少一个字符,直至找到“]”
     
    现在,把上述两个正则表达式加上分组符号(圆括号)后合并成单个表达式,这样就可以从日志记录提取出IP地址和时间。注意,为了匹配“- -”(但不提取它),正则表达式中间加入了“\s-\s-\s”。完整的正则表达式如图十所示。
     
     
    图十:匹配IP地址和时间标记
     
    现在正则表达式已经编写完毕,接下来可以编写使用正则表达式库的Java代码了。
    为使用Jakarta-ORO库,首先创建正则表达式字符串和待分析的日志记录字符串:
     
    这里使用的正则表达式与图十的正则表达式差不多完全相同,但有一点例外:在Java中,你必须对每一个向前的斜杠(“\”)进行转义处理。图十不是Java 的表示形式,所以我们要在每个“\”前面加上一个“\”以免出现编译错误。遗憾的是,转义处理过程很容易出现错误,所以应该小心谨慎。你可以首先输入未经转义处理的正则表达式,然后从左到右依次把每一个“\”替换成“\\”。如果要复检,你可以试着把它输出到屏幕上。
    初始化字符串之后,实例化PatternCompiler对象,用PatternCompiler编译正则表达式创建一个Pattern对象:
     
    现在,创建PatternMatcher对象,调用PatternMatcher接口的contain()方法检查匹配情况:
     
    接下来,利用PatternMatcher接口返回的MatchResult对象,输出匹配的组。由于logEntry字符串包含匹配的内容,你可以看到类如下面的输出:
     
    3.2 HTML处理实例一
    下面一个任务是分析HTML页面内FONT标记的所有属性。HTML页面内典型的FONT标记如下所示:
     
    程序将按照如下形式,输出每一个FONT标记的属性:
     
    在这种情况下,我建议你使用两个正则表达式。第一个如图十一所示,它从字体标记提取出“"face="Arial, Serif" size="+2" color="red"”。
     
     
    图十一:匹配FONT标记的所有属性
     
    第二个正则表达式如图十二所示,它把各个属性分割成名字-值对。
     
     
    图十二:匹配单个属性,并把它分割成名字-值对
     
    分割结果为:
     
    现在我们来看看完成这个任务的Java代码。首先创建两个正则表达式字符串,用Perl5Compiler把它们编译成Pattern对象。编译正则表达式的时候,指定Perl5Compiler.CASE_INSENSITIVE_MASK选项,使得匹配操作不区分大小写。
    接下来,创建一个执行匹配操作的Perl5Matcher对象。
     
    假设有一个String类型的变量html,它代表了HTML文件中的一行内容。如果html字符串包含FONT标记,匹配器将返回true。此时,你可以用匹配器对象返回的MatchResult对象获得第一个组,它包含了FONT的所有属性:
     
    接下来创建一个PatternMatcherInput对象。这个对象允许你从最后一次匹配的位置开始继续进行匹配操作,因此,它很适合于提取FONT标记内属性的名字-值对。创建PatternMatcherInput对象,以参数形式传入待匹配的字符串。然后,用匹配器实例提取出每一个FONT的属性。这通过指定PatternMatcherInput对象(而不是字符串对象)为参数,反复地调用PatternMatcher对象的contains() 方法完成。PatternMatcherInput对象之中的每一次迭代将把它内部的指针向前移动,下一次检测将从前一次匹配位置的后面开始。
    本例的输出结果如下:
     
    3.3 HTML处理实例二
    下面我们来看看另一个处理HTML的例子。这一次,我们假定Web服务器从widgets.acme.com移到了newserver.acme.com。现在你要修改一些页面中的链接:
     
    执行这个搜索的正则表达式如图十三所示:
     
     
    图十三:匹配修改前的链接
     
    如果能够匹配这个正则表达式,你可以用下面的内容替换图十三的链接:
     
    注意#字符的后面加上了$1。Perl正则表达式语法用$1、$2等表示已经匹配且提取出来的组。图十三的表达式把所有作为一个组匹配和提取出来的内容附加到链接的后面。
    现在,返回Java。就象前面我们所做的那样,你必须创建测试字符串,创建把正则表达式编译到Pattern对象所必需的对象,以及创建一个PatternMatcher对象:
    接下来,用com.oroinc.text.regex包Util类的substitute()静态方法进行替换,输出结果字符串:
     
    Util.substitute()方法的语法如下:
     
    这个调用的前两个参数是以前创建的PatternMatcher和Pattern对象。第三个参数是一个Substiution对象,它决定了替换操作如何进行。本例使用的是Perl5Substitution对象,它能够进行Perl5风格的替换。第四个参数是想要进行替换操作的字符串,最后一个参数允许指定是否替换模式的所有匹配子串(Util.SUBSTITUTE_ALL),或只替换指定的次数。
    【结束语】在这篇文章中,我为你介绍了正则表达式的强大功能。只要正确运用,正则表达式能够在字符串提取和文本修改中起到很大的作用。另外,我还介绍了如何在Java程序中通过Jakarta- ORO库利用正则表达式。至于最终采用老式的字符串处理方式(使用StringTokenizer,charAt,和substring),还是采用正则表达式,这就有待你自己决定了。


    Jakarta-ORO篇

    陈广佳 (cgjmail@163.net)
    电子信息工程系工科学士
    2001 年 12 月

    由于工作的需要,本人经常要面对大量的文字电子资料的整理工作,因此曾对在JAVA中正则表达式的应用有所关注,并对其有一定的了解,希望通过本文与同行进行有关方面的心得交流。
    正则表达式:
    正则表达式是一种可以用于模式匹配和替换的强有力的工具,一个正则表达式就是由普通的字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式,它描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

    正则表达式在字符数据处理中起着非常重要的作用,我们可以用正则表达式完成大部分的数据分析处理工作,如:判断一个串是否是数字、是否是有效的 Email地址,从海量的文字资料中提取有价值的数据等等,如果不使用正则表达式,那么实现的程序可能会很长,并且容易出错。对这点本人深有体会,面对大量工具书电子档资料的整理工作,如果不懂得应用正则表达式来处理,那么将是很痛苦的一件事情,反之则将可以轻松地完成,获得事半功倍的效果。

    由于本文目的是要介绍如何在JAVA里运用正则表达式,因此对刚接触正则表达式的读者请参考有关资料,在此因篇幅有限不作介绍。

    JAVA对正则表达式的支持:
    在JDK1.3或之前的JDK版本中并没有包含正则表达式库可供JAVA程序员使用,之前我们一般都在使用第三方提供的正则表达式库,这些第三方库中有源代码开放的,也有需付费购买的,而现时在JDK1.4的测试版中也已经包含有正则表达式库 ---java.util.regex。

    故此现在我们有很多面向JAVA的正则表达式库可供选择,以下我将介绍两个较具代表性的 Jakarta-ORO和java.util.regex,首先当然是本人一直在用的 Jakarta-ORO:

    Jakarta-ORO正则表达式库

    1.简介:
    Jakarta-ORO是最全面以及优化得最好的正则表达式API之一,Jakarta-ORO库以前叫做 OROMatcher,是由Daniel F. Savarese编写,后来他将其赠与Jakarta Project,读者可在Apache.org的网站下载该API包。

    许多源代码开放的正则表达式库都是支持Perl5兼容的正则表达式语法,Jakarta-ORO正则表达式库也不例外,他与Perl 5正则表达式完全兼容。

    2.对象与其方法:
    ★PatternCompiler对象:
    我们在使用Jakarta-ORO API包时,最先要做的是,创建一个Perl5Compiler类的实例,并把它赋值给PatternCompiler接口对象。 Perl5Compiler是PatternCompiler接口的一个实现,允许你把正则表达式编译成用来匹配的Pattern对象。

    PatternCompiler compiler=new Perl5Compiler();

    ★Pattern对象:
    要把所对应的正则表达式编译成Pattern对象,需要调用compiler对象的compile()方法,并在调用参数中指定正则表达式。举个例子,你可以按照下面这种方式编译正则表达式"s[ahkl]y":

     Pattern pattern=null;
            try {
                    pattern=compiler.compile("s[ahkl]y ");
            } catch (MalformedPatternException e) {
                    e.printStackTrace();
            }
     

     


    在默认的情况下,编译器会创建一个对大小写敏感的模式(pattern)。因此,上面代码编译得到的模式只匹配"say"、"shy"、 "sky"和"sly",但不匹配"Say"和"skY"。要创建一个大小写不敏感的模式,你应该在调用编译器的时候指定一个额外的参数:
    pattern=compiler.compile("s[ahkl]y",Perl5Compiler.CASE_INSENSITIVE_MASK);

    Pattern对象创建好之后,就可以通过PatternMatcher类用该Pattern对象进行模式匹配。

    ★PatternMatcher对象:

    PatternMatcher对象依据Pattern对象和字符串展开匹配检查。你要实例化一个Perl5Matcher类并把结果赋值给 PatternMatcher接口。Perl5Matcher类是PatternMatcher接口的一个实现,它根据Perl 5正则表达式语法进行模式匹配:
    PatternMatcher matcher=new Perl5Matcher();

    PatternMatcher对象提供了多个方法进行匹配操作,这些方法的第一个参数都是需要根据正则表达式进行匹配的字符串:

    boolean matches(String input, Pattern pattern):当要求输入的字符串input和正则表达式pattern精确匹配时使用该方法。也就是说当正则表达式完整地描述输入字符串时返回真值。
    boolean matchesPrefix(String input, Pattern pattern):要求正则表达式匹配输入字符串起始部分时使用该方法。也就是说当输入字符串的起始部分与正则表达式匹配时返回真值。
    boolean contains(String input, Pattern pattern):当正则表达式要匹配输入字符串的一部分时使用该方法。当正则表达式为输入字符串的子串时返回真值。

     


    但以上三种方法只会查找输入字符串中匹配正则表达式的第一个对象,如果当字符串可能有多个子串匹配给定的正则表达式时,那么你就可以在调用上面三个方法时用PatternMatcherInput对象作为参数替代String对象,这样就可以从字符串中最后一次匹配的位置开始继续进行匹配,这样就方便的多了。

    用PatternMatcherInput对象作为参数替代String时,上述三个方法的语法如下:

    boolean matches(PatternMatcherInput input, Pattern pattern)
    boolean matchesPrefix(PatternMatcherInput input, Pattern pattern)
    boolean contains(PatternMatcherInput input, Pattern pattern)

     


    ★Util.substitute()方法:
    查找后需要要进行替换,我们就要用到Util.substitute()方法,其语法如下:

    public static String substitute(PatternMatcher matcher,
           Pattern pattern,Substitution sub,String input,
           int numSubs)

     

     

     


    前两个参数分别为PatternMatcher和Pattern对象。而第三个参数是个Substiution对象,由它来决定替换操作如何进行。第四个参数是要进行替换操作的目标字符串,最后一个参数用来指定是否替换模式的所有匹配子串(Util.SUBSTITUTE_ALL),或只进行指定次数的替换。

    在这里我相信有必要详细解说一下第三个参数Substiution对象,因为它将决定替换将怎样进行。

    Substiution:
    Substiution是一个接口类,它为你提供了在使用Util.substitute()方法时控制替换方式的手段,它有两个标准的实现类:StringSubstitution与Perl5Substitution。当然,同时你也可以生成自己的实现类来定制你所需要的特殊替换动作。

    StringSubstitution:
    StringSubstitution 实现的是简单的纯文字替换手段,它有两个构造方法:

    StringSubstitution()->缺省的构造方法,初始化一个包含零长度字符串的替换对象。

    StringSubstitution(java.lang.String substitution)->初始化一个给定字符串的替换对象。

    Perl5Substitution:
    Perl5Substitution 是StringSubstitution的子类,它在实现纯文字替换手段的同时也允许进行针对MATH类里各匹配组的PERL5变量的替换,所以他的替换手段比其直接父类StringSubstitution更为多元化。

    它有三个构造器:

    Perl5Substitution()

    Perl5Substitution(java.lang.String substitution)

    Perl5Substitution(java.lang.String substitution, int numInterpolations)

    前两种构造方法与StringSubstitution一样,而第三种构造方法下面将会介绍到。

    在Perl5Substitution的替换字符串中可以包含用来替代在正则表达式里由小扩号围起来的匹配组的变量,这些变量是由$1, $2,$3等形式来标识。我们可以用一个例子来解释怎样使用替换变量来进行替换:

    假设我们有正则表达式模式为b\d+:(也就是b[0-9]+:),而我们想把所有匹配的字符串中的"b"都改为"a",而":"则改为"-",而其余部分则不作修改,如我们输入字符串为"EXAMPLE b123:",经过替换后就应该变成"EXAMPLE a123-"。要做到这点,我们就首先要把不做替换的部分用分组符号小括号包起来,这样正则表达式就变为"b(\d+):",而构造 Perl5Substitution对象时其替换字符串就应该是"a$1-",也就是构造式为Perl5Substitution("a$1-"),表示在使用Util.substitute()方法时只要在目标字符串里找到和正则表达式" b(\d+): "相匹配的子串都用替换字符串来替换,而变量$1表示如果和正则表达式里第一个组相匹配的内容则照般原文插到$1所在的为置,如在"EXAMPLE b123:"中和正则表达式相匹配的部分是"b123:",而其中和第一分组"(\d+)"相匹配的部分则是"123",所以最后替换结果为"EXAMPLE a123-"。

    有一点需要清楚的是,如果你把构造器Perl5Substitution(java.lang.String substitution,int numInterpolations)

    中的numInterpolations参数设为INTERPOLATE_ALL,那么当每次找到一个匹配字串时,替换变量($1,$2等)所指向的内容都根据目前匹配字串来更新,但是如果numInterpolations参数设为一个正整数N时,那么在替换时就只会在前N次匹配发生时替换变量会跟随匹配对象来调整所代表的内容,但N次之后就以一致以第N次替换变量所代表内容来做为以后替换结果。

    举个例子会更好理解:

    假如沿用以上例子中的正则表达式模式以及替换内容来进行替换工作,设目标字符串为"Tank b123: 85 Tank b256: 32 Tank b78: 22",并且设numInterpolations参数为INTERPOLATE_ALL,而Util.substitute()方法中的numSub变量设为SUBSTITUTE_ALL(请参考上文Util.substitute()方法内容),那么你获得的替换结果将会是:
    Tank a123- 85 Tank a256- 32 Tank a78- 22

    但是如果你把numInterpolations设为2,并且numSubs依然设为SUBSTITUTE_ALL,那么这时你获得的结果则会是:
    Tank a123- 85 Tank a256- 32 Tank a256- 22

    你要注意到最后一个替换所用变量$1所代表的内容与第二个$1一样为"256",而不是预期的"78",因为在替换进行中,替换变量$1只根据匹配内容进行了两次更新,最后一次就使第二次匹配时所更新的结果,那么我们可以由此知道,如果numInterpolations设为1,那么结果将是:
    Tank a123- 85 Tank a123- 32 Tank a123- 22

    3.应用示例:
    刚好前段时间公司准备出一个《伊索预言》的英语学习互动教材,其中有电子档资料的整理工作,我们就以此为例来看一下 Jakarta-ORO与JDBC2.0 API结合起来对数据库内的资料进行简单提取与整理的实现。假设由录入部的同事送过来的存放在MS SQLSERVER 7数据库里的电子档的表结构如下(注:或许在不同的DBMS中有相应的正则表达式的应用,但这不在本文讨论范围内):

    表名:AESOP, 表中每条记录包含有三列:
    ID(int):单词索引号
    WORD(varchar):单词
    CONTENT(varchar):存放单词的相关解释与例句等内容

    其中CONTENT列中内容的格式如下:
    [音标] [词性] (解释){(例句一/例句解释/例句中该词的词性: 单词在句中的意思) (例句二/例句解释/例句中该词的词性: 单词在句中的意思)}

    如对应单词Kevin,CONTENT中的内容如下:
    ['kevin] [名词](人名凯文){(Kevin loves comic./凯文爱漫画/名词: 凯文)( Kevin is living in ZhuHai now./凯文现住在珠海/名词: 凯文)}

    我们的例子主要针对CONTENT列中内容进行字符串处理。

    ★查找单个匹配:
    首先,让我们尝试把CONTNET列中的[音标]字段的内容列示出来,由于所有单词的记录中都有这一项并且都在字串开始位置,所以这个查找工作比较简单:

    确定相应的正则表达式:\[[^]]+\]
    这个是很简单的正则表达式,其意思是要求相匹配的字符串必须为以一对中括号包含的所有内容,如 ['kevin] 、[名词]等,但内容中不包括"]"符号,也就是要避免出现"[][]"会作为一个匹配对象的情况出现(有关正则表达式的基础知识请参照有关资料,这里不再详述)。

    注意,在Java中,你必须对每一个向前的斜杠("\")进行转义处理。所以我们要在上面的正则表达式里每个"\"前面加上一个"\"以免出现编译错误,也就是在JAVA中初始化正则表达式的字符串的语句应该为:

    String restring=" \\[[^]]+\\]";

    并且在表达式里每个符号中间不能有空格,否则就会同样出现编译错误。

    实例化PatternCompiler对象,创建Pattern对象
    PatternCompiler compiler=new Perl5Compiler();

    Pattern pattern=compiler.compile(restring);

    创建PatternMatcher对象,调用PatternMatcher接口的contain()方法检查匹配情况:   PatternMatcher matcher=new Perl5Matcher();
            if (matcher.contains(content,pattern)) {
                     //处理代码片段
            }

     

     

    这里matcher.contains(content,pattern)中的参数 content是从数据库里取来的字符串变量。该方法只会查到第一个匹配的对象字符串,但是由于音标项均在CONETNET内容字符串中的起始位置,所以用这个方法就已经可以保证把每条记录里的音标项找出来了,但更为直接与合理的办法是使用boolean matchesPrefix(PatternMatcherInput input, Pattern pattern)方法,该方法验证目标字符串是否以正则表达式所匹配的字串为起始。

    具体实现的完整的程序代码如下:

    package RegularExpressions;
    //import……
    import org.apache.oro.text.regex.*;
    //使用Jakarta-ORO正则表达式库前需要把它加到CLASSPATH里面,如果用IDE是//JBUILDER,那么也可以在JBUILDER里直接自建新库。

    public class yisuo{
      public static void main(String[] args){
      try{   
    //使用JDBC DRIVER进行DBMS连接,这里我使用的是一个第三方JDBC
    //DRIVER,Microsoft本身也有一个面向SQLSERVER7/2000的免费JDBC //DRIVER,但其性能真的是奇差,不用也罢。
            Class.forName("com.jnetdirect.jsql.JSQLDriver");
              Connection con=DriverManager.getConnection
              ("jdbc:JSQLConnect://kevin:1433","kevin chen","re");
              Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
              ResultSet.CONCUR_UPDATABLE);
    //为使用Jakarta-ORO库而创建相应的对象
    String rsstring=" \\[[^]]+\\]";
              PatternCompiler rocom=new Perl5Compiler();
              Pattern pattern=orocom.compile(rsstring);
              PatternMatcher matcher=new Perl5Matcher();
              ResultSet uprs = stmt.executeQuery("SELECT * FROM aesop");
              while (uprs.next()) {
    Stirng  word=uprs.getString("word");
              Stirng  content=uprs.getString("content");
                if(matcher.contains(content,pattern)){
              //或if(matcher.matchesPrefix(content,pattern)){
                    MatchResult result=matcher.getMatch();
                    Stirng pure=result.toString();
                    System.out.println(word+"的音标为:"+pure);
                }
              }
           }
      catch(Exception e) {
                 System.out.println(e);
           }
      }
    }
     

     

    输出结果为:kevin的音标为['kevin]

     

    在这个处理中我是用toString()方法来取得结果,但是如果正则表达式里是用了分组符号(圆括号),那么就可以用group(int gid)的方法来取得相应各组匹配的结果,如正则表达式改为" (\[[^]]+\])",那么就可以用以下方法来取得结果:pure=result.group(0);

     

    用程序验证,输出结果同样为:kevin的音标为['kevin]

    而如果正则表达式为(\[[^]]+\])(\[[^]]+\]),则会查找到两个连续的方括号所包含的内容,也就找到[音标] [词性]两项,但是两项的结果分别在两个组里面,分别由下面语句获得结果:

    result.group(0)->返回[音标] [词性]两项内容,也就是与整个正则表达式相匹配的结果字符串,在这里也就为['kevin] [名词]

    result.group(1) ->返回[音标]项内容,结果应是['kevin]

    result.group(2) ->返回[词性]项内容,结果应是[名词]

    继续用程序验证,发现输出并不正确,主要是当内容有中文时就不能成功匹配,考虑到可能是Jakarta-ORO正则表达式库版本不支持中文的问题,回看一下原来我一直用的还是2.0.1的老版本,马上到Jakarta.org上下载最新的2.0.4版本装上再用程序验证,得出的结果就和预期一样正确。

    ★查找多个匹配:
    经过第一步的尝试使用Jakarta-ORO后,我们已经知道了如何正确使用该API包来查找目标字符串里一个匹配的子串,下面我们接着来看一看当目标字符串里包含不止一个匹配的子串时我们如何把它们一个接一个找出来进行相应的处理。

    首先我们先试个简单的应用,假设我们想把CONTNET字段内容里所有用方括号包起来的字串都找出来,很清楚地,CONTNET字段的内容里面就只有两项匹配的内容:[音标]和 [词性],刚才我们其实已经把它们分别找出来了,但是我们所用的方法是分组方法,把"[音标] [词性]"作为一整个正则表达式匹配的内容先找到,再根据分组把[音标]和 [词性]分别挑出来。但是现在我们需要做的是把[音标]和[词性]分别做为与同一个正则表达式匹配的内容,先找到一个接着再找下一个,也就是刚才我们的表达式为(\[[^]]+\])(\[[^]]+\]),而现在应为" \[[^]]+\] "。

    我们已经知道在匹配操作的三个方法里只要用PatternMatcherInput对象作为参数替代String对象就可以从字符串中最后一次匹配的位置开始继续进行匹配,实现的程序片段如下:

    PatternMatcherInput input=new PatternMatcherInput(content);
                while (matcher.contains(input,pattern)) {
                    result=matcher.getMatch();
                    System.out.println(result.group(0))
                }

     
    输出结果为:['kevin]
    [名词]

     

    接着我们来做复杂一点的处理,就是我们要先把下面内容:
    ['kevin] [名词](人名凯文){(Kevin loves comic./凯文爱漫画/名词: 凯文)( Kevin is living in ZhuHai now. /凯文现住在珠海/名词: 凯文)}中的整个例句部分(也就是由大括号所包含的部分)找出来,再分别把例句一和例句二找出,而各例句中的各项内容(英文句、中文句、词性、解释)也要分项列出。

    第一步当然是要定出相应的正则表达式,需要有两个,一是和整个例句部分(也就是由大括号包起来的部分)匹配的正则表达式:"\{.+\}",

    另一个则要和每个例句部分匹配(也就是小括号中的内容),:\(([^)]+\)

     

     

    而且由于要把例句的各项分离出来,所以要再把里面的各部分用分组的方法匹配出来:" ([^(]+)/(.+)/(.+):([^)]+) "。

    为了简便起见,我们不再和从数据库里读出,而是构造一个包含同样内容的字符串变量,程序片段如下:

    try{
             String content="['kevin] [名词](人名凯文){(Kevin loves comic./凯文爱漫画/名词:凯文) (Kevin is living in ZhuHai now./凯文现住在珠海/名词: 凯文)}";
             String ps1="\\{.+\\}";
             String ps2="\\([^)]+\\)";
             String ps3="([^(]+)/(.+)/(.+):([^)]+)";
             String sentence;
             PatternCompiler rocom=new Perl5Compiler();
             Pattern pattern1=orocom.compile(ps1);
             Pattern pattern2=orocom.compile(ps2);
             Pattern pattern3=orocom.compile(ps3);
             PatternMatcher matcher=new Perl5Matcher();
    //先找出整个例句部分
                if (matcher.contains(content,pattern1)) {
                MatchResult result=matcher.getMatch();
                String example=result.toString();
                PatternMatcherInput input=new PatternMatcherInput(example);
            //分别找出例句一和例句二
                while (matcher.contains(input,pattern2)){
                    result=matcher.getMatch();
                    sentence=result.toString();
            //把每个例句里的各项用分组的办法分隔出来
                    if (matcher.contains(sentence,pattern3)){
                      result=matcher.getMatch();
                      System.out.println("英文句: "+result.group(1));
                      System.out.println("句子中文翻译: "+result.group(2));
                      System.out.println("词性: "+result.group(3));
                      System.out.println("意思: "+result.group(4));
                    }
                }
            }
           }
      catch(Exception e) {
                 System.out.println(e);
           }

     

     


    输出结果为:
    英文句: Kevin loves comic.
    句子中文翻译: 凯文爱漫画
    词性: 名词
    意思: 凯文
    英文句: Kevin is living in ZhuHai now.
    句子中文翻译: 凯文现住在珠海
    词性: 名词
    意思: 凯文

    ★查找替换:
    以上的两个应用都是单纯在查找字符串匹配方面的,我们再来看一下查找后如何对目标字符串进行替换。

    例如我现在想把第二个例句进行改动,换为:Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。

    也就是把
    ['kevin] [名词](人名凯文){(Kevin loves comic./凯文爱漫画/名词: 凯文)( Kevin is living in ZhuHai now. /凯文现住在珠海/名词: 凯文)}

    改为:
    ['kevin] [名词](人名凯文){(Kevin loves comic./凯文爱漫画/名词: 凯文)( Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。)}

    之前,我们已经了解Util.substitute()方法与Substiution接口,以及Substiution的两个实现类 StringSubstitution和Perl5Substitution,我们就来看看怎么用Util.substitute()方法配合 Perl5Substitution来完成我们上面提出的替换要求,确定正则表达式:

    我们要先找到其中的整个例句部分,也就是由大括号包起来的字串,并且把两个例句分别分组,所以正则表达式为:"\{(\([^)]+\)) (\([^)]+\))\}",如果用替换变量来代替分组,那么上面的表达式可以看为"\{$1$2\}",这样就可以更容易看出替换变量与分组间的关系。

    根据上面的正则表达式Perl5Substitution类可以这样构造:
    Perl5Substitution("{$1( Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。)}")

    再根据这个Perl5Substitution对象来使用Util.substitute()方法便可以完成替换了,实现的代码片段如下:

    try{
       String content="['kevin] [名词](人名凯文){(Kevin loves comic./凯文爱漫画/名词: 凯文)(Kevin lives in ZhuHai now./凯文现住在珠海/名词: 凯文)}";
       String ps1="\\{(\\([^)]+\\))(\\([^)]+\\))\\}";
       String sentence;
       String pure;
       PatternCompiler rocom=new Perl5Compiler();
       Pattern pattern1=orocom.compile(ps1);
       PatternMatcher matcher=new Perl5Matcher();
           String result=Util.substitute(matcher,
            pattern1,new Perl5Substitution(
           "{$1( Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。)}",1),
            content,Util.SUBSTITUTE_ALL);
            System.out.println(result);
       }
      catch(Exception e) {
                 System.out.println(e);
           }

     

     


    输出结果是正确的,为:
    ['kevin] [名词](人名凯文){(Kevin loves comic./凯文爱漫画/名词: 凯文)( Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。)}

    至于有关使用numInterpolations参数的构造器用法,读者只要根据上面的介绍自己动手试一下就会清楚了,在此就不再例述。

    总结:
    本文首先介绍了Jakarta-ORO正则表达式库的对象与方法,并且接着举例让读者对实际应用有进一步的了解,虽然例子都比较简单,但希望读者们在看了该文后对Jakarta-ORO正则表达式库有一定的认知,在实际工作中有所帮助与启发。

    其实在Jakarta org里除了Jakarta-ORO外还有一个百分百的纯JAVA正则表达式库,就是由Jonathan Locke赠与Jakarta ORG的Regexp,在该包里面包含了完整的文档以及一个用于调试的Applet例子,对其有兴趣的读者可以到此下载。

    参考资料:

    本文的主要参考文章,该文在介绍Jakarta-ORO的同时也为读者详尽解析了正则表达式的基本语法。
    一个基于PERL的正则表达式详尽教程(虽然该教程是基于PERL的,但是你并不需要有PERL的经验,虽然那会有所帮助),以及一个不错的正则表达?

  • rely on yourself 日志 [2010年12月07日]

    2010-12-07 16:46:08

     

    现实与理想,咫尺天涯

    rely on yourself.

  • 调整vmware虚拟机硬盘空间的方法 最简单可行

    2010-11-01 21:51:25

    调整vmware虚拟机硬盘空间的方法 最简单可行

     

    在VMware中又不能直接修改虚拟机的硬盘容量大小,查找无数帖子,终于找到了解决之道,最简单傻瓜式。

    其实在VMware安装目录下就有一个vmware-vdiskmanager.exe程序,它是一个命令行工具,可用来修改虚拟机硬盘的大小。方法如下:


        第一步:按Win+R键调出运行对话框,输入“cmd”并按回车键启动命令提示符窗口。


        第二步:进入VMware的安装目录(比如我的安装目录为:D:\ProgramFiles\VMwarelVMware Workstation),找到"vmware-vdiskmanager"文件,最简单直接拖到命令提示符窗口。

        第三步:在后面直接加上下面的命令: -x 20Gb "D\VMware\WinXP\Windows XP Professional.vmdk"   即 -x 需要的硬盘大小 "虚拟文件路径\虚拟系统名称.vmdk" ,如:图1


    (注意;在命令提示符后输入"vmware-vdiskmanager",什么参数也不加直接按回车键,可显示这一命令的说明。参数"-X"表示要扩展虚拟机硬盘空间,紧随其后的数字是要扩展的大小(本例为扩展到20GB,这是一个磁盘总量,包含了原先的磁盘容量)。最后是指定要操作的虚拟机磁盘的具体文件,因为路径名中有空格,所以必须以双引号括起来。)

    第四步:按回车键开始执行,执行完毕,退出命令提示符窗口,重启VMware,会发现虚拟机硬盘空间已变成20GB了。


    如果原来的虚拟机硬盘已被分成了多个分区,那么在通过vmware-vdiskmanager.exe扩大了硬盘空间后还得在盛拟机系统中安装第三方分区工具对虚拟机分区做出调整

          注意,请严格按图1的格式操作,否则运行不成功!

    调整vmware虚拟机硬盘空间的方法 最简单可行

     

     

     

  • 2010 贱语大全!搜刮整理版,你被贱到了吗?

    2010-10-28 23:28:50

  • 【精彩】

    2010 贱语大全!搜刮整理版,你被贱到了吗?

  • 1,撼山易,撼姑娘难,撼对你没电的姑娘更是难上加难....
    2,长个包子样其实也没什么,毕竟看了没**,起码还有食欲,要是狗都不理了,那真是人品有问题了....
    3,你长的比假奶粉的毒性还大 我看着都头大....
    4,上帝关上一扇门的同时也打开了一扇窗,如此说来,上帝没安排丘比特射你可他赐予你双手...这个都懂,不解释!
    5,日久不仅生情,还可能生子....
    6,这条说个事吧 初入大学时,常见水果摊摆卖黄瓜,女生常购之,不解,后来联合男生大一就要买电脑此事,顿悟....都是单身惹的祸....对了想起一句不知谁说的:情侣多了,黄瓜也不好卖了....哈哈,够邪恶... (此6条均为猫扑楼主自编 不信还有巧合雷同)

    =====================华丽丽的分割线===========================

    1.别和我谈恋爱,虚伪。有本事咱俩结婚。
    2.你情敌和曾经背叛你的人同时掉入河中,并且他们不会游泳,你是选择蹦迪还是去KTV?
    3.love your mother who who…...
    4.别做点错事就把什么脏水都往自己身上泼,姐还要留着冲厕所呢。
    5.新闻联播的牛X之处在于就算你一直在换台,也能完整的看完一条新闻。

    6.你跟谁俩整那表情呢。。我欠你贷款要到期了还是怎么的。
    7.爷不是你的小浣熊,玩不出你的其乐无穷。
    8.人生苦短,必须性感。
    9.不是所有看上去**的美女都是婊 子,还有可能是推销员。
    10.我不整理房间,我是乱室佳人。

    11.法律规定:男人23岁才能结婚,可是18岁就能当兵。这说明了3个问题:一是杀人比做丈夫容易;二是过日子比打仗难;三是女人比敌人更难对付。
    12.姐不是客服人员,你没权要求姐答这答那。
    13.别人的钱财乃我的身外之物。
    14.你出生后是不是被扔上去3次,但只被接住2次?
    15.有的人,做面膜的时候,比真人好看多了。

    16.跟你很熟吗?没事弹个视频,你当是你家电视啊,一按就出人。
    17.能动手,就尽量别吵吵。
    18.长张鞋垫脸,就别怪人踩着。
    19.牛B中的战斗机,贱人中的VIP。
    20.牛粪终归是牛粪,上锅蒸了也不会变成香饽饽。

    21.你给我滚,马不停蹄的滚... ...
    22.猛的一看你不怎么样,仔细一看还不如猛的一看。
    23.你就是堕胎失败的最好例子!
    24.想做二奶并不是你的错,可来大学念书就是你的不对了!!
    25.做个有气质的流氓,做个有品位的色狼,做个有知识的文盲!

    26.你问雄癞蛤蟆什么最美,他的回答一定是雌癞蛤蟆。不用怀疑他的欣赏水平,只是所处的环境不同。
    27.有些事情无须争辩,表面服从,偷偷反抗。
    28.昨天捡了一块鼠标垫,想配台电脑,大家说还缺些啥呢?
    29.打你就打你,还要挑日子吗?
    30.真羡慕你这么年轻就认识我了。

    31.勇于认错,坚决不改。
    32.你匍匐在地上仰视别人,就不能怪人家站得笔直俯视你。
    33.灵魂的性感,才是骨子里的真正的性感。
    34.**尚未努力,革命仍须成功。
    35.太理智的人一定会错过误入歧途的机会,以及错误带来的沿途美景。

    36.有谁会在时过境迁之后还在那里等你?
    37.要戒烟,早睡,好好的死。
    38.要不是打不过你,早就跟你翻脸了。
    39.万恶的新社会啊,为什么你就没有包办婚姻了?
    40.毁谁不是毁,灭谁不是灭。

    41.不是我不叠被子,主要是我恋旧,就是喜欢睡前一天睡过的被窝。非逼我把这个生活习惯问题上升到人格修养上来。
    42.从单纯到冷漠是怎样的疲惫?
    43.眼泪的存在是为了证明悲伤不是一场幻觉。
    44.我真的不愿意用脚趾头鄙视你。但是,是你逼我这么做的!
    45.讨厌听到“对不起”这三个字,这说明我又被什么人占便宜,或者被欺骗,甚至被辜负。

    46.终究要亲自受伤,才会学着聪明...
    47.看不见的东西固然可怕,但人心不是更可怕吗?
    48.有些失望是无可避免的,但大部分的失望,都是因为你高估了自己。
    49.很多事介于不说憋屈和说了矫情之间。
    50.这世间,真心本就稀缺,更该俭省。

    51.在乎的人不明白,明白的人不在乎。
    52.诺不轻信,故人不负我;诺不轻许,故我不负人。
    53.男人哭了,是因为他真的爱了;女人哭了,是因为她真的放弃了。
    54.身边有太多的伤害,希望某天早上醒来,世界上只有我一个人,安静的死去...
    55.有些问题没有答案就是最后的答案,有的事情没有结果就是最好的结果。

    56.世上有三种人:一是良心被狗吃了的人,二是良心没被狗吃的人,三是良心连狗都不吃的人。
    57.女人的眼泪是最无用的液体,但你让女人流泪说明你很无用。
    58.一念起,万水千山;一念灭,沧海桑田。
    59.我深信,会有一个男人是为受我的折磨而来到这世上的。
    60.心不动,则不痛。

    61.想说爱我,先学会和我做朋友。
    62.男人是条狗,谁有本事谁牵走。
    63.恨,有时是误用了爱的力量。
    64.谎言和誓言的区别在于,一个是听的人当真了,一个是说的人当真了。
    65.狼行天下,吃肉;狗行天下,吃屎。

    66.爱的反义词不是不爱而是曾经爱过。
    67.我不骂你是因为我不想恭维你,知道不?
    68.一觉醒来,天都黑了...
    69.连贝克汉姆都不知道,你丫还有什么资格敢跟我谈篮球!
    70.男人与牙刷--我绝不与人共用!

    71.将来就娶唐僧做老公,能玩就玩一玩,不能玩就把他吃掉。
    72.人不怕死,但是最怕不知道怎么活!
    73.我不能让所有人都满意,因为不是所有人都是人!
    74.我只在意我在意的,你,不在这个范围!
    75.你以为你是多余的,其实吧...你还真是多余的!

    76.不爱我,放了我...
    77.他说爱你的时候,是无心之过,别轻易感动。
    78.再美好也经不住遗忘,再悲伤也抵不过时间。
    79.幸好爱情不是一切,幸好一切都不是爱情。
    80.男人说谎,是要让自己觉得好过;女人说谎,是要让对方好过。

    81.让女人念念不忘的是感情,让男人念念不忘的是感觉。
    82.感情随着时间沉淀,感觉随着时间消失...
    83.谁能明白谁的深爱,谁又能理解谁的离开...
    84.也许似乎大概是,然而未必不见得。
    85.除了变化,无一例外。

    86.一个人时,善待自己;两个人时,善待对方。
    87.地球是运动的,一个人不会永远处在倒霉的位置。
    88.誓言只是一时的失言。
    89.就算再想哭,也要微笑着说一句:你大爷的!
    90.人生如戏,全靠演技。

    91.你信不信我一巴掌把你拍墙上,想抠都抠不下来。
    92.喜欢吸烟是因为它可以伤肺,却不会伤心。
    93.没有谁瞧不起你,因为别人根本就没有瞧你,大家都很忙的。
    94.宁愿悲哀的深刻,不愿开心的肤浅。
    95.但愿我能像个婴儿那么善忘与无情...

    96.和对自己有恶意的人绝交。人有绝交,才有至交。
    97.现在很痛苦,等过阵子回头看看,会发现其实那都不算事。
    98.过去的事情可以不忘记,但一定要放下。
    99.永远不要给背叛过自己的朋友第二次背叛的机会。
    100.你没那么多观众,别那么累。

    101.贱人就是贱人,经济危机了也贵不了!
    102.和你一同笑过的人,你可能把他忘了,但是和你一同哭过的人,你却永远不会忘。
    103.如果方向错了,停下来就是前进。
    104.你会流泪,并不代表真的慈悲;我会微笑,并不代表一切都好。
    105.结局其实一早就注定了,我们不过是按照命运的剧本生活。

    106.我的精神分裂已经治好了,现在我和我都很好。
    107.感谢虚伪突然诚恳,感谢谎言弄假成真。
    108.在寂寞当儿想念一个人,不算什么。但如果在热闹的时候想念,又不同了。
    109.我曾拥有你,想到就心酸。
    110.世上没有未完的事,只有未死的心。

    111.不见得我比别人更坚强些,只不过我沉默得比别人更彻底些。不见得你比别人更痛苦些,只不过你表达得更精彩些。
    112.我们有着不同的假面,扮演着不同的角色,演绎着不同的经历,却有着相同的悲哀。
    113.这年头,有人忙单身,有人忙结束单身。
    114.开心了就笑,不开心了就过会儿再笑。
    115.读万卷书,不如行万里路;行万里路,不如阅人无数;阅人无数,不如明师指路。

    116.只有殉情的女人,没有痴情的男人。
    117.让我在这里低调的喊一句,你的过去我来不及参与,你的未来打死我也不想参与了。
    118.我眼本明,因你而瞎!!!
    119.世界很大,转角有爱,我走了,您随意!
    120.一个人要是舍得让你伤心,就根本不会在乎你是否流泪。所以赶紧收起那卑微的泪水,洗洗脸刷刷牙,该干嘛就干嘛去吧...

    121.如果你是我的菜,对不起,最近我不想吃菜。况且,你并不是我的菜...
    122.这星期就下了两场雨,第一场三天,第二场四天...
    123.我们一直在寻觅,寻觅,那个我们都有的结局。
    124.牵着你的手,闭着眼睛走我也不会迷路。
    125.什么叫快乐?就是掩饰自己的悲伤对每个人微笑。

    126.快乐和幸福那么相似,可是快乐就是幸福吗?
    127.第一句话错误,整个假设失败。
    128.在一个不爱你的男人面前流泪,那是侮辱你自己。
    129.敬告各位家长:请不要骂自己的孩子是“小兔崽子”,因为从遗传学的角度讲,这对你们自己是非常不利的。
    130.有招想去,没招死去。

    131.爱或被爱,不如相爱。
    132.当一个女人在看天空的时候,她并不想寻找什么。她只是寂寞...
    133.话是人说的,屁也是人放的,说话和放屁一样,都是一口气而已。
    134.某些人的爱情,只是一种“当时的情绪”。如果对方错将这份情绪当做长远的爱情,是本身的幼稚。
    135.如果没法忘记他,就不要忘记好了。真正的忘记,是不需要努力的。

    136.如果我们不能在一起,那么说明我们没有缘分。既然没有缘分,那么不能在一起也没什么好遗憾的。
    137.如何知世故而不世故。
    138.让我们心理上受苦的,不是事情本身,而是我们对事情的想法和围绕着这个事情所编造的故事。
    139.珍惜能拥有的,放弃得不到的,何乐而不为?
    140.欢乐如烟花般短暂,感情如玻璃般脆弱。

    141.我想要的是一起吃方便面,也能够谦让着喝汤。
    142.不爱非要爱,是一种自虐;有爱而不爱,是一种自残。
    143.看别人不顺眼,是自己修养不够。
    144.一个女人的品位,在于她身边站着一个怎样品位的男人。
    145.女人一生之中最成功的事情之一,便是选了一个对的男人。

    146.看透的时候,假装没看透。
    147.吃下去的就坚决不再吐出来,所以吃之前要想清楚。恋爱也是。
    148.可以不认同,但要学会尊重。
    149.我是没有锅,有锅早就把你给炖了!
    150.你不害人就是给社会做贡献了!

    151.打你应该!不打你悲哀!
    152.同样都是自来水,装你妈的纯净啊!
    153.历史,只有人名是真的;小说,只有人名是假的。
    154.要么忍,要么残忍。
    155.别跟姐问东问西,猫扑上的人比姐懂的多,有问题上去发帖子去!

    156.早回家的男人,讲故事给老婆听;晚回家的男人,编故事给老婆听。
    157.你这么牛B为什么tian~an-door没挂你的照片啊?
    158.把你栽到花盆里让你也知道知道什么是植物人!
    159.我把你的话放到油锅里可以榨出油来!
    160.一个受过教育的笨蛋是多么可怕的笨蛋啊!

    161.你的话,我连标点符号都不信。
    162.hey,请问一下,你的棺材是翻盖的还是滑盖的?
    163.qq的在线率越高,证明这个人越寂寞。
    164.男人的实力,就是你兜里的人民币。
    165.想想,还是幼儿园好混。

    166.梦想不实现都是因为不够现实。
    167.如果我的人生是一部电影,你就是那弹出来的广告。
    168.我哪有空跟你玩儿啊,像我这样的大牌,今年档期早都排满了,我有好多好多电影,电视剧和广告要看啊。
    169.我说这位大哥,我又不是草船,你的贱用不着总往我这儿乱发!
    170.俩人彻底分手了之后,任何一方在对方每年生日时发短信送祝福,以此证明:你看咱俩虽然分手了,但我还记得你,甚至还记得你的生日。是完全没有必要的狗屎行为,你把人家当烈士陵园了?

    171.光长着一双发现美的眼睛还不够,关键是你那眼睛必须还得能发现自己的丑。
    172.爱变成婚姻,无非就是慢慢的把感受变成忍受,其中还可能夹杂无法预料的承受。
    173.什么都在涨价,就是人越来越贱...
    174.你原来在我的心里,后来慢慢你就跑我胃里了,再后来我把你消化了,你就跑我大肠里了,最后你变成了一个屁,然后我就把你放了,你是个屁我不放了你,难道还留在肠子里慢慢回味不成?!
    175.我们都能勇敢的面对--你爱的人不爱你;但是,谁都无力面对--一个爱你很久很久的人转身离去。

    176.有多少人一辈子承诺爱一个人又付诸行动了呢?
    177.传闻对女人不好的男人下辈子会做卫生巾。
    178.青春不常在,抓紧谈恋爱。
    179.一个人一辈子成功不成功就看追悼会了。
    180.你若先走了,转身时就不要怪我也在背对着你。

    181.找不到我喜欢的伞,我宁愿淋雨。
    182.没人牵我的手,我就--揣兜里。
    183.人生最重要的不是所在的位置,而是所朝的方向。同样是个B,你一路向北能变成NB,撞破南墙不回头,就只能当个NB。
    184.脑袋空不要紧,关键是不要进水。
    185.人生为棋,我愿为卒,行动虽慢,可谁曾见我后退一步。

    186.虾的大红之日,便是它的大悲之时。
    187.朋友和刺客唯一的区别是:刺客在背后捅你一刀,你回头痛苦地说,啊,你是?----朋友在背后捅你一刀,你回头惊讶的说,啊,是你!
    188.中国人的2大特点:不爱说实话,不爱听实话。
    189.婆婆妈妈的结果:男性女性化,女性大妈化。
    190.像每一滴酒回不了最初的葡萄,我回不了年少。

    191.生活多美好,有吃有喝有电脑。
    192.在古代,我们不短信 不网聊 不漂洋过海 不被堵在路上,如果我想你,就翻过两座山 走五里路 去牵你的手。
    193.那些你所不知道的,就是命中注定。
    194.发情的你和绝情的我怎样面对这个滥情的世界。
    195.如果你想让他从此忘记你,那你就以你一贯的样子去见他;而如果你想让他从此忘不了你,那就以一个颠覆性的面貌去见他。

    196.我不是天桥上算命的,唠不出那么多你爱听的嗑。
    197.明月几时有,把酒问青天...青天说:滚你妈的,我这么忙,哪有时间理你,自己看天气预报去!
    198.铁杵能磨成针,但木杵只能磨成牙签。材料不对,再努力也没用。
    199.男人偷腥时的智商仅次于爱因斯坦!
    200.有人说生了孩子就不会痛经了,那就生一个吧!

    201.男人保持兴趣的时间通常会与猎物挣扎的时间成正比,投降越快,失宠越早。
    202.再美好也经不住遗忘,再悲伤也抵不过时间。
    203.Miss somebody I lost.Forget somebody I miss...
    204.幸好爱情不是一切,幸好一切都不是爱情...
    205.年少时,我们因谁因爱或是只因寂寞而同场起舞;
    沧桑后,我们何因何故寂寞如初却宁愿形同陌路。

    206.自从两个妓 女自称是某名牌大学的毕业生后,我现在一般都自称文盲。
    207.人要是无聊啊,鼻涕泡都能拿来玩会。
    208.最近穷疯了,没钱买大饼吃,只好啃馒头。想吃大饼了,就把馒头拍扁,想吃面条了,就用梳子把馒头梳几下。
    209.在职场中就应该像柯南那样,有一种我走到哪就让别人死到哪的霸气。
    210.将错就错,或者将计就计了,反正将就了。

    211.初恋无限好,只是挂得早。
    212.就怕会更难过,只好装作比你冷漠。
    213.这世界上有两个我,一个假装快乐,一个真心难过。
    214.带着你的为我好滚出我的生活。
    215.怎么会突然想哭?难道我也有些逆流成河的小忧伤。

    216.我不要求什么,并不代表我不在乎什么。
    217.一称体重我就很不开心,不开心的时候我就想吃东西。
    218.我祝你孤独,并且长命百岁。
    219.当我努力地提高自我修为的时候,总有那么一些人就是喜欢跑过来当炮灰...那我只好换个角度,成全你!
    220.再多的“我爱你”抵不上一句“我娶你”。

    221.9朵玫瑰是长久,99朵玫瑰还是长久,不就是99朵是相对豪华长久呗...
    222.有这样一个人,你给他发短信,他会马上回你,无论白天还是深夜。有这样一个人,你问他,他会听你说,你不想理他了,他也不会再发短信烦你。他,是10086...
    223.企鹅GG和企鹅MM去约会,企鹅MM还没有到约会地点,企鹅GG就一直在左看看,右看看...左看看,右看看...左看看,右看看...企鹅MM来了后看见企鹅GG这个样子,怒了!一巴掌呼了过去骂道:“你以为你TMD在登陆QQ啊?”
    224.女朋友说她在日本找到工作了,叫我在国内好好工作,没事不要看**。
    225.男朋友说他在泰国找到工作了,叫我在国内好好工作,不要去泰国旅游。

    226.如果你恨一个男人,就把他的女人揍成李宇春,让他无法享受上半身的快乐,如果你恨一个女人,就把她的男人揍成李宇春,让她无法享受下半身的快乐。
    227.谁对我的感情能像......对人民币那样的坚定啊?
    228.你妈生你的时候一定是满怀焦虑,心不在焉的,如此潦草...
    229.你别总是带着一脸便秘似的郁闷!
    230.比恋爱更能使人疯狂的是--失恋。

    231.明明是乡镇干部之子的气质还偏装都市富二代。
    232.没人给你台阶下,还是自己搬把椅子吧。
    233.股市暴跌后还有报复性反弹呢,我偶尔做下出格的事,用以表达自己的不满,无可厚非吧?
    234.年轻时抖落的那些目光,十年后还剩几双?
    235.没有男朋友的人每个晚上都是有时间的...

    236.两耳不闻窗外事,一心只上猫扑网。
    237.一觉醒来,天都黑了...
    238.只要你要,只要我有。
    239.记性好,还是太过关心的缘故?
    240.你这人特善良,特别是对不起人的时候...

    241.没有伞的孩子必须努力奔跑。
    242.如果心胸不似海,又怎能有海一样的事业。
    243.只做第一个我,不做第二个谁。
    244.窈窕君子,淑女好求。
    245.专家建议,每天睡眠不要超过24小时,有个差不多就行了,也别太过。
    246.如果你相信命,那么一切的偶然都是注定;如果你不相信命,那么一切的注定都是偶然。
    247.收女友一名,名额有限 预报从速(小月月教主级别恭请绕行,吾等屁民,口味较淡!) 并赠送豪华大礼包:1,床位半张,2,逛街免费跟班一名 3,寂寞无聊陪扯淡人员一名 4,无助时坚实肩膀一个 5,可升任管家婆 助理 内务大臣等等重要官职!另有随机大礼一份,入选揭晓!
     
  • LR9.5 与sqlserver2008不兼容?

    2010-10-27 21:31:48

     

     

    LR9.5 与sqlserver2008不兼容?

    今天参数化时,lr死掉,报错如下。

    vugen.exe caused an EXCEPTION_ACCESS_VIOLATION in module MFC80.DLL at 001B:7821C0F3, Ordinal3771()+0098 byte(s)

    EAX=00000000  EBX=079C9FE0  ECX=77E2B888  EDX=00000030  ESI=016C7340
    EDI=00000001  EBP=0012E284  ESP=0012E1D0  EIP=7821C0F3  FLG=00010206
    CS=001B   DS=0023  SS=0023  ES=0023   FS=003B  GS=0000

    001B:7821C0F3 MFC80.DLL, Ordinal3771()+0098 byte(s)

    001B:7820277E MFC80.DLL, Ordinal6275()+0034 byte(s)

    001B:78201514 MFC80.DLL, Ordinal1028()+0163 byte(s)

    001B:7820172A MFC80.DLL, Ordinal1209()+0053 byte(s)

    001B:40A70AAB coparamui.dll, DllUnregisterServer()+36923 byte(s)

    001B:77E2B6E3 USER32.dll, LoadCursorW()+19701 byte(s)

    。。。。。

    经查是与SQL2008不兼容问题

    google解决如下:

    分析了原因可能是因为调用的MFC80.dll和安装sql2008附带的MFC80.dll不一致。

    loadrunner9.5调用下面路径下的mfc80.dll
    C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.1833_x-ww_2fd6f5db\mfc80.dll ......1,080KB

    安装sqlserver 2008后,系统中的mfc80.dll
    C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_dec6ddd2\mfc80.dll.........1,068KB

    解决方法:
    备份C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.1833_x-ww_2fd6f5db\mfc80.dll => mfc80.dll.bak
    复制C:\WINDOWS\WinSxS\x86_Microsoft.VC80.MFC_1fc8b3b9a1e18e3b_8.0.50727.42_x-ww_dec6ddd2\mfc80.dll到上面的目录。

    重启loadrunner9.5,尝试参数化,正常。

    参考自http://bbs.51testing.com/viewthread.php?tid=155060

    "+userLink+""; $('miniAd').show(); } }, onFailure: function(){} }}); } showMiniAd();
     
     
  • 八个问题思考人生,生活需要思索(反思下下)

    2010-10-24 11:26:28

    八个问题思考人生,生活需要思索

     

    问题一:如果你家附近有一家餐厅,东西又贵又难吃,桌上还爬着蟑螂,你会因为它很近很方便,就一而再、再而三地光临吗?  
        回答:你一定会说,这是什么烂问题,谁那么笨,花钱买罪受?  
        可同样的情况换个场合,自己或许就做类似的蠢事。  
        不少男女都曾经抱怨过他们的情人或配偶品性不端,三心二意,不负责任。明知在一起没什么好的结果,怨恨已经比爱还多,但却“不知道为什么”还是要和他搅和下去,分不了手。说穿了,只是为了不甘,为了习惯,这不也和光临餐厅一样?  
        ———做人,为什么要过于执着?!


        问题二:如果你不小心丢掉100块钱,只知道它好像丢在某个你走过的地方,你会花200块钱的车费去把那100元找回来吗?  
        回答:一个超级愚蠢的问题。  
        可是,相似的事情却在人生中不断发生。做错了一件事,明知自己有问题,却怎么也不肯认错,反而花加倍的时间来找藉口,让别人对自己的印象大打折扣。被人骂了一句话,却花了无数时间难过,道理相同。为一件事情发火,不惜损人不利己,不惜血本,不惜时间,只为报复,不也一样无聊?  
        失去一个人的感情,明知一切已无法挽回,却还是那么伤心,而且一伤心就是好几年,还要借酒浇愁,形销骨立。其实这样一点用也没有,只是损失更多。
        ———做人,干吗为难自己?!
      

        问题三:你会因为打开报纸发现每天都有车祸,就不敢出门吗?  
        回答:这是个什么烂问题?当然不会,那叫因噎废食。  
        然而,有不少人却曾说:现在的离婚率那么高,让我都不敢谈恋爱了。说得还挺理所当然。也有不少女人看到有关的诸多报道,就对自己的另一半忧心忡忡,这不也是类似的反应?所谓乐观,就是得相信:虽然道路多艰险,我还是那个会平安过马路的人,只要我小心一点,不必害怕过马路。  
        ———做人,先要相信自己。
      

        问题四:你相信每个人随便都可以成功立业吗?  
        回答:当然不会相信。
        但据观察,有人总是在听完成功人士绞尽脑汁的建议,比如说,多读书,多练习之后,问了另一个问题?那不是很难?  
        我们都想在3分钟内学好英文,在5分钟内解决所有难题,难道成功是那么容易的吗?改变当然是难的。成功只因不怕困难,所以才能出类拔萃。 有一次坐在出租车上,听见司机说看到自己前后都是高档车,兀自感叹:“唉,为什么别人那么有钱,我的钱这么难赚?”  
        我心血来潮,问他:“你认为世上有什么钱是好赚的?”他答不出来,过了半晌才说:好像都是别人的钱比较好赚。  
        其实任何一个成功者的钱都是艰辛取得。我们实在不该抱怨命运。  
        ———做人,依靠自己!

      
        问题五:你认为完全没有打过篮球的人,可以当很好的篮球教练吗?  
        回答:当然不可能,外行不可能领导内行。  
        可是,有许多人,对某个行业完全不了解,只听到那个行业好赚钱,就马上开起业来了。  
        我看过对穿着没有任何品味,或根本不在乎穿着的人,梦想却是开间服装店;不知道电脑怎么开机的人,却想在网上聊天,结果道听途说,却不反省自己是否专业能力不足,只抱怨时不我与。  
        ———做人,量力而行。
      

        问题六:相似但不相同的问题:你是否认为,篮球教练不上篮球场,闭着眼睛也可以主导一场完美的胜利?  
        回答:有病啊,当然是不可能的。  
        可是却有不少朋友,自己没有时间打理,却拼命投资去开咖啡馆、餐厅,开自己根本不懂的公司,火烧屁股一样急着把辛苦积攒的钱花掉,去当一个稀里糊涂的投资人。亏的总是比赚的多,却觉得自己是因为运气不好,而不是想到出了问题。  
        ———做人,记得反省自己。

      
        问题七:你宁可永远后悔,也不愿意试一试自己能否转败为胜?  
        回答:恐怕没有人会说:“对,我就是这样的孬种”吧。  
        然而,我们却常常在不该打退堂鼓时拼命打退堂鼓,为了恐惧失败而不敢尝试成功。  
         以关颖珊赢得2000年世界花样滑冰冠军时的精彩表现为例:她一心想赢得第一名,然而在最后一场比赛前,她的总积分只排名第三位,在最后的自选曲项目上,她选择了突破,而不是少出错。在4分钟的长曲中,结合了最高难度的三周跳,并且还大胆地连跳了两次。她也可能会败得很难看,但是她毕竟成功了。  
        她说:“因为我不想等到失败,才后悔自己还有潜力没发挥。”  
        一个中国伟人曾说:胜利的希望和有利情况的恢复,往往产生于再坚持一下的努力之中。  
        ———做人,何妨不放手一搏。

      
        问题八:你的时间无限,长生不老,所以最想做的事,应该无限延期?  
        回答:不,傻瓜才会这样认为。 然而我们却常说,等我老了,要去环游世界;等我退休,就要去做想做的事情;等孩子长大了,我就可以……  
        我们都以为自己有无限的时间与精力。其实我们可以一步一步实现理想,不必在等待中徒耗生命。如果现在就能一步一步努力接近,我们就不会活了半生,却出现自己最不想看到的结局。  
        ———做人,要活在当下。

     

     

  • 多线程脚本_思路二则

    2010-10-14 20:07:18

    多线程脚本: 一个是按执行时间,一个是按执行次数

    计算平均响应时间:

    方法1:设定运行时间:
    线程   运行时间 运行次数
    线程1: 1s    2 
    线程1: 1s    4
    线程1: 1s    2


    time/次数  

    1/10 0.1  ===>错误

    (1/2 + 1/4 + 1/2) / 3 = 1.25/3 = 0.4   ===>正确

     

    方法二:设定固定次数:

    线程    运行次数  运行时间
    线程1: 10        2 
    线程1: 10        4
    线程1: 10        2

    time/次数
    (2+4+2)/(3*10)

    也可以按照上面的算法:

    (2/10+4/10+2/10) / 3 = 结果

    总结:第一种算法是通用的,第二种算法是特例。

  • mysql explain 及 profile,优化SQL

    2010-09-21 15:07:02

     

     

     

     


    http://hi.baidu.com/gguoyu/blog/item/f811d7f4cfd9b0e27709d752.html

    mysql explain 及 profile

     

    2010-07-09 14:22在mysql查询性能分析中最常用的就是explain了,profile查看一些具体的性能也是不错的
    1. profile
    我们可以先使用
    SELECT @@profiling;
    来查看是否已经启用profile,如果profilng值为0,可以通过
    SET profiling = 1;
    来启用。启用profiling之后,我们执行一条查询语句,比如:
    select count(*) from roi_summary;
    然后show profiles查看如下:
    +----------+------------+----------------------------------+
    | Query_ID | Duration       | Query                            |
    +----------+------------+----------------------------------+
    |        1       | 0.00021500 | select @@profiling               |
    |        2       | 0.05522700 | select count(*) from roi_summary |
    +----------+------------+----------------------------------+
    2 rows in set (0.00 sec)

    其中ID为5的语句是刚执行的查询语句,这时候我们执行show profile for query 2来查看这条语句的执行过程如下;
    +--------------------------------+----------+
    | Status                         | Duration |
    +--------------------------------+----------+
    | starting                       | 0.000021 |
    | checking query cache for query | 0.000045 |
    | checking permissions           | 0.000007 |
    | Opening tables                 | 0.000011 |
    | System lock                    | 0.000004 |
    | Table lock                     | 0.000040 |
    | init                           | 0.000012 |
    | optimizing                     | 0.000005 |
    | statistics                     | 0.000010 |
    | preparing                      | 0.000010 |
    | executing                      | 0.000005 |
    | Sending data                   | 0.055021 |
    | end                            | 0.000007 |
    | end                            | 0.000004 |
    | query end                      | 0.000003 |
    | storing result in query cache | 0.000004 |
    | freeing items                  | 0.000008 |
    | closing tables                 | 0.000005 |
    | logging slow query             | 0.000002 |
    | cleaning up                    | 0.000003 |
    +--------------------------------+----------+
    20 rows in set (0.00 sec)
    可以看出此条查询语句的执行过程及执行时间,总的时间约为0.05s。
    这时候我们再执行一次
    select count(*) from roi_summary;
    show profiles;
    +----------+------------+----------------------------------+
    | Query_ID | Duration   | Query                            |
    +----------+------------+----------------------------------+
    |        1 | 0.00021500 | select @@profiling               |
    |        2 | 0.05522700 | select count(*) from roi_summary |
    |        3 | 0.00006000 | select count(*) from roi_summary |
    +----------+------------+----------------------------------+


    然后执行show profile for query 3来查看本条语句的执行过程
    +--------------------------------+----------+
    | Status                         | Duration |
    +--------------------------------+----------+
    | starting                       | 0.000016 |
    | checking query cache for query | 0.000007 |
    | checking privileges on cached | 0.000004 |
    | checking permissions           | 0.000005 |
    | sending cached result to clien | 0.000022 |
    | logging slow query             | 0.000003 |
    | cleaning up                    | 0.000003 |
    +--------------------------------+----------+

    可以看出此次第二次查询因为前一次的查询生成了cache,所以这次无需从数据库文件中再次读取数据而是直接从缓存中读取,结果查询时间比第一次快了N倍。

    2. explain
    至于EXPLAIN 官方文档讲解的相当详细了,
    地址:http://dev.mysql.com/doc/refman/5.1/zh/optimization.html#explain

     

     

     

     

     

     

     

     

    =============================================================================

     


    首先,影响所有语句的一个因素是:你的许可设置得越复杂,所需要的开销越多。

    执行GRANT语句时使用简单的许可,当客户执行语句时,可以使MySQL降低许可检查开销。例如,如果未授予任何表级或列级权限,服务器不需要检查tables_priv和columns_priv表的内容。同样地,如果不对任何 账户进行限制,服务器不需要对资源进行统计。如果查询量很高,可以花一些时间使用简化的授权结构来降低许可检查开销。

    如果你的问题是与具体MySQL表达式或函数有关,可以使用mysql客户程序所带的BENCHMARK()函数执行定时测试。其语法为BENCHMARK(loop_count,expression)。例如:

    mysql> SELECT BENCHMARK(1000000,1+1);+------------------------+| BENCHMARK(1000000,1+1) |+------------------------+|                      0 |+------------------------+1 row in set (0.32 sec)上面结果在PentiumII 400MHz系统上获得。它显示MySQL在该系统上在0.32秒内可以执行1,000,000个简单的+表达式运算。

    所有MySQL函数应该被高度优化,但是总有可能有一些例外。BENCHMARK()是一个找出是否查询有问题的优秀的工具。

    7.2.1. EXPLAIN语法(获取SELECT相关信息)
    EXPLAIN tbl_name或:

    EXPLAIN [EXTENDED] SELECT select_optionsEXPLAIN语句可以用作DESCRIBE的一个同义词,或获得关于MySQL如何执行SELECT语句的信息:

    ·         EXPLAIN tbl_name是DESCRIBE tbl_name或SHOW COLUMNS FROM tbl_name的一个同义词。

    ·         如果在SELECT语句前放上关键词EXPLAIN,MySQL将解释它如何处理SELECT,提供有关表如何联接和联接的次序。

    该节解释EXPLAIN的第2个用法。

    借助于EXPLAIN,可以知道什么时候必须为表加入索引以得到一个使用索引来寻找记录的更快的SELECT。

    如果由于使用不正确的索引出现了问题,应运行ANALYZE TABLE更新表的统计(例如关键字集的势),这样会影响优化器进行的选择。参见13.5.2.1节,“ANALYZE TABLE语法”。

    还可以知道优化器是否以一个最佳次序联接表。为了强制优化器让一个SELECT语句按照表命名顺序的联接次序,语句应以STRAIGHT_JOIN而不只是SELECT开头。

    EXPLAIN为用于SELECT语句中的每个表返回一行信息。表以它们在处理查询过程中将被MySQL读入的顺序被列出。MySQL用一遍扫描多次联接(single-sweep multi-join)的方式解决所有联接。这意味着MySQL从第一个表中读一行,然后找到在第二个表中的一个匹配行,然后在第3个表中等等。当所有的表处理完后,它输出选中的列并且返回表清单直到找到一个有更多的匹配行的表。从该表读入下一行并继续处理下一个表。

    当使用EXTENDED关键字时,EXPLAIN产生附加信息,可以用SHOW WARNINGS浏览。该信息显示优化器限定SELECT语句中的表和列名,重写并且执行优化规则后SELECT语句是什么样子,并且还可能包括优化过程的其它注解。

    EXPLAIN的每个输出行提供一个表的相关信息,并且每个行包括下面的列:

    ·         id

    SELECT识别符。这是SELECT的查询序列号。

    ·         select_type

    SELECT类型,可以为以下任何一种:

    o        SIMPLE

    简单SELECT(不使用UNION或子查询)

    o        PRIMARY

    最外面的SELECT

    o        UNION

    UNION中的第二个或后面的SELECT语句

    o        DEPENDENT UNION

    UNION中的第二个或后面的SELECT语句,取决于外面的查询

    o        UNION RESULT

    UNION的结果。

    o        SUBQUERY

    子查询中的第一个SELECT

    o        DEPENDENT SUBQUERY

    子查询中的第一个SELECT,取决于外面的查询

    o        DERIVED

    导出表的SELECT(FROM子句的子查询)

    ·         table

    输出的行所引用的表。

    ·         type

    联接类型。下面给出各种联接类型,按照从最佳类型到最坏类型进行排序:

    o        system

    表仅有一行(=系统表)。这是const联接类型的一个特例。

    o        const

    表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!

    const用于用常数值比较PRIMARY KEY或UNIQUE索引的所有部分时。在下面的查询中,tbl_name可以用于const表:

    SELECT * from tbl_name WHERE primary_key=1; SELECT * from tbl_nameWHERE primary_key_part1=1和 primary_key_part2=2;o        eq_ref

    对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY。

    eq_ref可以用于使用= 操作符比较的带索引的列。比较值可以为常量或一个使用在该表前面所读取的表的列的表达式。

    在下面的例子中,MySQL可以使用eq_ref联接来处理ref_tables:

    SELECT * FROM ref_table,other_table  WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table  WHERE ref_table.key_column_part1=other_table.column    AND ref_table.key_column_part2=1;o        ref

    对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。

    ref可以用于使用=或<=>操作符的带索引的列。

    在下面的例子中,MySQL可以使用ref联接来处理ref_tables:

    SELECT * FROM ref_table WHERE key_column=expr; SELECT * FROM ref_table,other_table  WHERE ref_table.key_column=other_table.column; SELECT * FROM ref_table,other_table  WHERE ref_table.key_column_part1=other_table.column    AND ref_table.key_column_part2=1;o        ref_or_null

    该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。

    在下面的例子中,MySQL可以使用ref_or_null联接来处理ref_tables:

    SELECT * FROM ref_tableWHERE key_column=expr OR key_column IS NULL;参见7.2.7节,“MySQL如何优化IS NULL”。

    o        index_merge

    该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。详细信息参见7.2.6节,“索引合并优化”。

    o        unique_subquery

    该类型替换了下面形式的IN子查询的ref:

    value IN (SELECT primary_key FROM single_table WHERE some_expr)unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。

    o        index_subquery

    该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:

    value IN (SELECT key_column FROM single_table WHERE some_expr)o        range

    只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。

    当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range:

    SELECT * FROM tbl_nameWHERE key_column = 10; SELECT * FROM tbl_nameWHERE key_column BETWEEN 10 and 20; SELECT * FROM tbl_nameWHERE key_column IN (10,20,30); SELECT * FROM tbl_nameWHERE key_part1= 10 AND key_part2 IN (10,20,30);o        index

    该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。

    当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。

    o        ALL

    对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。

    ·         possible_keys

    possible_keys列指出MySQL能使用哪个索引在该表中找到行。注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。

    如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询。参见13.1.2节,“ALTER TABLE语法”。

    为了看清一张表有什么索引,使用SHOW INDEX FROM tbl_name。

    ·         key

    key列显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。参见13.2.7节,“SELECT语法”。

    对于MyISAM和BDB表,运行ANALYZE TABLE可以帮助优化器选择更好的索引。对于MyISAM表,可以使用myisamchk --analyze。参见13.5.2.1节,“ANALYZE TABLE语法”和5.9.4节,“表维护和崩溃恢复”。

    ·         key_len

    key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。注意通过key_len值我们可以确定MySQL将实际使用一个多部关键字的几个部分。

    ·         ref

    ref列显示使用哪个列或常数与key一起从表中选择行。

    ·         rows

    rows列显示MySQL认为它执行查询时必须检查的行数。

    ·         Extra

    该列包含MySQL解决查询的详细信息。下面解释了该列可以显示的不同的文本字符串:

    o        Distinct

    MySQL发现第1个匹配行后,停止为当前的行组合搜索更多的行。

    o        Not exists

    MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行。

    下面是一个可以这样优化的查询类型的例子:

    SELECT * 从t1 LEFT JOIN t2 ON t1.id=t2.id  WHERE t2.id IS NULL;假定t2.id定义为NOT NULL。在这种情况下,MySQL使用t1.id的值扫描t1并查找t2中的行。如果MySQL在t2中发现一个匹配的行,它知道t2.id绝不会为NULL,并且不再扫描t2内有相同的id值的行。换句话说,对于t1的每个行,MySQL只需要在t2中查找一次,无论t2内实际有多少匹配的行。

    o        range checked for each record (index map: #)

    MySQL没有发现好的可以使用的索引,但发现如果来自前面的表的列值已知,可能部分索引可以使用。对前面的表的每个行组合,MySQL检查是否可以使用range或index_merge访问方法来索取行。关于适用性标准的描述参见7.2.5节,“范围优化”和7.2.6节,“索引合并优化”,不同的是前面表的所有列值已知并且认为是常量。

    这并不很快,但比执行没有索引的联接要快得多。

    o        Using filesort

    MySQL需要额外的一次传递,以找出如何按排序顺序检索行。通过根据联接类型浏览所有行并为所有匹配WHERE子句的行保存排序关键字和行的指针来完成排序。然后关键字被排序,并按排序顺序检索行。参见7.2.12节,“MySQL如何优化ORDER BY”。

    o        Using index

    从只使用索引树中的信息而不需要进一步搜索读取实际的行来检索表中的列信息。当查询只使用作为单一索引一部分的列时,可以使用该策略。

    o        Using temporary

    为了解决查询,MySQL需要创建一个临时表来容纳结果。典型情况如查询包含可以按不同情况列出列的GROUP BY和ORDER BY子句时。

    o        Using where

    WHERE子句用于限制哪一个行匹配下一个表或发送到客户。除非你专门从表中索取或检查所有行,如果Extra值不为Using where并且表联接类型为ALL或index,查询可能会有一些错误。

    如果想要使查询尽可能快,应找出Using filesort 和Using temporary的Extra值。

    o        Using sort_union(...), Using union(...), Using intersect(...)

    这些函数说明如何为index_merge联接类型合并索引扫描。详细信息参见7.2.6节,“索引合并优化”。

    o        Using index for group-by

    类似于访问表的Using index方式,Using index for group-by表示MySQL发现了一个索引,可以用来查询GROUP BY或DISTINCT查询的所有列,而不要额外搜索硬盘访问实际的表。并且,按最有效的方式使用索引,以便对于每个组,只读取少量索引条目。详情参见7.2.13节,“MySQL如何优化GROUP BY”。

    通过相乘EXPLAIN输出的rows列的所有值,你能得到一个关于一个联接如何的提示。这应该粗略地告诉你MySQL必须检查多少行以执行查询。当你使用max_join_size变量限制查询时,也用这个乘积来确定执行哪个多表SELECT语句。参见7.5.2节,“调节服务器参数”。

    下列例子显示出一个多表JOIN如何能使用EXPLAIN提供的信息逐步被优化。

    假定你有下面所示的SELECT语句,计划使用EXPLAIN来检查它:

    EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,               tt.ProjectReference, tt.EstimatedShipDate,               tt.ActualShipDate, tt.ClientID,               tt.ServiceCodes, tt.RepetitiveID,               tt.CurrentProcess, tt.CurrentDPPerson,               tt.RecordVolume, tt.DPPrinted, et.COUNTRY,               et_1.COUNTRY, do.CUSTNAME        FROM tt, et, et AS et_1, do        WHERE tt.SubmitTime IS NULL          AND tt.ActualPC = et.EMPLOYID          AND tt.AssignedPC = et_1.EMPLOYID          AND tt.ClientID = do.CUSTNMBR;对于这个例子,假定:

    ·         被比较的列声明如下:


     列
     列类型
     
    tt
     ActualPC
     CHAR(10)
     
    tt
     AssignedPC
     CHAR(10)
     
    tt
     ClientID
     CHAR(10)
     
    et
     EMPLOYID
     CHAR(15)
     
    do
     CUSTNMBR
     CHAR(15)
     

    ·         表有下面的索引:


     索引
     
    tt
     ActualPC
     
    tt
     AssignedPC
     
    tt
     ClientID
     
    et
     EMPLOYID(主键)
     
    do
     CUSTNMBR(主键)
     

    ·         tt.ActualPC值不是均匀分布的。

    开始,在进行优化前,EXPLAIN语句产生下列信息:

     

    table type possible_keys key  key_len ref  rows  Extraet    ALL  PRIMARY       NULL NULL    NULL 74do    ALL  PRIMARY       NULL NULL    NULL 2135et_1  ALL  PRIMARY       NULL NULL    NULL 74tt    ALL  AssignedPC,   NULL NULL    NULL 3872           ClientID,           ActualPC      range checked for each record (key map: 35) 因为type对每张表是ALL,这个输出显示MySQL正在对所有表产生一个笛卡尔乘积;即每一个行的组合!这将花相当长的时间,因为必须检查每张表的行数的乘积!对于一个实例,这是74 * 2135 * 74 * 3872 = 45,268,558,720行。如果表更大,你只能想象它将花多长时间……

    这里的一个问题是MySQL能更高效地在声明具有相同类型和尺寸的列上使用索引。在本文中,VARCHAR和CHAR是相同的,除非它们声明为不同的长度。因为tt.ActualPC被声明为CHAR(10)并且et.EMPLOYID被声明为CHAR(15),长度不匹配。

    为了修正在列长度上的不同,使用ALTER TABLE将ActualPC的长度从10个字符变为15个字符:

    mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR(15);现在tt.ActualPC和et.EMPLOYID都是VARCHAR(15),再执行EXPLAIN语句产生这个结果:

     

    table type   possible_keys key     key_len ref         rows    Extratt    ALL    AssignedPC,   NULL    NULL    NULL        3872    Using             ClientID,                                         where             ActualPCdo    ALL    PRIMARY       NULL    NULL    NULL        2135      range checked for each record (key map: 1)et_1  ALL    PRIMARY       NULL    NULL    NULL        74      range checked for each record (key map: 1)et    eq_ref PRIMARY       PRIMARY 15      tt.ActualPC 1 这不是完美的,但是好一些了:rows值的乘积少了一个因子74。这个版本在几秒内执行完。

    第2种方法能消除tt.AssignedPC = et_1.EMPLOYID和tt.ClientID = do.CUSTNMBR比较的列的长度失配问题:

    mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),    ->                MODIFY ClientID   VARCHAR(15);EXPLAIN产生的输出显示在下面:

    table type   possible_keys key      key_len ref           rows Extraet    ALL    PRIMARY       NULL     NULL    NULL          74tt    ref    AssignedPC,   ActualPC 15      et.EMPLOYID   52   Using             ClientID,                                         where             ActualPCet_1  eq_ref PRIMARY       PRIMARY  15      tt.AssignedPC 1do    eq_ref PRIMARY       PRIMARY  15      tt.ClientID   1 这几乎很好了。

    剩下的问题是,默认情况,MySQL假设在tt.ActualPC列的值是均匀分布的,并且对tt表不是这样。幸好,很容易告诉MySQL来分析关键字分布:

    mysql> ANALYZE TABLE tt;现在联接是“完美”的了,而且EXPLAIN产生这个结果:

    table type   possible_keys key     key_len ref           rows Extratt    ALL    AssignedPC    NULL    NULL    NULL          3872 Using             ClientID,                                        where             ActualPCet    eq_ref PRIMARY       PRIMARY 15      tt.ActualPC   1et_1  eq_ref PRIMARY       PRIMARY 15      tt.AssignedPC 1do    eq_ref PRIMARY       PRIMARY 15      tt.ClientID   1注意在从EXPLAIN输出的rows列是一个来自MySQL联接优化器的“教育猜测”。你应该检查数字是否接近事实。如果不是,可以通过在SELECT语句里面使用STRAIGHT_JOIN并且试着在FROM子句以不同的次序列出表,可能得到更好的性能。

    7.2.2. 估计查询性能
    在大多数情况下,可以通过计算磁盘搜索来估计性能。对小的表,通常能在1次磁盘搜索中找到行(因为索引可能被缓存)。对更大的表,可以使用B-树索引进行估计,将需要log(row_count)/log(index_block_length/3 * 2/(index_length + data_pointer_length))+1次搜索才能找到行。

    在MySQL中,索引块通常是1024个字节,数据指针通常是4个字节,这对于有一个长度为3(中等整数)的索引的500,000行的表,通过公式可以计算出log(500,000)/log(1024/3*2/(3+4))+1= 4次搜索。

    上面的索引需要大约500,000 * 7 * 3/2 = 5.2MB,(假设典型情况下索引缓存区填充率为2/3),可以将大部分索引保存在内存中,仅需要1-2调用从OS读数据来找出行。

    然而对于写,将需要4次搜索请求(如上)来找到在哪儿存放新索引,并且通常需要2次搜索来更新这个索引并且写入行。

    注意,上述讨论并不意味着应用程序的性能将缓慢地以logN 退化!当表格变得更大时,所有内容缓存到OS或SQL服务器后,将仅仅或多或少地更慢。在数据变得太大不能缓存后,将逐渐变得更慢,直到应用程序只能进行磁盘搜索(以logN增加)。为了避免这个问题,随数据增加而增加 键高速缓冲区大小。对于MyISAM表, 由key_buffer_size系统变量控制 键高速缓冲区大小。参见7.5.2节,“调节服务器参数”。

    7.2.3. SELECT查询的速度
    总的来说,要想使一个较慢速SELECT ... WHERE更快,应首先检查是否能增加一个索引。不同表之间的引用通常通过索引来完成。你可以使用EXPLAIN语句来确定SELECT语句使用哪些索引。参见7.4.5节,“MySQL如何使用索引”和7.2.1节,“EXPLAIN语法(获取关于SELECT的信息)”。

    下面是一些加速对MyISAM表的查询的一般建议:

    ·         为了帮助MySQL更好地优化查询,在一个装载数据后的表上运行ANALYZE TABLE或myisamchk --analyze。这样为每一个索引更新指出有相同值的行的平均行数的值(当然,如果只有一个索引,这总是1。)MySQL使用该方法来决定当你联接两个基于非常量表达式的表时选择哪个索引。你可以使用SHOW INDEX FROM tbl_name并检查Cardinality值来检查表分析结果。myisamchk --description --verbose可以显示索引分布信息。

    ·         要想根据一个索引排序一个索引和数据,使用myisamchk --sort-index --sort-records=1(如果你想要在索引1上排序)。如果只有一个索引,想要根据该索引的次序读取所有的记录,这是使查询更快的一个好方法。但是请注意,第一次对一个大表按照这种方法排序时将花很长时间!

     

  • java基本问题2则 string ; return 和 finally

    2010-09-14 20:38:35

     

    java基本问题

    1. String str1 ;  String str2 = null ;  String str3 = "" ; 三者的区别

    2. return 和 finally 的执行顺序

    下面是测试代码:

    package com.java.lianxi;

    public class Lianxi {

     /**
      * @param args
      */
     
     static int j;  // 在类中的属性可以自动赋初值,但是非类属性不会自动赋初值,会报异常。
     int i ; // 在类中的属性可以自动赋初值,但是非类属性不会自动赋初值,会报异常。
     
     public static void main(String[] args) {
      // TODO Auto-generated method stub
      
      String str1 ;
    //  if(str == null){
    //   System.out.println(str1);
    //  }
      String str2 = null ;
      String str3 = "" ;
      System.out.println("1----"+str2);
      System.out.println("2----"+str3);
      //System.out.println("2----"+str1);
      
      // int = 1 ; // 必须定义成  类的static变量才会自动赋值
      // 所有的对象在使用 前均要被初始化
      
      System.out.println("2----"+j); // static method 使用static 变量
      
    //  string是引用类型;
    //  
    //  String str ; // str没有被初始化,会报错 The local variable str1 may not have been initialized
    //
    //  string str = null 没有创建内存空间,str中存放的是空引用指针;
    //
    //  string str = "" 创建了内存空间,str中存放的是指向堆中的指针。
      
      System.out.println("return------->"+new Lianxi().mytest()) ;

      

     }
     
     public int mytest(){
      int var1 = 1 ;
      int var2 = 2 ;
      int var3 = 3 ;
      int var4 = 4 ;
      
      try{
       System.out.println("before return"); // 1
       return var1 ;                        //4
       //System.out.println("after return"); // Unreachable code
      }catch(Exception e){
       System.out.println("print in catch");
       return var2 ;
      }finally{
       //System.out.println(i);
       System.out.println("print in finally");  //2
       return var3 ;                           //3
       
      }
      //return var4 ; // Unreachable code
     }
     
     
     // finally 关键字是对 Java 异常处理模型的最佳补充。
     // finally 结构使代码总会执行,而不管有无异常发生。
     // 使用 finally 可以维护对象的内部状态,并可以清理非内存资源。
     // 如果没有 finally,您的代码就会很费解。
     // 比如关闭事务。正常流和异常流都要写。使用finally就没有这样的问题了。
     //
     
     
     
     //finally里的代码会抢在离开此方法前执行,
     //但是如果在finally里有return的话,那肯定就return了,就像if else分支里都有return一样
     
     //return、continue和break都不能阻止finally语句块的执行
     
     // 有一种方法可以退出 try 块而不执行 finally 块。
     // 如果代码在 try 内部执行一条 System.exit(0); 语句,
     // 则应用程序终止而不会执行 finally 执行。
     // 另一方面,如果您在 try 块执行期间拨掉电源,finally 也不会执行。)
    }

     

  • 教育--- fight for it

    2010-09-13 10:12:22

    火影 --- 理想,痛苦,信念

    相信的力量

    做你自己
    活出真我

    be yourself
    you are here

     

    教育事业---- 鲁迅 ---- 教育

    大学教育 --- 帮助别人成功

    虽然你不能改变世界,但是相信你的弟子可以

     

    做这些事,而不是金钱,更能让我激动不已

     

     

     

  • Linux中find常见用法示例

    2010-09-10 17:37:18


     

    Linux中find常见用法示例

     

    ·find   path   -option   [   -print ]   [ -exec   -ok   command ]   {} \;
    #-print 将查找到的文件输出到标准输出
    #-exec   command   {} \;      —–将查到的文件执行command操作,{} 和 \;之间有空格
    #-ok 和-exec相同,只不过在操作前要询用户
    ====================================================

    -name   filename             #查找名为filename的文件
    -perm                        #按执行权限来查找
    -user    username             #按文件属主来查找
    -group groupname            #按组来查找
    -mtime   -n +n                #按文件更改时间来查找文件,-n指n天以内,+n指n天以前
    -atime    -n +n               #按文件访问时间来查GIN: 0px">

    -ctime    -n +n              #按文件创建时间来查找文件,-n指n天以内,+n指n天以前

    -nogroup                     #查无有效属组的文件,即文件的属组在/etc/groups中不存在
    -nouser                     #查无有效属主的文件,即文件的属主在/etc/passwd中不存
    -newer   f1 !f2              找文件,-n指n天以内,+n指n天以前
    -ctime    -n +n               #按文件创建时间来查找文件,-n指n天以内,+n指n天以前
    -nogroup                     #查无有效属组的文件,即文件的属组在/etc/groups中不存在
    -nouser                      #查无有效属主的文件,即文件的属主在/etc/passwd中不存
    -newer   f1 !f2               #查更改时间比f1新但比f2旧的文件
    -type    b/d/c/p/l/f         #查是块设备、目录、字符设备、管道、符号链接、普通文件
    -size      n[c]               #查长度为n块[或n字节]的文件
    -depth                       #使查找在进入子目录前先行查找完本目录
    -fstype                     #查更改时间比f1新但比f2旧的文件
    -type    b/d/c/p/l/f         #查是块设备、目录、字符设备、管道、符号链接、普通文件
    -size      n[c]               #查长度为n块[或n字节]的文件
    -depth                       #使查找在进入子目录前先行查找完本目录
    -fstype                      #查位于某一类型文件系统中的文件,这些文件系统类型通常可 在/etc/fstab中找到
    -mount                       #查文件时不跨越文件系统mount点
    -follow                      #如果遇到符号链接文件,就跟踪链接所指的文件
    -cpio                %;      #查位于某一类型文件系统中的文件,这些文件系统类型通常可 在/etc/fstab中找到
    -mount                       #查文件时不跨越文件系统mount点
    -follow                      #如果遇到符号链接文件,就跟踪链接所指的文件
    -cpio                        #对匹配的文件使用cpio命令,将他们备份到磁带设备中
    -prune                       #忽略某个目录

    =====================================================
    $find   ~   -name   "*.txt"   -print    #在$HOME中查.txt文件并显示
    $find   .    -name   "*.txt"   -print
    $find   .    -name   "[A-Z]*"   -print   #查以大写字母开头的文件
    $find   /etc   -name   "host*"   -print #查以host开头的文件
    $find   .   -name   "[a-z][a-z][0–9][0–9].txt"    -print   #查以两个小写字母和两个数字开头的txt文件
    $find .   -perm   755   -print
    $find   .   -perm -007   -exec ls -l {} \;   #查所有用户都可读写执行的文件同-perm 777
    $find   . -type d   -print
    $find   .   !   -type   d   -print
    $find   .   -type l   -print

    $find   .   -size   +1000000c   -print        #查长度大于1Mb的文件
    $find   .   -size   100c         -print       # 查长度为100c的文件
    $find   .   -size   +10   -print              #查长度超过期作废10块的文件(1块=512字节)

    $cd /
    $find   etc   home   apps    -depth   -print   | cpio   -ivcdC65536   -o   /dev/rmt0
    $find   /etc -name "passwd*"   -exec grep   "cnscn"   {}   \;   #看是否存在cnscn用户
    $find . -name "yao*"   | xargs file
    $find   . -name "yao*"   |   xargs   echo    "" > /tmp/core.log
    $find   . -name "yao*"   | xargs   chmod   o-w

    ======================================================

    find   -name april*                     在当前目录下查找以april开始的文件
    find   -name   april*   fprint file        在当前目录下查找以april开始的文件,并把结果输出到file中
    find   -name ap* -o -name may*   查找以ap或may开头的文件
    find   /mnt   -name tom.txt   -ftype vfat   在/mnt下查找名称为tom.txt且文件系统类型为vfat的文件
    find   /mnt   -name t.txt ! -ftype vfat   在/mnt下查找名称为tom.txt且文件系统类型不为vfat的文件
    find   /tmp   -name wa* -type l            在/tmp下查找名为wa开头且类型为符号链接的文件
    find   /home   -mtime   -2                 在/home下查最近两天内改动过的文件
    find /home    -atime -1                  查1天之内被存取过的文件
    find /home -mmin    +60                  在/home下查60分钟前改动过的文件
    find /home   -amin   +30                  查最近30分钟前被存取过的文件
    find /home   -newer   tmp.txt             在/home下查更新时间比tmp.txt近的文件或目录
    find /home   -anewer   tmp.txt            在/home下查存取时间比tmp.txt近的文件或目录
    find   /home   -used   -2                  列出文件或目录被改动过之后,在2日内被存取过的文件或目录
    find   /home   -user cnscn                列出/home目录内属于用户cnscn的文件或目录
    find   /home   -uid   +501                  列出/home目录内用户的识别码大于501的文件或目录
    find   /home   -group   cnscn              列出/home内组为cnscn的文件或目录
    find   /home   -gid 501                   列出/home内组id为501的文件或目录
    find   /home   -nouser                    列出/home内不属于本地用户的文件或目录
    find   /home   -nogroup                   列出/home内不属于本地组的文件或目录
    find   /home    -name tmp.txt    -maxdepth   4   列出/home内的tmp.txt 查时深度最多为3层
    find   /home   -name tmp.txt   -mindepth   3   从第2层开始查
    find   /home   -empty                     查找大小为0的文件或空目录
    find   /home   -size   +512k                查大于512k的文件
    find   /home   -size   -512k               查小于512k的文件
    find   /home   -links   +2                查硬连接数大于2的文件或目录
    find   /home   -perm   0700                查权限为700的文件或目录
    find   /tmp   -name tmp.txt   -exec cat {} \;
    find   /tmp   -name   tmp.txt   -ok   rm {} \;

    find    /   -amin    -10     # 查找在系统中最后10分钟访问的文件
    find    /   -atime   -2        # 查找在系统中最后48小时访问的文件
    find    /   -empty             # 查找在系统中为空的文件或者文件夹
    find    /   -group   cat        # 查找在系统中属于 groupcat的文件
    find    /   -mmin   -5         # 查找在系统中最后5分钟里修改过的文件
    find    /   -mtime   -1       #查找在系统中最后24小时里修改过的文件
    find    /   -nouser           #查找在系统中属于作废用户的文件
    find    /   -user    fred     #查找在系统中属于FRED这个用户的文件

    查当前目录下的所有普通文件
    --------------------------------------------------------------------------------

    # find . -type f -exec ls -l {} \;
    -rw-r–r–    1 root      root         34928 2003-02-25   ./conf/httpd.conf
    -rw-r–r–    1 root      root         12959 2003-02-25   ./conf/magic
    -rw-r–r–    1 root      root          180 2003-02-25   ./conf.d/README
    查当前目录下的所有普通文件,并在- e x e c选项中使用ls -l命令将它们列出
    =================================================
    在/ l o g s目录中查找更改时间在5日以前的文件并删除它们:
    $ find logs -type f -mtime +5 -exec   -ok   rm {} \;

    =================================================
    查询当天修改过的文件
    [root@book class]# find   ./   -mtime   -1   -type f   -exec   ls -l   {} \;

    =================================================
    查询文件并询问是否要显示
    [root@book class]# find   ./   -mtime   -1   -type f   -ok   ls -l   {} \; 
    < ls … ./classDB.inc.php > ? y
    -rw-r–r–    1 cnscn    cnscn       13709   1月 12 12:22 ./classDB.inc.php
    [root@book class]# find   ./   -mtime   -1   -type f   -ok   ls -l   {} \; 
    < ls … ./classDB.inc.php > ? n
    [root@book class]#

    =================================================
    查询并交给awk去处理
    [root@book class]# who   |   awk   ’{print $1"\t"$2}’
    cnscn    pts/0

    =================================================
    awk—grep—sed

    [root@book class]# df   -k |   awk ‘{print $1}’ |   grep   -v   ’none’ |   sed   s"/\/dev\///g"
    文件系统
    sda2
    sda1
    [root@book class]# df   -k |   awk ‘{print $1}’ |   grep   -v   ’none’
    文件系统
    /dev/sda2
    /dev/sda1

    1)在/tmp中查找所有的*.h,并在这些文件中查找“SYSCALL_VECTOR",最后打印出所有包含"SYSCALL_VECTOR"的文件名
    A) find   /tmp   -name   "*.h"   | xargs   -n50   grep SYSCALL_VECTOR
    B) grep   SYSCALL_VECTOR   /tmp/*.h | cut    -d’:'   -f1| uniq > filename
    C) find   /tmp   -name "*.h"   -exec grep "SYSCALL_VECTOR"   {}   \; -print

    2)find / -name filename -exec rm -rf {} \;
        find / -name filename -ok rm -rf {} \;

    3)比如要查找磁盘中大于3M的文件:
    find . -size +3000k -exec ls -ld {} ;

    4)将find出来的东西拷到另一个地方
    find *.c -exec cp ‘{}’ /tmp ‘;’

    如果有特殊文件,可以用cpio,也可以用这样的语法:
    find dir -name filename -print | cpio -pdv newdir

    6)查找2004-11-30 16:36:37时更改过的文件
    # A=`find ./ -name "*php"` |   ls -l –full-time $A 2>/dev/null | grep "2004-11-30 16:36:37"

    Linux-all, Linux | No Comments »

    find 实例
    四月 18th, 2006
      要在/usr/linux中查找所有的*.h,并在这些文件中查找“SYSCALL_VECTOR",最后打印出所有包含"SYSCALL_VECTOR"的文件名,有以下几种方法实现
    find /usr/linux -name "*.h" | xargs -n50 grep SYSCALL_VECTOR
    grep SYSCALL_VECTOR /usr/linux/*.h | cut -d’:’ -f1 | uniq > filename
    find /usr/linux -name "*.h" -exec grep "SYSCALL_VECTOR" {} \; -print

      我用find / -name filename| rm -rf,不成功,请问为什么不成功?
    find / -name filename -exec rm -rf {} \;
    find . -name filename |rm -rf试一下{} 表示你找出来的结果。
    \; 则相当于“宪法”,没什么说头,就是这么规定的,在 -exec 后面需要一个表示该命令终结的的符号。可以在 man find 中找到答案。
    要让rm识别find的结果,如下:
    find / -name filename |xargs rm -rf
    之所以find . -name filename |rm -rf不通过,是因为rm命令不接受从标准输入传过来的指令
    查找含特定字符串的文件
    例如查找当前目录下含有"the string you want find…"字符串的文件:
    $find . -type f -exec grep “the string you want find…” {} ; -print

      从根目录开始查tmpfile,一旦查到马上删除
    find / -name "tmpfile" -exec rm {} \;

      find 的perm问题
    请问一下以下命令什么意思?关键是那个数字前的-,其他都还知道
    find -name ".*" -perm -007
    我知道
    find -name ".*" -perm 755
    这个是用来查找权限位为755的隐藏文件
    噢,对了还有,我上边的命令都省略了find的pathname参数 find默认是查找当前工作目录的吗?
    如果我用 -ok 替代 -exec, 那么还需要加上 {} \; 吗?
    这个已经清楚,仍然需要,因为 -ok 只是 -exec 的提示模式,它只是多了一个确认操作的步骤,刚才没有读懂那几句E文的意思 呵呵 不好意思
    -007是指查找所有用户都可读、写、执行的文件,要小心呀~~~
    解释解释?
    find -name ".*" -perm -007 和 find -name ".*" -perm 777 有区别吗?
    -007是怎么来得呢?
    不过有一个问题
    我用 find . -perm -100 会列出当前目录 . , 这是为什么呢?

    下面引用由explover在 2002/10/01 06:15am 发表的内容:
    -007是指查找所有用户都可读、写、执行的文件,要小心呀~~~
    -007是查找含其它用户(不同组,非属主)可读,写,执行的文件.并不一定要同组可读写,-是指最少权限为007.
    下面引用由一颗小白菜在 2002/10/01 10:16am 发表的内容:
    OK了, 呵呵
    不过有一个问题
    我用 find . -perm -100 会列出当前目录 . , 这是为什么呢?
    这种方法不会准确的找出目录的. -100是指权限至少是属主可运行.
    在unix系统下,你可以拥有对目录文件的执行权你才可以进入一个目录.这便是目录文件被列出的原因.
    find . -perm -001 -print找到往往是目录文件.
    我的意思当然不是使用这种方法来找目录,只不过不明白其中的 -100 意义了
    那以此类推,是不是 -010是指权限至少是owner同组可执行的吗?也就是说其实这里的010和-是分开的,-表示一个至少的意思,而且010才是真正用来描述权限位的?
    这样子就明白了 谢谢你噢

      将find出来的东西拷到另一个地方?
    find *.c -exec cp ‘{}’ /tmp ‘;’
    如果有特殊文件,可以用cpio,也可以用这样的语法:
    find dir -name filename -print | cpio -pdv newdir

      找出磁盘中某个大小范围内的文件
    比如要查找磁盘中大于3M的文件:
    find . -size +3000k -exec ls -ld {} ;

      如何用find查找某一天更改的文件?
    可以使用这一行命令来实现:
    A=`find ~ -print` | ls -l –full-time $A 2>/dev/null | grep "Jun 27" | grep 1998

      使用find 命令查找某个时间段的shell怎么写。比如11点到12点的。thanks
    创建一个脚本judgetime,内容如下:
    ls -l $*|awk ‘{split($8,hour,":");if((hour[1]>23 || hour[1] < 1)&&hour[1]<24)print}’
    到要查找的目录下,运行
    find ./ -name "*" -exec judgetime {} \;
    注意时间格式为24小时制。
    thank you ,如果我要精确到分钟呢
    touch -t 04241112 starttemp #精确到12分钟
    touch -t 04241220 endtemp #截止到12点20
    find [dir] -newer starttemp -a ! -newer endtemp -exec ls -l {} \;
    newer?
    那昨天12:10文件如何呢?
    每天执行的时候,用当天的日期和时间戳替换一下不就行了吗?
    我不知道他是不是把所有的11:00~12:00的都找出来,是不是只执行一次还是每天都执行?
    这种情况俺猜想是自己的东西放在哪忘了,只记得当时是深夜了。
    有道理!
    不愧是斑竹!
    不光知道怎么解决问题,还知道在什么情况下出现这类问题,佩服佩服!
    问题又出现了。创建这个文件的时候。本来应该是时间的一栏现在写上了2002,而不是12:00.
    等到12:00过了吧!

      删除指定日期的文件
    find ./ -name 文件名 -exec rm -f {} \;
    例:删除当前30天内没用过的文件,用如下命令:
    find / -atime +30 -exec rm -f {} \;
    我自己试着写了一小段SHELL,也用ll ,grep, rm 几个命令,用起来还差强人意。
    对过滤出来的文件名列表中用了一个FOR语句,再执行rm 。现在我想把这段SHELL 扩展一下让它每天定时运行将 n 天前的文件删掉,有没有人能给我一些提示,谢谢!
    还有个问题,对于前面那位朋友提到的"find / -atime +30 -exec rm -f {} \;
    "方法,我很早就试过几次,不过好像都不太对,参数 -atime n 是查找n天前被访问过的文件,我不明白的是这里的时间参照点是什么,以及这个n天是怎么计算的。
    问 题二、对于"ll |cut -f 1" 这个命令我是不是用错了,我只想取出 ll 中列出的文件名,但用cut -f 命令做不到 ,我只好换用 ll |cut -c 59- 这种方式得到我要的文件名,but it’s a pool idear !我也试过用awk ,好像也不对,看看大家可不可以给我一些小小的提醒,TKS SO MUCH
    问题三、如何改变 I结点 的日期格式 我现在的系统显示的格式是:
    -rw-r—– 1 msahz01 users 2253 2002年2月 2日 poheader.i
    我想把这换成
    -rw-rw-rw- 1 house users 2193 Apr 19 2001 hkdisp.p
    如何才能做到这点?
    awk 应该可以
    ll | awk ‘{print $9}’
    删除多少天之前的文件
    find /yourpath -mtime +31 -exec rm {} \;
    find /yourpath -mtime +366 -exec rm {} \;

    find中, -ctime, -mtime及其-atime有何区别

    请问 -ctime 和 -mtime 有什么关系 ?
    如果父目录的 ctime 改变, 那它下面的文件的 ctime 就会自动都改了吗 ?
    -ctime 和 -mtime ,-atime 这些信息是存在哪儿呢 ?

    我用 -mtime -1 找到了新建或改的文件.
    但怎样才能找到一天内 mv 来的文件呢( 它们的时间是原有的时间,早于一天 ) ?

    用-newer选项啊。
    你可以先touch一个你想要的时间的文件如下:
    $ touch -t 08190800 test
    $ ls -l test
    -rw-r–r– 1 dba other 0 Aug 19 08:00 test
    然后
    $ find . -newer test -print
    .
    ./.sh_history
    $ ls -l .sh_history
    -rw——- 1 dba other 154 Aug 20 17:39 .sh_history

    用touch可以写出你想要的任何时间的文件,然后用-newer ,! -newer选项即可成功。

    1.ctime含inode信息修改的时间.mtime只指文件内容建立或修改的时间.
    2 不会.
    3.这些信息应该是存在文件系统的超级块里.

    我查了书 -ctime 是指 inode 的改变(或称文件的状态改变).
    请问 inode 存了哪些信息 ?
    做了些小测试,-mtime 改, -ctime 一定也改.
    改文件名, -ctime 也会改.
    谁能回答 i-node 存了哪些东西 ?

    vi /usr/include/sys/inode.h

    班主,我不能 access /usr/include/sys/inode.h .
    摘书如下:
    Directories contain directory entries. Each entry contains a file or subdirectory name and an index node reference number (i-node number). To increase speed and enhance use of disk space, the data in a file is stored at various locations in the computer’s memory. The i-node contains the addresses used to locate all the scattered blocks of data associated with a file. The i-node also records other information about the file including time of modification and access, access modes, number of links, file owner, and file type.
    可我发现 -atime 改了, -ctime 还没改. why ?
    ( 我先 cat 一个 ASCII 文件,再用 -atime -1 有它用 -ctime -1 居然没有它.)
    着岂不跟 inode 信息改变, ctime 就改矛盾吗?

    我不同意你贴出来的那段文章,正如我提到的那样,atime,ctime,mtime是放到超级块里,在sco unix下是一种叫stat的结构.(stat_32),不同的系统文件系统可能不同.
    sco 下inode的结构如下:

    typedef struct inode
    {
    struct inode *i_forw; /* inode hash chain */
    struct inode *i_back; /* ‘’ */
    struct inode *av_forw; /* freelist chain */
    struct inode *av_back; /* ‘’ */
    int *i_fsptr; /* "typeless" pointer to fs dependent */
    ino32_t i_number; /* i number, 1-to-1 with dev address */
    ushort i_ftype; /* file type = IFDIR, IFREG, etc. */
    short i_fstyp; /* File system type */
    off_t i_size; /* size of file */
    ushort i_uid; /* owner */
    ushort i_gid; /* group of owner */
    ushort i_flag;
    ushort i_want; /* i_flag extension to avoid MP races */
    ushort i_count; /* reference count */
    short i_nlink; /* directory entries */
    dev_t i_rdev; /* Raw device number */
    #define i_namtype i_rdev /* i_ftype==IFNAM subtype */
    dev_t i_dev; /* device where inode resides */
    struct mount *i_mton;/* ptr to mount table entry that */
    /* this directory is mounted on */
    struct region *i_rp; /* ptr to shared region if any */
    struct stdata *i_sp; /* ptr to associated stream */
    struct iisem *isem; /* ptr to XENIX semaphores */
    struct iisd *isd; /* ptr to XENIX shared data */
    } i_un;
    #define i_mnton i_un.i_mton /* i_ftype==IFDIR IMOUNT */
    #define i_rptr i_un.i_rp /* i_ftype==IFREG || i_ftype==IFBLK */
    #define i_sptr i_un.i_sp /* i_ftype==IFCHR || i_ftype==IFIFO */
    #define i_sem i_un.isem /* i_ftype==IFNAM && i_namtype==IFSEM */
    #define i_sd i_un.isd /* i_ftype==IFNAM && i_namtype==IFSHD */

    struct fstypsw *i_fstypp; /* ptr to file system switch FSPTR */
    long *i_filocks; /* pointer to filock (structure) list */
    unsigned long i_mappages; /* number of pages currently cached */
    unsigned long i_vcode; /* read-ahead block save (NFS) */
    short i_wcnt; /* write open count or ITEXT count */
    struct lockb i_cilock; /* tas to synchronize i_flag changes */
    ushort i_rdlocks; /* count of non-exclusive lockers */
    } inode_t;

    所以,访问一个文件不能改变inode信息.
    使用chown, chgrp, chmod命令可以很好的比较mtime和ctime
    chown改变一个文件的属主,用ctime可以找到,用mtime便找不到.
    试试看.

    多谢斑竹! 我是在 Solaris 上面试的.我是对 -ctime 不明白.
    试的结果如下:
    修改文件,-mtime 改了, -ctime 也会改.
    访问文件,-atime 改了, -ctime 没变.
    chown, chgrp, chmod,mv, 都会使 -ctime 改变,但不影响 -atime 和 -mtime.
    touch 可以改 -mtime and/or -atime,但 touch -a 只改访问时间时,-ctime也改了.
    touch -m 改修改时间时,-ctime当然也改了.
    好象还有别的很多东西可以令 -ctime 改变, 搞不清楚.
    有什么方法可以显示 -mtime,atime,ctime 吗?
    可以用 -ctime 来实现对目录的增量文件进行备份或 transfer 吗 ?
    多谢!

    没有什么工具显示,(可能是俺不知道)
    把下面程序里的st_mtime换成st_ctime,或st_atime便可以得到你要的了.
    #include
    int
    main (int argc, char **argv)
    {
    struct stat buf;
    char date[80];
    char fname[80];
    printf("Enter filename (with full path) to check mtime : ");
    scanf("%s",fname);
    stat(fname, &buf);
    printf ("mtime (in sec) of %s = %ld\n", fname, buf.st_mtime);
    strcpy(date, ctime((time_t *)&(buf.st_mtime)));
    printf ("mtime (in date) of %s = %s\n", fname, date);
    }

    至于文件备份,有什么不可以的么?

    mtime ls -l 最近修改文件内容的时间
    atime ls -lu 最近访问文件的时间
    ctime ls -li 最近文件有所改变的状态 ,如文件修改,属性\属主 改变 ,节点 ,链接变化等 ,应该是不拘泥只是时间前后的改变

    俺看了ls的帮助,以为只是按ctime或atime排序,显示的时间还是mtime.

    仔细比较了一下,ayhan说的是对的.谢谢ayhan.

    多谢 ahyan 提示 ! 我在 Solaris 上试过如下:
    mtime 用 ls -l 看到
    atime 用 ls -lu 看到
    ctime 用 ls -lc 看到. (ls -li 只有 inode number)
    摘书如下:
    -c Uses time of last modification of the i-node (file
    created, mode changed, and so forth) for sorting (-t)
    or printing (-l or -n).
    -u Uses time of last access instead of last modification
    for sorting (with the -t option) or printing (with the
    -l option).
    -i For each file, prints the i-node number in the first
    column of the report.

     

     

     

    转载自:http://apps.hi.baidu.com/share/detail/11177457









     

     

  • 2010年最新的韩国喜剧片

    2010-09-10 14:35:08

    最佳答案
    这些都是10年最新的韩国喜剧片:
    
    《你好杀人犯》 
    《六轮枪强盗团 》
    《加油站被袭事件2 》 
    《爸爸喜欢女人》
    《田禹治》
    《我眼里的豆荚》
    《爱子》
    《清潭菩萨》  
    《离家的男人》
    《鸭子的反击》
    《乔治和奉植》
    《邻家男子》
    《竞猜王》
    《超能力者》
    《我的强盗恋人》
    《得失之间》
    《棒球明猩》
    《快递惊魂》
    《棒球之爱》
    《我的野蛮女友2》
    《疯狂的钻石》
    《梦想成真》
    《欠债还情 》 
  • 性能测试人员面试经典技术问题(汇总)----果然经典

    2010-09-02 10:06:34

    第一篇:性能测试人员面试经典技术问题


    1.请问什么是性能测试、负载测试、压力测试?

          原参考答案:

      性能测试:对一个软件系统而言,包括执行效率、资源占用、系统稳定性、安全性兼容性、可扩展性等。

      负载测试:通过逐步加压的方式来确定系统的处理能力,确定系统能承受的各项阀值。

      压力测试:逐步增加负载,使系统某些资源达到饱和甚至失效的测试。

         个人理解:

         经典的问题,答案打算参考段念的书:
         性能测试(Performance Testing):是通过模拟系统实际运行的压力和使用场景组合,测试系统的性能是否满足实际生产的性能要求。
                 特点:1.主要目的是验证系统是否具备其宣称的能力
                       2.需要事先了解被测系统的典型场景,并具有确定的性能目标
                       3.要求在已确定的环境下运行
         负载测试(Load Testing):通过在被测系统上不断增加压力,直到某个性能指标超过预定指标或者某种资源使用已经达到饱和状态
                  特点:1. 主要目的是找到系统处理能力的极限,为系统调优提供数据。测试形式/手段:"检测--加压--知道性能指标超过预期"
                  2.在给定的测试环境下进行,考虑被测系统的业务压力量和典型场景
                  3. 一般用来了解系统的性能容量,或是配合性能调优
         压力测试(Stress Testing):测试系统在一定饱和状态下(CPU/MEMORY),
                     特点:1. 主要目的是检查系统处于压力情况下时,应用的表现
                     2. 一般用于测试系统的稳定性

      

      2.请分别针对性能测试、负载测试和压力测试试举一个简单的例子?

    原参考答案:

      性能测试例子:公司开发了一个小型项目管理系统,上线前需要做负载、压力、大数据量、强度测试等。

      负载测试:逐步加压,从而得到“响应时间不超过10秒”,“服务器平均CPU利用率低于85%”等指标阀值。

      压力测试:逐步加压,从而使“响应时间超过10秒”,“服务器平均CPU利用率高于90%”等指标来确定系统能承受的最大负载量。

      3.请例举出常用的性能测试工具,并指出这些工具的优缺点?

      LoadRunner,录制脚本快捷操作简便,需要一定的学习时间,有采购成本。

      4.请问您是如何得到性能测试需求?怎样针对需求设计、分析是否达到需求?

      在查看需求文档,从中提取性能测试需求,与用户交流,了解实际使用情况。

      结合业务信息设计操作场景总结出需测试的性能关键指标。

      执行用例后根据提取关键性能指标来分析是否满足性能需求。

      5.什么时候可以开始执行性能测试?

      在产品相对比较稳定,功能测试结束后。灵活性比较强。

      6.什么是集合点?设置集合点有什么意义?LoadRunner中设置集合点的函数是哪个?

      集合点可以控制各个Vuser以便在同一时刻执行任务。

      借助集合点,可以再LoadRunner中实现真正意义上的并发。

      lr_rendezvous()

      7.性能测试时,是不是必须进行参数化?为什么要创建参数?LoadRunner中如何创建参数?

      8是。

      模拟用户真实的业务操作。

      创建参数列表,用参数替换固定的文本。

      8.您了解关联吗?如何找出哪里需要关联?请给一些您所在项目的实例。

      了解。

      使用LoadRunner自动关联功能。手动关联:录制两份相同操作步骤的脚本,找出不同的部分进行判断。

      一个项目管理系统,每次登录后服务器都自动分配一个sessionID以便之后每次表单提交后验证。

      9.您如何调试LoadRunner脚本?

      设置断点、增加log。


    10.在LoadRunner中如何编写自定义函数?请给出一个您在以前项目中编写的函数。

      11.请问您是如何理解LoadRunner中集合点、事务以及检查点等概念?

      集合点:可以控制各个Vuser以便在同一时刻执行任务,可实现真正意义上的并发。

      事务:事务是用来度量服务器响应时间的操作集。

      检查点:在回放脚本期间搜索特定内容,从而验证服务器响应内容的正确性。

      12.如何应用LoadRunner进行性能测试?

      使用虚拟用户生成器创建脚本,使用控制器设定场景、运行脚本,使用分析器分析运行后得到的数据。

      13.LoadRunner中思考时间有什么作用?

      用户执行两个连续操作期间等待的时间。模拟用户真实的使用情况。

      14.LoadRunner中如何实现多用户并发操作,需要进行哪些设置?

      设置集合点来实现,在脚本中加入lr_rendezvous(),然后可以在控制器中设定集结百分比。

      15.LoadRunner中有基于目标和手动两种场景设计方式,他们分别适用于什么情况?

      手动场景可按照要求来配置场景,能够更加精确的满足测试需要。

      目标场景要先制定希望实现的测试目标,然后由控制器惊醒自动测试评估。

      16.LoadRunner中有几种并发执行策略,它们的含义是什么?

      三种。1.当所有虚拟用户中的x%到达集合点时释放。2.当所有正在运行的虚拟用户中的x%到达集合点时释放。3.当x个虚拟用户到达集合点时释放。

      17.有5台配置为处理器:Intel Pentium 4 1.6G,内存容量 512MB,硬盘容量 40GB的机器,如何较好的利用这些机器完成一次并发用户数为1000人的性能测试工作?

      1台做应用服务器,1台做数据库服务器,1台运行控制器并承担一部分负载生成任务,2台负载生成器。

      18.平时大家在注册邮箱等关联操作时,经常会遇到需要输入验证码的情况,请问,如果我们公司也开发了一套带验证码的应用软件,需要警醒性能测试,您会如何处理?

      留一个后门,我们设定一个所谓的“万能验证码”,只要用户输入这个“万能验证码”,系统就验证通过。测试完成后补上后门。




    ============================================================================================================================================

    第二篇:性能测试面试题(参考第四篇的英文题目及答案)
     
    1.什么是负载测试?什么是性能测试?

     

    2.性能测试包含了哪些测试(至少举出3种)

     

    3.简述性能测试的步骤

     

    4.简述使用Loadrunner的步骤

     

    5.什么时候可以开始执行性能测试?

     

    6.LoadRunner由哪些部件组成?

     

    7.你使用LoadRunner的哪个部件来录制脚本?

     

    8.LoadRunner的哪个部件可以模拟多用户并发下回放脚本?

     

    9.什么是集合点?设置集合点有什么意义?Loadrunner中设置集合点的函数是哪个?

     

    10.什么是场景?场景的重要性有哪些?如何设置场景?

     

    11.请解释一下如何录制web脚本?

     

    12.为什么要创建参数?如何创建参数?

     

    13.什么是关联?请解释一下自动关联和手动关联的不同。

     

    14.你如何找出哪里需要关联?请给一些你所在项目的实例。

     

    15.你在哪里设置自动关联选项?

     

    16.哪个函数是用来截取虚拟用户脚本中的动态值?(手工管联)

     

    17.你在VUGen中何时选择关闭日志?何时选择标准和扩展日志?

     

    18.你如何调试LoadRunner脚本?

     

    19你在LR中如何编写自定义函数?请给出一些你在以前进行的项目中编写的函数。

     

    20.在运行设置下你能更改那些设置?

     

    21.你在不同的环境下如何设置迭代?

     

    22.你如何在负载测试模式下执行功能测试?

     

    23.什么是逐步递增?你如何来设置?

     

    24.以线程方式运行的虚拟用户有哪些优点?

     

    25.当你需要在出错时停止执行脚本,你怎么做?

     

    26.响应时间和吞吐量之间的关系是什么?

     

    27.说明一下如何在LR中配置系统计数器?

     

    28.你如何识别性能瓶颈?

     

    29.如果web服务器、数据库以及网络都正常,问题会出在哪里?

     

    30.如何发现web服务器的相关问题?

     

    31.如何发现数据库的相关问题?

     

    32.解释所有web录制配置?

     

    33.解释一下覆盖图和关联图的区别?

     

    34.你如何设计负载?标准是什么?

     

    35.Vuser_init中包括什么内容?

     

    36. Vuser_end中包括什么内容?

     

    37.什么是think time?think_time有什么用?

     

    38.标准日志和扩展日志的区别是什么?

     

    39.解释以下函数及他们的不同之处。

    Lr_debug_message

    Lr_output_message

    Lr_error_message

    Lrd_stmt

    Lrd_fetch

     

    40.什么是吞吐量?

     

    41.场景设置有哪几种方法


    ============================================================================================================================================

    第三篇:性能测试面试题
    1、        【测试理论】描述不同的角色(用户、产品开发人员、系统管理员)各自关注的软件性能要点。

    2、        【测试理论】解释5个常用的性能指标的名称与具体含义。

    3、        【测试流程】简述性能测试流程与各阶段的工作内容。

    4、        【LR工具】web系统中,username参数表为file类型,表中有12个值,分别A、B、C、D、E、F、G、H、I、J、K、L。
    测试场景中虚拟并发用户数设为4,迭代次数设为3,
    参数中Select next row与Update value on分别为(Sequential, Each Iteration)与(Unique, Once)时,
    写出迭代3次的取值情况。

      

    (Select next row, Update value on)        虚拟用户取值(VUi:迭代时取值)

    (Sequential, Each Iteration)

    VU1:

    VU2:

    VU3:

    VU4:

    (Unique, Once)       

    VU1:

    VU2:

    VU3:

    VU4:

    5、【LR工具】web系统脚本录制过程中,两次录制同一功能点,在View Tree的Server Response中产生的字符串分别为:

    Server Response:name="_id_Node " value=" RSDP0013425" />", ENDITEM,

    Server Response:name="_id_Node " value=" RSDP1203655" />", ENDITEM,

    为脚本回放成功,需要对字符串中某些字符做一定处理,写出详细实现方法。

    6、        【数据库应用】现有Customers表和Sales表的数据如下:

    Customers表:

    CustID        Name          ShpCity            Discount

    449320        Adapto          PortLand            0.05

    890003        AA          PortLand            0.05

    888402        Seaworth  Albany            0.04

    Sales表:

    SaleID        CustID        SaleMount

    234112        499320        8000

    234113        888402        6500

    234114        499320        5900

    234115        890003        4500

    要求:

    1)        给出查询语句,描述:在Customers表中查询名字为AA或Bolt的查询语句;

    2)        给出删除操作,描述:在Sales表中删除SaleID为234115的语句。

    3)        根据以下结果表给出多表查询语句。

    SaleID        CustID        Name          Discount         SaleMount

    234112        499320        Adapto           0.05          8000

    234113        888402        Seaworth   0.04          6500

    234114        499320        Adapto           0.05          5900

    234115        890003        AA           0.05          4500

    7、        【数据库应用】为了尽可能避免大表全表扫描,最常见的方法有哪些?

    8、        【中间件】WebLogic参数调整中,列举三项影响并发性能的参数项并简述其含义。

    9、        【Unix命令】HP-UX与AIX操作系统中,监控CPU、内存、磁盘I/O的命令分别是什么?

    10、        【Unix命令】用命令实现:

    1)        对文件FileA添加读、写、执行权限;

    2)        列出当前系统与java相关的活动进程;

    3)        搜索当前文件夹中所有的.sh文件。

    11、  【网络】服务器ip地址为128.64.96.100,HP-UX操作系统,ftp服务开启,用户名与密码分别为username/password, /home目录下有一个monitor.svc文件,现需要将monitor.svc文件取到客户机192.168.2.100,服务器与客户机二者之间网络互通,描述在192.168.2.100上操作过程


    ============================================================================================================================================


    第四篇: 45道性能测试的面试题及答案(In English)


    1. What is load testing?
            - Load testing is to test that if the application works fine with the loads that result from large number of simultaneous users, transactions and to determine weather it can handle peak usage periods.
    2. What is Performance testing?
            - Timing for both read and update transactions should be gathered to determine whether system functions are being performed in an acceptable timeframe. This should be done standalone and then in a multi user environment to determine the effect of multiple transactions on the timing of a single transaction.
    3. Did u use LoadRunner? What version?
            - Yes. Version x.x .
    4. Explain the Load testing process? -
            Step 1: Planning the test. Here, we develop a clearly defined test plan to ensure the test scenarios we develop will accomplish load-testing objectives.
            Step 2: Creating Vusers. Here, we create Vuser scripts that contain tasks performed by each Vuser, tasks performed by Vusers as a whole, and tasks measured as transactions.
            Step 3: Creating the scenario. A scenario describes the events that occur during a testing session. It includes a list of machines, scripts, and Vusers that run during the scenario. We create scenarios using LoadRunner Controller. We can create manual scenarios as well as goal-oriented scenarios. In manual scenarios, we define the number of Vusers, the load generator machines, and percentage of Vusers to be assigned to each script. For web tests, we may create a goal-oriented scenario where we define the goal that our test has to achieve. LoadRunner automatically builds a scenario for us.
            Step 4: Running the scenario.We emulate load on the server by instructing multiple Vusers to perform. tasks simultaneously. Before the testing, we set the scenario configuration and scheduling. We can run the entire scenario, Vuser groups, or individual Vusers.
            Step 5: Monitoring the scenario.We monitor scenario execution using the LoadRunner online runtime, transaction, system resource, Web resource, Web server resource, Web application server resource, database server resource, network delay, streaming media resource, firewall server resource, ERP server resource, and Java performance monitors.
            Step 6: Analyzing test results. During scenario execution, LoadRunner records the performance of the application under different loads. We use LoadRunner’s graphs and reports to analyze the application’s performance.
    5. When do you do load and performance Testing?
            - We perform. load testing once we are done with interface (GUI) testing. Modern system architectures are large and complex. Whereas single user testing primarily on functionality and user interface of a system component, application testing focuses on performance and reliability of an entire system. For example, a typical application-testing scenario might depict 1000 users logging in simultaneously to a system. This gives rise to issues such as what is the response time of the system, does it crash, will it go with different software applications and platforms, can it hold so many hundreds and thousands of users, etc. This is when we set do load and performance testing.

    6. What are the components of LoadRunner?
            - The components of LoadRunner are The Virtual User Generator, Controller, and the Agent process, LoadRunner Analysis and Monitoring, LoadRunner Books Online.
    7. What Component of LoadRunner would you use to record a Script?
            - The Virtual User Generator (VuGen) component is used to record a script. It enables you to develop Vuser scripts for a variety of application types and communication protocols.
    8. What Component of LoadRunner would you use to play Back the script. in multi user mode?
            - The Controller component is used to playback the script. in multi-user mode. This is done during a scenario run where a vuser script. is executed by a number of vusers in a group.
    9. What is a rendezvous point?
            - You insert rendezvous points into Vuser scripts to emulate heavy user load on the server. Rendezvous points instruct Vusers to wait during test execution for multiple Vusers to arrive at a certain point, in order that they may simultaneously perform. a task. For example, to emulate peak load on the bank server, you can insert a rendezvous point instructing 100 Vusers to deposit cash into their accounts at the same time.
    10. What is a scenario?
            - A scenario defines the events that occur during each testing session. For example, a scenario defines and controls the number of users to emulate, the actions to be performed, and the machines on which the virtual users run their emulations.
    11. Explain the recording mode for web Vuser script?
            - We use VuGen to develop a Vuser script. by recording a user performing typical business processes on a client application. VuGen creates the script. by recording the activity between the client and the server. For example, in web based applications, VuGen monitors the client end of the database and traces all the requests sent to, and received from, the database server. We use VuGen to: Monitor the communication between the application and the server; Generate the required function calls; and Insert the generated function calls into a Vuser script.
    12. Why do you create parameters?
            - Parameters are like script. variables. They are used to vary input to the server and to emulate real users. Different sets of data are sent to the server each time the script. is run. Better simulate the usage model for more accurate testing from the Controller; one script. can emulate many different users on the system.
    13. What is correlation?
            Explain the difference between automatic correlation and manual correlation? - Correlation is used to obtain data which are unique for each run of the script. and which are generated by nested queries. Correlation provides the value to avoid errors arising out of duplicate values and also optimizing the code (to avoid nested queries). Automatic correlation is where we set some rules for correlation. It can be application server specific. Here values are replaced by data which are created by these rules. In manual correlation, the value we want to correlate is scanned and create correlation is used to correlate.
    14. How do you find out where correlation is required? Give few examples from your projects?
            - Two ways: First we can scan for correlations, and see the list of values which can be correlated. From this we can pick a value to be correlated. Secondly, we can record two scripts and compare them. We can look up the difference file to see for the values which needed to be correlated. In my project, there was a unique id developed for each customer, it was nothing but Insurance Number, it was generated automatically and it was sequential and this value was unique. I had to correlate this value, in order to avoid errors while running my script. I did using scan for correlation.
    15. Where do you set automatic correlation options?
            - Automatic correlation from web point of view can be set in recording options and correlation tab. Here we can enable correlation for the entire script. and choose either issue online messages or offline actions, where we can define rules for that correlation. Automatic correlation for database can be done using show output window and scan for correlation and picking the correlate query tab and choose which query value we want to correlate. If we know the specific value to be correlated, we just do create correlation for the value and specify how the value to be created.
    16. What is a function to capture dynamic values in the web Vuser script?
            - Web_reg_save_param function saves dynamic data information to a parameter.
    17. When do you disable log in Virtual User Generator, When do you choose standard and extended logs?
            - Once we debug our script. and verify that it is functional, we can enable logging for errors only. When we add a script. to a scenario, logging is automatically disabled. Standard Log Option: When you selectStandard log, it creates a standard log of functions and messages sent during script. execution to use for debugging. Disable this option for large load testing scenarios. When you copy a script. to a scenario, logging is automatically disabled Extended Log Option: Selectextended log to create an extended log, including warnings and other messages. Disable this option for large load testing scenarios. When you copy a script. to a scenario, logging is automatically disabled. We can specify which additional information should be added to the extended log using the Extended log options.
    18. How do you debug a LoadRunner script?
            - VuGen contains two options to help debug Vuser scripts-the Run Step by Step command and breakpoints. The Debug settings in the Options dialog box allow us to determine the extent of the trace to be performed during scenario execution. The debug information is written to the Output window. We can manually set the message class within your script. using the lr_set_debug_message function. This is useful if we want to receive debug information about a small section of the script. only.
    19. How do you write user defined functions in LR?
            Give me few functions you wrote in your previous project? - Before we create the User Defined functions we need to create the external library (DLL) with the function. We add this library to VuGen bin directory. Once the library is added then we assign user defined function as a parameter. The function should have the following format: __declspec (dllexport) char* (char*, char*)Examples of user defined functions are as follows:GetVersion, GetCurrentTime, GetPltform. are some of the user defined functions used in my earlier project.
    20. What are the changes you can make in run-time settings?
            - The Run Time Settings that we make are: a) Pacing - It has iteration count. b) Log - Under this we have Disable Logging Standard Log and c) Extended Think Time - In think time we have two options like Ignore think time and Replay think time. d) General - Under general tab we can set the vusers as process or as multithreading and whether each step as a transaction.
    21. Where do you set Iteration for Vuser testing?
            - We set Iterations in the Run Time Settings of the VuGen. The navigation for this is Run time settings, Pacing tab, set number of iterations.
    22. How do you perform. functional testing under load?
            - Functionality under load can be tested by running several Vusers concurrently. By increasing the amount of Vusers, we can determine how much load the server can sustain.
    23. What is Ramp up? How do you set this?
            - This option is used to gradually increase the amount of Vusers/load on the server. An initial value is set and a value to wait between intervals can bespecified. To set Ramp Up, go to ‘Scenario Scheduling Options’
    24. What is the advantage of running the Vuser as thread?
            - VuGen provides the facility to use multithreading. This enables more Vusers to be run per generator. If the Vuser is run as a process, the same driver program is loaded into memory for each Vuser, thus taking up a large amount of memory. This limits the number of Vusers that can be run on a single generator. If the Vuser is run as a thread, only one instance of the driver program is loaded into memory for the given number of Vusers (say 100). Each thread shares the memory of the parent driver program, thus enabling more Vusers to be run per generator.
    25. If you want to stop the execution of your script. on error, how do you do that?
            - The lr_abort function aborts the execution of a Vuser script. It instructs the Vuser to stop executing the Actions section, execute the vuser_end section and end the execution. This function is useful when you need to manually abort a script. execution as a result of a specific error condition. When you end a script. using this function, the Vuser is assigned the status “Stopped”. For this to take effect, we have to first uncheck the “Continue on error” option in Run-Time Settings.
    26. What is the relation between Response Time and Throughput?
            - The Throughput graph shows the amount of data in bytes that the Vusers received from the server in a second. When we compare this with the transaction response time, we will notice that as throughput decreased, the response time also decreased. Similarly, the peak throughput and highest response time would occur approximately at the same time.
    27. Explain the Configuration of your systems?
            - The configuration of our systems refers to that of the client machines on which we run the Vusers. The configuration of any client machine includes its hardware settings, memory, operating system, software applications, development tools, etc. This system component configuration should match with the overall system configuration that would include the network infrastructure, the web server, the database server, and any other components that go with this larger system so as to achieve the load testing objectives.
    28. How do you identify the performance bottlenecks?
            - Performance Bottlenecks can be detected by using monitors. These monitors might be application server monitors, web server monitors, database server monitors and network monitors. They help in finding out the troubled area in our scenario which causes increased response time. The measurements made are usually performance response time, throughput, hits/sec, network delay graphs, etc.
    29. If web server, database and Network are all fine where could be the problem?
            - The problem could be in the system itself or in the application server or in the code written for the application.
    30. How did you find web server related issues?
            - Using Web resource monitors we can find the performance of web servers. Using these monitors we can analyze throughput on the web server, number of hits per second that occurred during scenario, the number of http responses per second, the number of downloaded pages per second.
    31. How did you find database related issues?
            - By running “Database” monitor and help of “Data Resource Graph” we can find database related issues. E.g. You can specify the resource you want to measure on before running the controller and than you can see database related issues
    32. Explain all the web recording options?
    33. What is the difference between Overlay graph and Correlate graph?
            - Overlay Graph: It overlay the content of two graphs that shares a common x-axis. Left Y-axis on the merged graph show’s the current graph’s value & Right Y-axis show the value of Y-axis of the graph that was merged. Correlate Graph: Plot the Y-axis of two graphs against each other. The active graph’s Y-axis becomes X-axis of merged graph. Y-axis of the graph that was merged becomes merged graph’s Y-axis.
    34. How did you plan the Load? What are the Criteria?
            - Load test is planned to decide the number of users, what kind of machines we are going to use and from where they are run. It is based on 2 important documents, Task Distribution Diagram and Transaction profile. Task Distribution Diagram gives us the information on number of users for a particular transaction and the time of the load. The peak usage and off-usage are decided from this Diagram. Transaction profile gives us the information about the transactions name and their priority levels with regard to the scenario we are deciding.
    35. What does vuser_init action contain?
            - Vuser_init action contains procedures to login to a server.
    36. What does vuser_end action contain?
            - Vuser_end section contains log off procedures.
    37. What is think time? How do you change the threshold?
            - Think time is the time that a real user waits between actions. Example: When a user receives data from a server, the user may wait several seconds to review the data before responding. This delay is known as the think time. Changing the Threshold: Threshold level is the level below which the recorded think time will be ignored. The default value is five (5) seconds. We can change the think time threshold in the Recording options of the Vugen.
    38. What is the difference between standard log and extended log?
            - The standard log sends a subset of functions and messages sent during script. execution to a log. The subset depends on the Vuser type Extended log sends a detailed script. execution messages to the output log. This is mainly used during debugging when we want information about: Parameter substitution. Data returned by the server. Advanced trace.
    39. Explain the following functions:
            - lr_debug_message - The lr_debug_message function sends a debug message to the output log when the specified message class is set. lr_output_message - The lr_output_message function sends notifications to the Controller Output window and the Vuser log file. lr_error_message - The lr_error_message function sends an error message to the LoadRunner Output window. lrd_stmt - The lrd_stmt function associates a character string (usually a SQL statement) with a cursor. This function sets a SQL statement to be processed. lrd_fetch - The lrd_fetch function fetches the next row from the result set.
    40. Throughput
            - If the throughput scales upward as time progresses and the number of Vusers increase, this indicates that the bandwidth is sufficient. If the graph were to remain relatively flat as the number of Vusers increased, it would be reasonable to conclude that the bandwidth is constraining the volume of data delivered.
    41. Types of Goals in Goal-Oriented Scenario
            - Load Runner provides you with five different types of goals in a goal oriented scenario:
                * The number of concurrent Vusers
                * The number of hits per second
                * The number of transactions per second
                * The number of pages per minute
                * The transaction response time that you want your scenario
    42. Analysis Scenario (Bottlenecks):
            In Running Vuser graph correlated with the response time graph you can see that as the number of Vusers increases, the average response time of the check itinerary transaction very gradually increases. In other words, the average response time steadily increases as the load increases. At 56 Vusers, there is a sudden, sharp increase in the average response time. We say that the test broke the server. That is the mean time before failure (MTBF). The response time clearly began to degrade when there were more than 56 Vusers running simultaneously.
    43. What is correlation?
            Explain the difference between automatic correlation and manual correlation? - Correlation is used to obtain data which are unique for each run of the script. and which are generated by nested queries. Correlation provides the value to avoid errors arising out of duplicate values and also optimizing the code (to avoid nested queries). Automatic correlation is where we set some rules for correlation. It can be application server specific. Here values are replaced by data which are created by these rules. In manual correlation, the value we want to correlate is scanned and create correlation is used to correlate.
    44. Where do you set automatic correlation options?
            - Automatic correlation from web point of view, can be set in recording options and correlation tab. Here we can enable correlation for the entire script. and choose either issue online messages or offline actions, where we can define rules for that correlation. Automatic correlation for database, can be done using show output window and scan for correlation and picking the correlate query tab and choose which query value we want to correlate. If we know the specific value to be correlated, we just do create correlation for the value and specify how the value to be created.
    45. What is a function to capture dynamic values in the web vuser script?
            - Web_reg_save_param function saves dynamic data information to a parameter.


    ============================================================================================================================================

  • 性能测试从零开始--读书笔记(转载)

    2010-09-01 11:40:19

    author: selfimpr

    blog: http://blog.csdn.net/lgg201

    mail: lgg860911@yahoo.com.cn

    感谢51testing 的柳胜前辈精彩的讲解

    以下是我的读书笔记, 在公司是程序员, 工作需要, 简单学习一下, 分享出来, 不足之处, 请邮件指点, 谢谢.

    Vuser 脚本语言基础
    1 脚本结构 :

    1.1 vuser_init: 脚本初始化操作 , 一般放置登录操作 , 分配内存等 , 在播放 vuser_init 时 , Controller 的 Vuser 状态区域会显示 initialize 状态

    1.2 Action: 虚拟用户要做的业务操作 .

    1.3 vuser_end: 与 vuser_init 对应 , 做收尾工作 .

    2 脚本中使用的三种函数

    2.1 VU 通用函数 : lr_ 系列函数

    2.2 协议相关函数 : 一般以协议名开头 , 比如 web 协议就是 web_ 系列

    2.3 语言相关函数 : 由 VU 脚本的生成语言决定 . 多用于用户自定义函数进行脚本扩展 .

    3 以 C 语言的 VU 脚本为例 , 实际上是隐式的存在 main 函数的 , 然后在 main 中去依次调用了 vuser_init, Action, vuser_end 几个函数 .

    4 录制 HTTP 协议的 web 系统测试脚本时 , 会生成一个 globals.h 文件 , 这个文件用来负责 vuser_init, Action, vuser_end 三个脚本都可用的全局变量的声明 .

    5 lr_whoami(*userid, char **groupname, int *sceneid) 可以用来获取当前运行 vuser 的 vuserid, 组名 , 场景 id, 在动态参数化的时候 , 可以使用这些值来构建动态参数 .

    6 自定义函数 :

    6.1 直接引用 : 以 C 语言产生的脚本 , 可以直接在 Action 外部定义函数 , 然后在 Action 内使用 .

    6.2 本地加载 : 使用 lr_load_dll(char *dll_file_name); 加载动态链接库 , 然后调用库中的函数 .

    6.3 include 模式 : 把多个函数写在一个文件中 , 在 vuser_init, Action, vuser_end 中的 include 并调用

    6.4 全局加载 (dll) 模式 : 在 LoadRunnder/data 目录下的 mdrv.dat 文件中 , 查找对应协议 , 然后在下面按照已有内容格式配置链接库即可

    7 通用 vu 函数 : 构建在 C 语言基础上的脚本框架函数 , 以 lr 开头 , 分为以下几类

    7.1 事务和事务控制函数 :

    7.1.1 lr_end_sub_transaction: 标记子事务的结束以便进行性能分析

    7.1.2 lr_end_transaction: 标记 LoadRunner 事务的结束

    7.1.3 lr_end_transaction_instance: 标记事务实例的结束以便进行性能分析

    7.1.4 lr_fail_trans_with_error: 打开事务的状态设置为 LR_FAIL 并发送错误消息 .

    7.1.5 lr_get_trans_instance_duration: 获取事务实例的持续时间

    7.1.6 lr_get_trans_instance_wasted_time: 获取事务实例浪费的时间

    7.1.7 lr_get_transaction_duration: 获取事务的持续事件 ( 按事务名称 )

    7.1.8 lr_get_transaction_think_time: 获取事务的思考时间 ( 按事务名称 )

    7.1.9 lr_get_transaction_wasted_time: 获取事务浪费的时间 ( 按事务的名称 )

    7.1.10 lr_resume_transaction: 继续收集事务数据以便进行性能分析

    7.1.11 lr_resume_transaction_instance: 继续收集事务实例数据以便进行性能分析

    7.1.12 lr_set_transaction_instance_status: 设置事务实例的状态

    7.1.13 lr_set_transaction_status: 设置打开事务的状态

    7.1.14 lr_set_transaction_status_by_name: 设置事务的状态

    7.1.15 lr_start_sub_transaction: 标记子事务的开始

    7.1.16 lr_start_transaction: 标记事务的开始

    7.1.17 lr_start_transaction_instance: 启动嵌套事务 ( 由它的父事务的句柄指定 )

    7.1.18 lr_stop_transaction: 停止事务数据的收集

    7.1.19 lr_stop_transaction_instance: 停止事务实例的数据收集

    7.1.20 lr_wasted_time: 消除所有打开事务浪费的时间 .

    7.2 命令行分析函数 : 当 LoadRunner 以命令行方式启动和运行时 , 以下函数用来分析命令行

    7.2.1 lr_get_attrib_double: 检索脚本命令行中使用的 double 类型变量

    7.2.2 lr_get_attrib_long: 检索脚本命令行中使用的 long 行变量

    7.2.3 lr_get_attrib_string: 检索脚本命令行中使用的字符串

    7.3 系统信息函数 : 获取 VU 的系统信息

    7.3.1 lr_user_data_point: 记录用户定义的数据采集点

    7.3.2 lr_whoami: 将有关 vuser 的信息返回给 vuser 脚本

    7.3.3 lr_get_host_name: 返回执行 vuser 脚本的主机名

    7.3.4 lr_get_master_host_name: 返回运行 LoadRunner Controller 的计算机名

    7.4 字符串函数 :

    7.4.1 lr_eval_string: 返回参数的当前值

    7.4.2 lr_save_string: 将以 NULL 结尾的字符串保存到参数中

    7.4.3 lr_save_var: 将变长字符串保存到参数中

    7.4.4 lr_save_datetime: 将当前日期和时间保存到参数中

    7.4.5 lr_advance_param: 前进到下一个可用参数

    7.4.6 lr_decrypt: 解密已编码的字符串

    7.4.7 lr_eval_string_ext: lr_eval_string 的扩展 , 为指向包含参数数据的缓冲区的指针

    7.4.8 lr_eval_string_ext_free: 释放由 lr_eval_string_ext 分配的指针

    7.4.9 lr_save_searched_string: 在缓冲区中搜索字符串实例 , 并将该字符串实例保存到参数中 .

    7.5 消息函数 :

    7.5.1 lr_debug_message: 将调试信息发送到输出窗口

    7.5.2 lr_error_message: 将错误消息发送到输出窗口

    7.5.3 lr_get_debug_message: 得到当前的消息类

    7.5.4 lr_log_message: 将输出消息直接发送到 output.txt 文件 , 此文件位于 vuser 脚本目录

    7.5.5 lr_output_message: 将消息发送到输出窗口中

    7.5.6 lr_set_debug_message: 为输出消息设置消息类

    7.5.7 lr_vuser_status_message: 生成格式化输出并将其打印到 Controller Vuser 状态区域

    7.5.8 lr_message: 将消息发送到 vuser 日志和输出窗口 .

    7.6 运行时函数 :

    7.6.1 lr_load_dll: 加载外部 dll

    7.6.2 lr_think_time: 暂停脚本的执行 , 以模拟思考时间

    7.6.3 lr_continue_on_error: 指定脚本如何处理错误场景 , 是继续还是退出

    7.6.4 lr_rendezvous: 在 vuser 脚本中设置集合点

    8 HTTP 协议函数 :

    8.1 HTTP 协议 :

    8.1.1 header 设置 :

    8.1.1.1 web_add_header

    8.1.1.2 web_clean_heander

    8.1.2 点击链接 :

    8.1.2.1 web_link( 文字链接 )

    8.1.2.2 web_image( 点击图片链接 )

    8.1.3 提交表单 :

    8.1.3.1 web_submit_data

    8.1.3.2 web_submit_form.

    8.2 web 系统设置

    8.2.1 cache 设置 :

    8.2.1.1 web_cache_leanup

    8.2.1.2 web_load_cache

    8.2.2 cookie 设置

    8.2.2.1 web_add_cookie

    8.2.2.2 web_cleanup_cookies

    8.2.3 proxy 设置

    8.2.3.1 web_set_proxy

    8.2.3.2 web_set_secure_proxy

    8.3 LoadRunner 框架支持

    8.3.1 检查点 :

    8.3.1.1 web_find

    8.3.1.2 web_image_check

    8.3.2 关联

    8.3.2.1 web_create_html_param

    8.3.2.2 web_create_html_param_ex

    8.3.2.3 web_reg_save_param

    8.3.2.4 web_set_max_html_param_len

    8.3.3 控制

    8.3.3.1 lr_start_transaction

    8.3.3.2 lr_rendezvous

    8.3.3.3 lr_think_time

    用户行为模拟器 —VUSER
    1 录制 HTTP 协议的脚本时 , 录制方式的选择原则 :

    1.1 基于浏览器的应用程序使用 HTML-basedScript.

    1.2 不是浏览器的应用使用 URL-based Script.

    1.3 如果基于浏览器的应用程序中包含了 Javascript. 并且该脚本向服务器产生了请求 , 比如 DataGrid 的分页按钮等 , 也要使用 URL-based 方式录制

    1.4 给予浏览器的应用程序中使用了 HTTPS 安全协议 , 使用 URL-based 方式录制 .

    2 几种有用的日志 : 脚本能够正常运行后 , 应当禁用日志以降低消耗 .

    2.1 执行日志 :

    2.1.1 脚本运行时产生 .

    2.1.2 描述 Vuser 运行时执行的操作

    2.1.3 黑色表示标准输出消息 , 红色表示标准错误消息 , 绿色用引号括起来的文字字符串 ( 例如 URL), 蓝色表示事务信息 ( 开始 , 结束 , 状态 , 持续时间 );

    2.2 录制日志 : 在脚本录制过程中产生 , 详细描述录制过程中客户端与服务器之间的各种交互动作 .

    2.3 产生日志 : 记录了脚本录制的设置 , 网络实践到脚本函数的转换过程 .

    3 Tools/General Options/Display/Show browser during replay 选中后可以在 VU 运行时查看浏览器活动 , 不过这只是一个不完整的解释器而不是浏览器 , 因此一些脚本可能会加载不完全 . 打开运行时查看器后在运行脚本时就会实时播放动作 .

    4 关联 : 对于一些请求 , 需要以前面某次请求服务器响应的数据去作为请求参数 , 因此 , 不能把这些数据硬编码 , 而是以参数的方式提供 , 同样 , 要使用的前面某次请求响应的数据也要写入到变量中以便使用 .

    5 录制前自动关联 : 在录制脚本之前 , 已知寻找需要关联数据和关联的规则 , 就可以通过为 VU 设置规则来让其自动关联 .

    5.1 内建关联规则 : 对于一些常用系统 , VU 有内建的关联规则 , 通过 Recording Options/HTTP Properties/Correlation 中启用关联规则 , 然后选择相应的关联规则 , 则在录制对应的系统时 , 就会自动建立关联 .

    5.2 自定义关联规则 : Recording Options/HTTP Properties/Correlation 中建立新的关联规则 ( 也需要启用关联 )

    6 录制后自动关联 : 录制完成后 , 脚本至少需要执行一次 , 在执行中 , 录制后关联会试图找出录制时和执行时服务器响应内容的差异部分 , 藉以找出需要关联的数据并建立关联 .

    7 手动关联 :

    7.1 找出需要关联的数据

    7.1.1 使用相同的业务流程和数据 , 录制两份脚本

    7.1.2 使用 WinDiff 工具找出不同点 : Tools/Compare with Vuser

    7.2 使用 web_reg_save_param 函数手动建立关联

    7.3 web_reg_save_param 函数放在要检查内容的请求之前

    7.4 原理 : 捕获第一个操作的输出   à 保存为参数   à   将参数作为另一个操作的输入

    8 关联的用户和意义 :

    8.1 简化和优化脚本代码

    8.2 动态生成数据 : session 等服务器端返回数据的利用

    8.3 支持唯一数据

    9 除了显式的以 lr_start_transaction 控制事务外 , 还可以在 vuser 的运行时设置中的 miscellaneous 选项中定义自动事务 .

    10 集合点 ( 同步点 ): 为了模拟较重的用户负载 , 需要模拟多个 vuser 同时向服务器发送请求 , 此时 , 就可以在 vuser 脚本中通过 lr_rendezvous 来创建集合点 , Controller 在遇到集合点时会暂停脚本 , 等待其他 vuser 到达后 , 一起释放 vuser 运行 .  需要注意的是只能在 action 中添加集合点 , 而不能在 vuser_init 和 vuser_end 中创建 .

    11 思考时间 : 为了模拟用户在操作过程中的停顿 , 可以用 lr_think_time 来设置思考时间 , 思考时间的单位是秒 . 有时测试不需要思考时间 , 这时就可以通过 Run-time Settings/Think time 中设置忽略思考时间 .

    12 由于集合点和思考时间在 Controller 运行中都会产生等待 , 因此如果在事务中有这两项操作 , 就可能会对事务的响应时间产生影响导致结果不准确 .

    13 参数化的过程 :

    13.1 在脚本中用参数取代常量值

    13.2 设置参数的属性以及数据源 .

    14 参数数据源类型 : 参数的信息在脚本目录下的 ” 脚本名 .prm” 文件中

    14.1 Data Files: 数据保存在文件中

    14.2 User-Defined Functions: 调用外部 dll 函数生成数据

    14.3 Internal Data: 虚拟用户内部产生的数据

    14.3.1 Date/Time: 用当前日期 / 时间替换参数 , 需要指定 Date/Time 格式 .

    14.3.2 Group Name: 用虚拟用户组名称替换参数

    14.3.3 Load Generator Name: 用脚本负载生成器的名称替换参数 , 负载生成器是虚拟用户在运行的计算机

    14.3.4 Iteration Number: 用当前迭代数目替换参数

    14.3.5 Random Number: 用一个随机数替换参数

    14.3.6 Unique Number: 用一个唯一的数字来替换参数 .

    14.3.7 Vuser Id: 用运行时分配给 Vuser 的 id 替换参数

    15 Tools/General Options/Parameterization 可以定义参数的括号类型 .

    16 直接的参数化 , 只有在其作为函数参数时才能够使用 , 而且 , 有些函数的有些参数是不能被参数化的 , 在这种情况下 , 如果想要参数化 , 可以使用 lr_eval_string() 来代替要参数化的内容 , 而我们去参数化 lr_eval_string() 的参数 .

    17 由于 lr_eval_string 返回的是一个指向参数值的指针 , 内容在每次 Iteration 后自动释放 , 因此 , 对于一个大的 Iteration, 如果使用 lr_eval_string 做参数化可能导致内存迟迟不能释放 , 此时可以使用 lr_eval_string_ext 和 lr_eval_string_ext_free 配对使用来自己做清理工作 .

    18 Vuser/Parameter List 中可以统一管理当前脚本中所有参数的属性 .

    19 参数的 update value on 意义

    19.1 each occurrence: 每发生一次换一个

    19.2 each iteration: 每次迭代换一个

    19.3 once: 所有循环中都使用同一个值

    20 参数的 when out of values 的意义

    20.1 Abort Vuser: 中止

    20.2 Continue in a cyclick manner: 继续循环取值

    20.3 Continue with last value: 取最后一个值

    21 从数据库导入参数

    21.1 利用 Microsoft Query 从已存在的数据库中导入参数数据 (Microsoft Query 是 Office 的套件之一 , 没有安装开始菜单中的快捷方式 , 可以在 Office 安装目录下找 MSQRY32.EXE, 如果没有 , 可能是安装 Office 时没有安装 , 运行安装程序添加组件即可 )

    21.2 指定数据库连接或 SQL: 在设置参数的界面如下顺序操作

    21.2.1 点击 Data wizard

    21.2.2 选择 Specify SQL statement manually

    21.2.3 Creat

    21.2.4 新建数据源 , 导入数据即可

    22 检查点 : 对于 web 应用 , vuser 中的请求执行成功并不能代表业务流程是成功的 , 比如用户名密码错误也会返回 200 响应 , 所以 , 需要检查服务器的响应内容来判断业务流程是否执行成功 , 这个判断的点就是检查点 .

    22.1 全局检查点 : 运行时设置中设置 ContentCheck, 这种检查点对于有统一出错处理页面的系统是有效的 .

    22.2 检查函数 : 在一个请求完成后 , 运行检查函数 , 然后作出期望的处理返回 .

    22.2.1 web_find: 检查文本

    22.2.2 web_image_check: 检查图片

    22.2.3 web_reg_find: 与 web_find 类似 , 不过 , 这个函数是先注册 ( 在请求之前 ), 然后查找 , 并且 , 这个函数可以查找多次 , 通过 SaveCount 保存查找到的次数 .  另外 , 通过运行时设置设置的 enable image and text check 对 web_find 有效 , 而对 web_reg_find 无效 , 即 web_reg_find 只要写了就会查找 .

    23 Action/Import Action into vuser 可以将其他 Action 引入进来

    24 在 Run-time settings 中可以设置脚本的全局错误处理机制 ( 是否继续执行 ), 但是 , 对于某些特殊段的脚本如果期望得到特殊的效果 , 可以通过 lr_continue_on_error 函数来控制 , 该函数接受参数 0 或 1, 0 表示以下代码在发生错误时退出 , 反之则继续执行 .

    25 动态运行 : Tools/General Options/Replay 中设置动态运行的延时 , 然后在 view 菜单内选择 Animated run 即可以进入动态运行状态 , 此时运行脚本每运行一句都会暂停设定的毫秒数 .

    26 扩展日志选项的意义 :

    26.1 参数替换 : 记录指定给脚本的所有参数及其相应的值

    26.2 服务器返回的数据 : 记录服务器返回的所有数据

    26.3 高级跟踪 : 记录 vuser 在会话期间发送的所有函数和消息 .

    27 由于扩展日志内容较大 , 因此可以选择性的开启 , 以自定义函数方式 , 调用处理时同错误处理一样 .

    void ud_log_extend(int switch) {

             lr_set_debug_message(LR_MSG_CLASS_EXTENDED_LOG, switch); // 设置扩展日志

             lr_set_debug_message(LR_MSG_CLASS_PARAMETERS_LOG, switch); // 设置参数替换日志

             lr_set_debug_message(LR_MSG_CLASS_RESULT_LOG, switch); // 设置服务器返回数据日志

             lr_set_debug_message(LR_MSG_CLASS_FULL_LOG, switch); // 设置高级跟踪日志

    }

    Action_test{

             ud_log_extend(1); /* 开启扩展日志 */

             web_link(“test”, “Text=test”, LAST);

             ud_log_extend(0); /* 关闭扩展日志 */

             return 0;

    }

    28 验证测试脚本的通常流程 :

    28.1 录制或开发脚本

    28.2 单用户单迭代 : 解决可能存在的关联问题

    28.3 单用户多迭代 : 验证参数化问题

    28.4 多用户单迭代 : 验证可能存在的多线程问题

    28.5 多用户多线程 : 实际就是真正的性能测试开始 .

    29 Tools/Create Controller Scenario 根据当前脚本创建场景

    性能测试指挥中心 —Controller
    1 手工场景 : 负载测试通常使用手工场景 , 首先设置虚拟用户数目 , 脚本 , 以及它们运行的方式 , 然后运行得出服务器的响应时间等指标 .

    2 面向目标的场景 : 首先定义测试要达到的目标 , 然后 LoadRunner 自动基于这些目标创建场景 , 运行过程中 , 不断把结果和目标相比较决定下一步走向 .

    3 虚拟用户组 : 一组用户指的就是针对同一个脚本的多个虚拟用户 , 在同一个场景中 , 可以用多个用户组使用同一个脚本 .

    4 集合点 ( 同步点 ): 如果当前场景中的脚本中包含集合点 (rendezvous), 那么可以通过 Scenario/Rendezvous 打开集合点信息面板来设置集合点信息

    4.1 点击 Policy 按钮 : 这里设置集合点的策略 . 三个 Release 选项用来设置释放集合点的策略 , timeout 表明第一个 vuser 等待一定时间后就不再等待 , 释放等待用户 , 继续执行场景 .

    5 负载生成器 : 网内安装了负载生成器的机器都可以被同一个 Controller 控制用来生成负载 .

    6 在 Controller 中可以对 vuser 组进行运行时设置 , 这里可以设置网络带宽来模拟真实的情况 .

    7 在 schedule( 调度栏 ) 内可以设置 vuser 加载及卸载的方式等调度策略 .

    8 Scenario/Convert scenario to the percentage mode 可以将场景转换为百分比模式 . 百分比模式的场景只是对场景内的 vuser group 中的 vuser 数量进行了百分比分配

    9 面向场景的目标类型 : 一次只能设置一个目标 .

    9.1 virtual users: 虚拟用户数量 , 如果测试服务器的并发处理能力 , 使用这个目标 .

    9.2 hits per second: 每秒点击数 , 测试 web 的真正响应处理能力 .

    9.3 transaction per second: 每秒事务数 , 这种目标需要选择事务名 .transaction response time: 事务响应时间 , 需要选择事务名 , 测试 web 的真正响应处理能力 .

    9.4 pages per minute: 每分钟页面响应数

    10 Controller 的加载策略 :

    10.1 在使用 pages per minute, hits/transaction per second 这几种目标时 , 加载时首先用最小用户数除以定义的目标 , 得到一个值 , 然后确定每个用户应该达到的数据 , 然后 Controller 开始按照以下策略加载用户 :

    10.1.1 如果选择的是自动加载 vuser, controller 会首先记载 50 个 vuser, 如果定义的最大用户数小于 50, 会一次加载所有的 vuser.

    10.1.2 如果选择的是在场景运行一段时间后达到目标 , LoadRunner 会尝试在定义的这段时间内达到目标 , 根据时间限制和计算出的单用户数据确定第一批加载多少 vuser.

    10.1.3 如果选择的是按照一定的阶段达到目标 ( 也就是 x 长时间内达到 y 数据 , 然后达到下一目标 ), LoadRunner 计算每个用户应该达到的数字后 , 再确定第一批加载多少用户 .

    10.2 每加载一批用户 , LoadRunner 会判断是否达到这批用户的目标 , 如果这批用户目标没有达到 , LoadRunner 重新计算每一个用户应该达到的目标数字后 , 重新调整下一批加载用户数量 .

    10.3 如果 Controller 加载了最多数量的用户还没有达到预订目标 , 会重新计算每个用户的目标 , 然后同时运行最大数量的用户 , 尝试达到预订目标

    10.4 如果出现以下情况 , pages per minute, hits/transaction per second 三种类型的面向目标场景会置于 ”Failed” 状态 :

    10.4.1 Controller 使用了指定的最大数量用户 , 并且两次都没有达到目标

    10.4.2 所有的用户运行都失败

    10.4.3 没有足够的 LoadGenerator 机器

    10.4.4 Controller 增加了几批用户后 , pages per minute, hits/transaction per second 数据没有增加 .

    11 IP 欺骗设置 : 应对某些服务器要求不允许单 IP 多登的测试 .

    11.1 在负载生成器机器上 ( 必须使用固定 IP), “Windows 开始 ”/LoadRunner/Tools/Ip wizard 打开 IP 向导 , 根据向导配置 IP 列表 .

    11.2 在 Controller 中 , Scenario/Enable IP spoofer 打开 IP 欺骗

    12 场景的运行时控制

    12.1 场景开始运行后 , 可以通过 stop 按钮停止 , 但是停止的方式需要在运行之前通过 Tools/Options/Run-time settings 中设置好

    12.2 场景开始运行后的 reset 按钮用来将方案中的所有 vuser 组重置为其方案前的关闭状态

    12.3 Vusers 用来查看 vuser 组内每个 vuser 的详细状态

    12.4 Run/Stop Vusers 打开 ” 运行 / 停止 vuser” 对话框 , 在场景运行时决定是继续执行还是停止某个用户组 .

    12.5 运行时释放集合点用户 : Scenario/Rendezvous 然后选定用户 disable vuser

    13 如果系统提供的数据采集点不能满足需求 , 可以在脚本中用 lr_user_data_point 自定义数据采集点 .

    14 判断磁盘瓶颈的方法 : 每磁盘 I/O 数 = [ 读次数 +(4* 写次数 )]/ 磁盘个数 , 如果每磁盘的 I/O 数大于磁盘的处理能力 , 那么磁盘存在瓶颈 .

    寻找系统瓶颈的得力助手 —Analysis
    1 Analysis 功能 :

    1.1 Analysis 图有助于确定系统性能瓶颈 .

    1.2 “ 图数据 ” 视图和 ” 原始数据 ” 视图以电子表格格式显示用于生成图的实际数据 .

    1.3 “ 报告 ” 功能可以使用户查看每个图的摘要 , HTML 报告或各种性能和活动报告 .

    2 摘要报告 (summary):

    2.1 Analysis summary( 统计摘要 ):

    2.1.1 Maximum Running vusers: 最大同时运行用户数

    2.1.2 Total Throughput(bytes): 吞吐量

    2.1.3 Average Thoughput(bytes/second): 吞吐率

    2.1.4 Total Hits: 总点击数

    2.1.5 Average Hits per Second: 每秒点击数

    2.1.6 View HTTP Responses Summary: 查看 HTTP 响应的摘要

    3 Trasaction summary( 事务摘要 ):

    3.1 Minimum: 事务最小时间

    3.2 Average: 平均事务时间

    3.3 Maximum: 事务最大时间

    3.4 Std.Deviation: 标准方差 . 值越大数据越离散也就说明不稳定 .

    3.5 90 Percent: 90% 的事务消耗的时间 , 通常这个值比总平均时间个更可靠 .

    3.6 Pass/Fail/Stop: 通过 / 失败 / 中途停止的事务数

    4 在 Average Transaction Response Time 图中 , 可以选择某个事务曲线 , 右键 ”Web Page Breakdown for login” 将事务进行分解 , 查看事务过程中每个请求的每一步是怎么样完成的 .

    5 Time to first buffer breakdown(Over Time) 图中可以对比页面响应时间中的服务器时间和网络时间 , 从而分析是网络还是服务器造成的耗时 .

    6 Page Download Time Breakdown(Over Time) 图中可以看出每次请求详细分解的请求时间 ( 包括客户端时间 , 连接时间 , DNS 解析时间 , 错误时间 , 首次缓存时间 , FTP 鉴权时间 , 接收时间 , SSL 处理时间等等 ).

    7 图的合并 :

    7.1 叠加 : 重叠共用一个 x 轴的两个图的内容 , 合并图使用左右两个不同的 y 轴

    7.2 平铺 : 共用同一个 x 轴的数据 , 但显示上上下分离 , 合并图仍然是左右两个不同的 y 轴

    7.3 关联 : 当前图的 y 轴成为合并图的 x 轴 , 被合并图的 y 轴是合并图的 y 轴

    8 可以使用 Reports 生成报告 .

     

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lgg201/archive/2010/08/15/5812928.aspx

  • 跳槽前10件你首先要做的事

    2010-09-01 10:44:17

    转自:http://blog.csdn.net/wzh0439/archive/2009/11/18/4828762.aspx

     

    每个人面对这样抉择时,都会有所顾虑。想要跳槽成功,你必须要思考10件事,只要你头脑冷静、全面分析,结果必将一目了然。

        Step1: 要跳的值得,你必问新东家的5件事

        知名的公司不一定是适合你的公司,最重要的是,你和新工作究竟能不能“气味相投”?破除“下一个会更好”的想象,你需要问清楚,想明白,才不会枉然白走一遭,还赔上自己的生涯。

        1.职位出缺的原因

        面对自己可能接手的职位,应征时得问清楚:“这个位置出缺的原因是什么?”是原来职位的人升职、调配、健康考量等一般原因,还是绩效不佳、人际失和、廉洁操守等负面理由?针对负面信息,你要注意前面的人遭遇的问题,短时间能不能解决?相处不和睦是人的性格,还是职位设计的角色冲突?能力不足是不是老板期望太高,没有下放职权与资源?

        从问答之间的蛛丝马迹,就可以知道这个职位与自己的人格特征、能力是否相符。

        一定要花点时间打听最为保险,探询对象从猎头公司、员工到上下游合作厂商都会是正确消息的来源。

        2.企业文化和制度

        必须弄清楚跳槽对象的企业文化,是充分授权,还是高压集权;是家族色彩浓厚,还是走向专业治理?一旦得知新公司的管理风格,你得扪心自问,“我的弹性够大吗?我能不能在那样的气氛下,充分发挥所长?”否则过度乐观赴任,最终会落得水土不服、白忙一? ?

        企业文化中有些看似小事,却会严重影响你的工作情绪。加班频率太高、每天打卡分秒计较、办公室不禁烟、开会时老板带头吞云吐雾、经常外出应酬出入声色场所、老板在企业里大谈宗教理念,鼓励员工信教。若你对这些事情特别敏感,一定都要一一问清楚。

        3.薪资条件和报酬

        薪水背后代表的是“需求”与“自尊”,到底你的贡献价值有多少,市场行情如何,劳雇双方的底线在哪里,都是交手的重点。若自己没有很好的谈判技巧,或是想要拉高新酬,不妨透过中间人或猎头代为打理。

        4.对职位的期望

        当你知道职位出缺的原因,下一步便要搞懂老板对这个职位的期待,而且最好“白纸黑字”。有的老板勾画一些虚幻的远景,开了许多空头支票,等到上任后才觉得受骗;也有的老板对你的角色有太多不切实际的期待,没有把游戏规则谈的清楚、具体。在询问当中,应逐一问清公司的方向与问题所在,并适度回应老板可能的解决之道。

        5.相关主管的管理风格

        对中高层求职者来说,最好的做法是:与自己业务相关的主管都要面谈。有的中高层主管只与直属主管或人事聊过,对平行的主管完全不了解,跨部门合作时,才会因沟通不良,惊觉问题所在。有的则是只跟董事长聊过,这些负责策略思考的大老板,对于改革,多半充满理想,十分容易“感召”人才。等到进去后,却发现真正承担执行重责的总经理,才是决定他未来工作形式的关键人物。

        Step2:避免提前阵亡,到任后你要做的5件事

        进到一个新的组织,你这个阻碍旧有人马升迁的“外人”尽管系出名门,怀有万般武艺,也不一定能安然存活。所以既然决定踏入,就要全心认同这家公司,而且要确实做到以下5点。

        1.快速了解公司与团队定位

        到任后,不要不眠不休尽快进入状况。因为在公司任何一个人眼中,“你已经占了这个位置,领了一天薪水,没理由说你才刚来?

        “大”的是了解整个产业趋势与特性,“中”指的是公司的定位、策略,

        2.主动广结善缘

        对于新上任的人,有人给予厚望,也有人抱持着问号。“第一时间愿意来支援你的不会超过两成,因为大家都在观望。”因此,不妨先向与自己业务相关的同事伸手,向他们请教,并建立起沟通的模式,包括目标与达成目标的标准,找一个团队的共识。

        另外,应把握员工休息活动机会,尽可能的参与。因为离开办公室,大家在谈笑之间,往往卸除心防,可深一层了解彼此,建立私谊。

        3.避免误踩公司的禁忌地雷

        “办公室政治”是新到任者最易误踩的地雷。关于“消息”之说,有时只是谣传,若察觉一些微妙的迹象,显示其真实性,要记得千万别被框?

        4.订立标杆,建立战功

        对于一个新面孔,想在最短时间内站稳,靠的就是如何赢得大家的信任。立下“标杆”与“战功”常常是取得“发言权”的做法。对于资深的人而言,初来乍到,要赢得老板的信任,得尽快做出来半年或1年的计划,订出时间的标杆。当你提出后,老板会告诉你哪些没问题,哪些需要修改,除了达到沟通的目的,还能让老板清楚你未来会有哪些贡献。

        若你不断张扬自己以前的战功,表现却跟上一任没两样,甚至更差,很快就会被看破手脚,甚至打入冷宫。

        5.先小修正,再求大改革

        “新官上任三把火”是表现企图心惯用手法,但却会引来最大的副作用。由于上司对你仍缺乏信任,改革太过急切,等于是对旧有势力的挑衅,反弹力道自然不言而喻。因为老板请来经理人,不是要他在自己好不容易建立的王国里翻上一番,弄成焦土后就闪人,若真要进行改革,也要在倾听员工声音、充分了解组织问题后,与老板取得共识,采取渐进式的做法。若组织改革有空间,在信任与磨合间,订一个长期的修改顺序,才能获得最大的支持与资源。

     

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wzh0439/archive/2009/11/18/4828762.aspx

     

     

     

  • Oracle 10g在Redhat Linux 4上安装笔记

    2010-08-25 16:25:05


    Oracle 10g在Redhat Linux 4上安装笔记


    废言:一直想在linux下学习 oracle,但是一切的开始就是安装,所以,我们踏上征程。。。。。。

    安装前的软件准备:
    1. 10201_database_linux32.zip
    2. RHEL4.8-i386-AS-DVD.iso
    3. VMware Workstation
    4. Xmanager
    5. xshell/SecureCRT/putty

    参考文档:
    1. 视频:牛牛公作品:Oracle 10gR2在Redhat Linux 4上的安装,可惜没有PPT文档
       http://www.boobooke.com/v/bbk4352.zip
       http://www.boobooke.com/v/bbk4353.zip
    2. http://www.oracle.com/technology/global/cn/pub/articles/smiley_10gdb_install.html
    3. Oracle 10g联机文档


    总体步骤:
    第 1 部分: 安装linux操作系统,并安装好必要的依赖包
    1.安装system
    2. install vmware tools:
    3. 修改hosname
    4.修改参数:设置时间同步
    5.修改启动参数,字符界面启动,启动3个用户:
    6.安装依赖的包
    7.安装另外两个需要额外下载的包:
    8.安装sqlplus辅助工具

    第 2 部分:针对 Oracle 配置 Linux
    1.创建 Oracle 组和用户帐户
    2.创建目录
    3.配置 Linux 内核参数
    4.为 oracle 用户设置 Shell 限制
    5.配置oracle的环境变量:
    6. 准备oracle安装文件
    7. 准备Xmanager
    8. 开始安装oracle
    9. 创建数据库
    10. 创建一个 Listener
    11. 创建一个 service
    12. 验证是否安装成功,sqlplus 连接

     

    第 1 部分: 安装linux操作系统,并安装好必要的依赖包

    1.安装system

      网络设置:
       安装的时候设置了固定IP
       但是和公司的网段IP不符。
       故应设置在相同网段(推荐)
       或者设置成自动获取

    1.1 选择语言language:  U.S. English
    1.2 磁盘分区: Manually partition with Disk Druid
    Yes
    创建磁盘分区:

    一般来说建立LINUX 需要三个分区    
    一个挂载点是/BOOT 引导分区格式为EXT2 或者EXT3 大小在150-200MB 为合适太大了只是浪费    
    一个是 格式 SWAP类似WINDOWS 下的虚拟内存建议是 比实际内存大1/4为合适,SWAP 格式的没有挂载点     
    最后一个是挂载点 /      是LINUX 主分区 格式EXT3    这个装东西的话主要就在这个区了   
     顺序是先建立     /BOOT     然后     SWAP     最后 /
     
    具体操作:
    new ---> /boot,ext2,100 MB(Fixed size), 勾选 Force to be a primary partition  ---> OK
    new ---> swap, 1024 MB(Fixed size), 勾选 Force to be a primary partition      ---> OK
    new ---> / ,ext3, 51200 MB(Fixed size), 勾选 Force to be a primary partition  ---> OK
    new ---> /u01,ext3, fill to maximum allowable size, 勾选 Force to be a primary partition      ---> OK

    1.3 Network Devices:
    ---> Edit, 取消 Configure using DHCP
         勾选 Activate on boot
         IP Address: 192.168.1.253
         Netmask:    255.255.255.0
       
        Set the hostname :  manually --- > Redhat
        Gateway : 192.168.1.1
        ---> Next --> Continue

    1.4 firewall:
    No firewall
    SElinux --> Disable   
      
      1.5 Location
    Asia/Shanghai

    1.6 set Root Password: jonathan

    1.7 software --- Customize software packages to be installed

    勾选:Editors
          Development --- Development Tools,legacy software Development
          System --- System Tools---> sysstat

    取消: Servers--- Server Configuration To0ls, Web Server, Windows File Server
           System --- Printing Support
           可以不取消

    安装完毕 ---> Reboot
    1.8 重启后继续配置,创建新用户jonathan/jonathan

     

    2. install vmware tools:
    1)  VM ---> remove devices ---> cd rom ---> redhat
        vm--->install vmware tools
        桌面出现 VMware Tools ---->执行 VMwareTools.rpm
    2)  open new terminal ---> 执行 $vmware-config-tools.pl
    3) 设置时间同步:
       $vmware-toolbox
       勾选上即可
    4) 安装vmware tools后,需要重启网卡
       service network restart


      
    3. 修改hosname
    修改/etc/hosts里面的名字
    # vi /etc/hosts
    127.0.0.1 localhost.localdomain localhost
    yourip yourname //在这修改hostname
    192.168.1.253 redhat

     

    4.修改参数:设置时间同步
    vim /boot/grub/grub.conf
    ------------------
     
    default=0
    timeout=0
    splashimage=(hd0,0)/grub/splash.xpm.gz
    hiddenmenu
    title Red Hat Enterprise Linux Server (2.6.18-8.el5)
     root (hd0,0)
     kernel /vmlinuz-2.6.18-8.el5 ro root=LABEL=/ rhgb quiet clock=pit nosmp noapic nolapic
     initrd /initrd-2.6.18-8.el5.img

     

    5.修改启动参数,字符界面启动,启动3个用户:--- 可以不改
    vi /etc/inittab

    id:3:initdefault:

    # Run gettys in standard runlevels
    1:2345:respawn:/sbin/mingetty tty1
    2:2345:respawn:/sbin/mingetty tty2
    3:2345:respawn:/sbin/mingetty tty3
    #4:2345:respawn:/sbin/mingetty tty4
    #5:2345:respawn:/sbin/mingetty tty5
    #6:2345:respawn:/sbin/mingetty tty6


    6.安装依赖的包

    #查询依赖包:
    rpm -q xorg-x11-deprecated-libs xorg-x11-libs xorg-x11-xfs alsa-lib-devel fontconfig-devel freetype-devel libjpeg-devel libtiff-devel libungif-devel xorg-x11 xorg-x11-deprecated-libs-devel xorg-x11-devel audiofile-devel esound-devel libaio libaio-devel openmotif21 openmotif glib-devel gnome-libs-devel gtk+-devel imlib-devel ORBit-devel compat-libcwait compat-oracle-rhel4 binutils compat-db control-center gcc gcc-c++ glibc glibc-common gnome-libs libstdc++ libstdc++-devel make pdksh sysstat xscreensaver gdk-pixbuf setarch

    rpm -q  xorg-x11-deprecated-libs xorg-x11-libs xorg-x11-xfs alsa-lib-devel \
    fontconfig-devel freetype-devel libjpeg-devel libtiff-devel libungif-devel \
    xorg-x11 xorg-x11-deprecated-libs-devel xorg-x11-devel audiofile-devel \
    esound-devel libaio libaio-devel openmotif21 openmotif glib-devel \
    gnome-libs-devel gtk+-devel imlib-devel ORBit-devel compat-libcwait \
    compat-oracle-rhel4 binutils compat-db control-center gcc gcc-c++ glibc glibc-common \
    gnome-libs libstdc++ libstdc++-devel make pdksh sysstat xscreensaver gdk-pixbuf setarch

    #进入到RHEL的安装光盘的目录下 /media/cdrom/RedHat/RPMS 进行安装

    rpm -ivh alsa-lib-devel-1.0.6-5.RHEL4.i386.rpm fontconfig-devel-2.2.3-13.el4.i386.rpm freetype-devel-2.1.9-8.el4.6.i386.rpm libjpeg-devel-6b-33.i386.rpm libtiff-devel-3.6.1-12.el4_7.2.i386.rpm libungif-devel-4.1.3-1.el4.2.i386.rpm xorg-x11-deprecated-libs-devel-6.8.2-1.EL.63.i386.rpm xorg-x11-devel-6.8.2-1.EL.63.i386.rpm audiofile-devel-0.2.6-1.el4.1.i386.rpm esound-devel-0.2.35-2.i386.rpm libaio-devel-0.3.105-2.i386.rpm glib-devel-1.2.10-15.i386.rpm gnome-libs-devel-1.4.1.2.90-44.1.i386.rpm gtk+-devel-1.2.10-36.i386.rpm imlib-devel-1.9.13-23.i386.rpm ORBit-devel-0.5.17-14.i386.rpm sysstat-5.0.5-25.el4.i386.rpm

    7.安装另外两个需要额外下载的包:
    下载地址:  http://oss.oracle.com/projects/compat-oracle/files/RedHat/
    compat-libcwait-2.1-1.i386.rpm
    compat-oracle-rhel4-1.0-5.i386.rpm

    xftp上传到Linux上:
    chmod +x *
    [root@oracle10g software]# rpm -ivh compat-*
    [root@oracle10g software]# rpm -q compat-libcwait compat-oracle-rhel4


    8.安装sqlplus辅助工具:(解决sqlplus上翻出现乱码的问题)
    http://utopia.knoware.nl/~hlub/uck/rlwrap/

    $chmod -R 777 rlwrap-0.37
    $./configure
    $make
    $make check
    $make install

     

    第 2 部分:针对 Oracle 配置 Linux

     

    1.创建 Oracle 组和用户帐户

    以 root 用户身份执行以下命令:

    $ groupadd oinstall
    $ groupadd dba

    $ mkdir -p /u01/app/oracle/product/10.2.0/db_1

    $ useradd -g oinstall -G dba -d /u01/app/oracle oracle

    ##说明:
    #man useradd
           -g initial_group
                  The group name or number of the user?. initial login group.  The group  name
                  must  exist.   A  group number must refer to an already existing group.  The
                  default group number is 1 or whatever is specified in  /etc/default/useradd.

           -G group,[...]
                  A  list  of  supplementary  groups which the user is also a member of.  Each
                  group is separated from the next by a comma, with no intervening whitespace.
                  The  groups are subject to the same restrictions as the group given with the
                  -g option.  The default is for the user to belong only to the initial group.
                 
    $ id oracle  #查看oracle 用户信息:uid=501(oracle) gid=501(oinstall) groups=501(oinstall),502(dba)
    $ passwd oracle ##设置 oracle 帐户的口令:

    $ chown -R oracle:oinstall /u01
       #oracle:oinstall --- oracle--改变目录的所有者为oracle用户,oinstall---改变目录的所属组为oinstall
    $ chmod -R 775 /u01
    查看:
    [root@oracle10g ~]# ls -l /u01
    drwxr-xr-x  3 oracle oinstall 4096 Aug 25 13:27


    ###########################

    2.创建目录  --- 命令已经在上一步执行。

    ###########################


    3.配置 Linux 内核参数 ([root@oracle10g ~]# find /etc -name sysctl.conf)
    vi /etc/sysctl.conf

    添加如下内容:

    kernel.shmall = 2097152
    kernel.shmmax = 2147483648
    kernel.shmmni = 4096
    kernel.sem = 250 32000 100 128
    fs.file-max = 65536
    net.ipv4.ip_local_port_range = 1024 65000
    net.core.rmem_default = 1048576
    net.core.rmem_max = 1048576
    net.core.wmem_default = 262144
    net.core.wmem_max = 262144


    使内核参数生效:
    # /sbin/sysctl -p

    以 root 用户身份运行以下命令来验证您的设置:

    /sbin/sysctl -a | grep shm
    /sbin/sysctl -a | grep sem
    /sbin/sysctl -a | grep file-max
    /sbin/sysctl -a | grep ip_local_port_range


    ######################################################
     
     
     4.为 oracle 用户设置 Shell 限制
     
     $vi /etc/security/limits.conf
     #添加如下内容:
    oracle               soft    nproc   2047
    oracle               hard    nproc   16384
    oracle               soft    nofile  1024
    oracle               hard    nofile  65536

    $vi /etc/pam.d/login
    session    required     /lib/security/pam_limits.so
    session    required     pam_limits.s

     

    5.配置oracle的环境变量:

    $su oracle
    $cd
    $ls -al
    $vi /u01/oracle/.bash_profile

    export PATH
    unset USERNAME

    export EDITOR=vi
    export ORACLE_SID=ora10g
    export ORACLE_BASE=/u01/app/oracle
    export ORACLE_HOME=/u01/app/oracle/product/10.2.0/db_1
    export PATH=$ORACLE_HOME/bin:$PATH

    alias sqlplus="rlwrap sqlplus"
    alias rman="rlwrap rman"

    #export ORACLE_BASE ORACLE_HOME ORACLE_SID  PATH

    if [ \$USER = "oracle" ]; then 
     if [ \$SHELL = "/bin/ksh" ]; then
      ulimit -p 16384
      ulimit -n 65536
     else
      ulimit -u 16384 -n 65536
     fi
      umask 022
    fi


    $source .bash_profile    #立即生效
    $env                     #查看环境变量


    6. 准备oracle安装文件
    $su root
    上传oracle安装文件,解压缩
    $unzip  o.zip -d ./
    $chown -R oracle:oinstall database
    $mv database /u01/app/oracle/
    #移动安装文件到 oracle目录下

    7. 准备Xmanager
    安装Open Xmanage
    打开 Xstart
    输入
    Session name: myOracle
    Host: yourip
    protocol: SSH
    User Name: oracle
    Password : ***
    Execution Command: 选择:xterm (Linux)

    然后点击save、 run,连接并登陆。

    8. 开始安装oracle
    连接成功后,进入oracle家目录
    $ls
    $cd database
    $./runinstaller
    然后出现熟悉的Oracle 图形安装界面,按照提示进行安装。
    #安装过程中不创建数据库,在后面用dbca命令进行创建。


    需要root用户执行的两个脚本:
    /u01/app/oracle/oraInventory/orainstRoot.sh
    /u01/app/oracle/product/10.2.0/db_1/root.sh

     

    ## 视频教程中的做法,可以不用。
    #使用oracle用户进行安装:
    #su oracle
    #$export DISPLAY=local_host_ip:0.0 ;
    #进入database安装目录下:
    #$./runinstaller
    #使用XManager进行图形界面安装

    #####
    The following J2EE Applications have been deployed and are accessible at the URLs listed below.

    iSQL*Plus URL:
    http://oracle10g:5560/isqlplus

    iSQL*Plus DBA URL:
    http://oracle10g:5560/isqlplus/dba
    #####


    9. #创建数据库
    $dbca


    10. # 创建一个 Listener
    $netca

    11. # 创建一个 service
    $netmgr


    12. #验证是否安装成功,sqlplus 连接:
    $sqlplus
    :/as sysdba
    SQL> select * from dual ;
    SQL> select sysdate from dual ;

     

     

     


     

  • HP大中华区总裁孙振耀退休十五天后九大感言

    2010-08-10 17:37:35

     

    发现自:http://www.51testing.com/?uid-4024-action-viewspace-itemid-218072

    转载自:http://blog.sina.com.cn/s/blog_4a78b4ee010096c8.html

    HP大中华区总裁孙振耀退休十五天后九大感言

    一、关于工作与生活

      我有个有趣的观察,外企公司多的是25-35岁的白领,40岁以上的员工很少,二三十岁的外企员工是意气风发的,但外企公司40岁附近的经理人是很尴尬的。我见过的40岁附近的外企经理人大多在一直跳槽,最后大多跳到民企,比方说,唐骏。外企员工的成功很大程度上是公司的成功,并非个人的成功,西门子的确比国美大,但并不代表西门子中国经理比国美的老板强,甚至可以说差得很远。而进外企的人往往并不能很早理解这一点,把自己的成功90%归功于自己的能力,实际上,外企公司随便换个中国区总经理并不会给业绩带来什么了不起的影响。好了问题来了,当这些经理人40多岁了,他们的薪资要求变得很高,而他们的才能其实又不是那么出众,作为外企公司的老板,你会怎么选择?有的是只要不高薪水的,要出位的精明强干精力冲沛的年轻人,有的是,为什么还要用你?
      从上面这个例子,其实可以看到我们的工作轨迹,二三十岁的时候,生活的压力还比较小,身体还比较好,上面的父母身体还好,下面又没有孩子,不用还房贷,也没有孩子要上大学,当个外企小白领还是很光鲜的,挣得不多也够花了。但是人终归要结婚生子,终归会老,到了40岁,父母老了,要看病要吃药,要有人看护,自己要还房贷,要过基本体面的生活,要养小孩……那个时候需要挣多少钱才够花才重要。所以,看待工作,眼光要放远一点,一时的谁高谁低并不能说明什么。
      从这个角度上来说,我不太赞成过于关注第一份工作的薪水,更没有必要攀比第一份工作的薪水,这在刚刚出校园的学生中间是很常见的。正常人大概要工作35年,这好比是一场马拉松比赛,和真正的马拉松比赛不同的是,这次比赛没有职业选手,每个人都只有一次机会。要知到,有很多人甚至坚持不到终点,大多数人最后是走到终点的,只有少数人是跑过终点的,因此在刚开始的时候,去抢领先的位置并没有太大的意义。刚进社会的时候如果进500强公司,大概能拿到3k-6k/月的工资,有些特别技术的人才可能可以到8k/月,可问题是,5年以后拿多少?估计5k-10k了不起了。起点虽然高,但增幅有限,而且,后面的年轻人追赶的压力越来越大。
      我前两天问我的一个销售,你会的这些东西一个新人2年就都学会了,但新人所要求的薪水却只是你的一半,到时候,你怎么办?
      职业生涯就像一场体育比赛,有初赛、复赛、决赛。初赛的时候大家都刚刚进社会,大多数都是实力一般的人,这时候努力一点认真一点很快就能让人脱颖而出,于是有的人二十多岁做了经理,有的人迟些也终于赢得了初赛,三十多岁成了经理。然后是复赛,能参加复赛的都是赢得初赛的,每个人都有些能耐,在聪明才智上都不成问题,这个时候再想要胜出就不那么容易了,单靠一点点努力和认真还不够,要有很强的坚忍精神,要懂得靠团队的力量,要懂得收服人心,要有长远的眼光……
      看上去赢得复赛并不容易,但,还不是那么难。因为这个世界的规律就是给人一点成功的同时让人骄傲自满,刚刚赢得初赛的人往往不知道自己赢得的仅仅是初赛,有了一点小小的成绩大多数人都会骄傲自满起来,认为自己已经懂得了全部,不需要再努力再学习了,他们会认为之所以不能再进一步已经不是自己的原因了。虽然他们仍然不好对付,但是他们没有耐性,没有容人的度量,更没有清晰长远的目光。就像一只愤怒的斗牛,虽然猛烈,最终是会败的,而赢得复赛的人则象斗牛士一样,不急不躁,跟随着自己的节拍,慢慢耗尽对手的耐心和体力。赢得了复赛以后,大约已经是一位很了不起的职业经理人了,当上了中小公司的总经理,大公司的副总经理,主管着每年几千万乃至几亿的生意。
      最终的决赛来了,说实话我自己都还没有赢得决赛,因此对于决赛的决胜因素也只能凭自己的猜测而已,这个时候的输赢或许就像武侠小说里写得那样,大家都是高手,只能等待对方犯错了,要想轻易击败对手是不可能的,除了使上浑身解数,还需要一点运气和时间。世界的规律依然发挥着作用,赢得复赛的人已经不只是骄傲自满了,他们往往刚愎自用,听不进去别人的话,有些人的脾气变得暴躁,心情变得浮躁,身体变得糟糕,他们最大的敌人就是他们自己,在决赛中要做的只是不被自己击败,等着别人被自己击败。这和体育比赛是一样的,最后高手之间的比赛,就看谁失误少谁就赢得了决赛。

     

      二、 根源

      你工作快乐么?你的工作好么?
      有没有觉得干了一段时间以后工作很不开心?有没有觉得自己入错了行?有没有觉得自己没有得到应有的待遇?有没有觉得工作像一团乱麻每天上班都是一种痛苦?有没有很想换个工作?有没有觉得其实现在的公司并没有当初想象得那么好?有没有觉得这份工作是当初因为生存压力而找的,实在不适合自己?你从工作中得到你想要得到的了么?你每天开心么?
      天涯上愤怒的人很多,你有没有想过,你为什么不快乐?你为什么愤怒?
      其实,你不快乐的根源,是因为你不知道要什么!你不知道要什么,所以你不知道去追求什么,你不知道追求什么,所以你什么也得不到。
      我总觉得,职业生涯首先要关注的是自己,自己想要什么?大多数人大概没想过这个问题,唯一的想法只是——我想要一份工作,我想要一份不错的薪水,我知道所有人对于薪水的渴望,可是,你想每隔几年重来一次找工作的过程么?你想每年都在这种对于工作和薪水的焦急不安中度过么?不想的话,就好好想清楚。饮鸩止渴,不能因为口渴就拼命喝毒药。越是焦急,越是觉得自己需要一份工作,越饥不择食,越想不清楚,越容易失败,你的经历越来越差,下一份工作的人看着你的简历就皱眉头。于是你越喝越渴,越渴越喝,陷入恶性循环。最终只能哀叹世事不公或者生不逢时,只能到天涯上来发泄一把,在失败者的共鸣当中寻求一点心理平衡罢了。大多数人都有生存压力,我也是,有生存压力就会有很多焦虑,积极的人会从焦虑中得到动力,而消极的人则会因为焦虑而迷失方向。所有人都必须在压力下做出选择,这就是世道,你喜欢也罢不喜欢也罢。
      一般我们处理的事情分为重要的事情和紧急的事情,如果不做重要的事情就会常常去做紧急的事情。比如锻炼身体保持健康是重要的事情,而看病则是紧急的事情。如果不锻炼身体保持健康,就会常常为了病痛烦恼。又比如防火是重要的事情,而救火是紧急的事情,如果不注意防火,就要常常救火。找工作也是如此,想好自己究竟要什么是重要的事情,找工作是紧急的事情,如果不想好,就会常常要找工作。往往紧急的事情给人的压力比较大,迫使人们去赶紧做,相对来说重要的事情反而没有那么大的压力,大多数人做事情都是以压力为导向的,压力之下,总觉得非要先做紧急的事情,结果就是永远到处救火,永远没有停歇的时候。(很多人的工作也像是救火队一样忙碌痛苦,也是因为工作中没有做好重要的事情。)那些说自己活在水深火热为了生存顾不上那么多的朋友,今天找工作困难是当初你们没有做重要的事情,是结果不是原因。如果今天你们还是因为急于要找一份工作而不去思考,那么或许将来要继续承受痛苦找工作的结果。
      我始终觉得我要说的话题,沉重了点,需要很多思考,远比唐笑打武警的话题来的枯燥乏味,但是,天下没有轻松的成功,成功,要付代价。请先忘记一切的生存压力,想想这辈子你最想要的是什么?所以,最要紧的事情,先想好自己想要什么。

    三、什么是好工作

      当初微软有个唐骏,很多大学里的年轻人觉得这才是他们向往的职业生涯,我在清华bbs里发的帖子被这些学子们所不屑,那个时候学生们只想出国或者去外企,不过如今看来,我还是对的,唐骏去了盛大,陈天桥创立的盛大,一家民营公司。一个高学历的海归在500强的公司里拿高薪水,这大约是很多年轻人的梦想,问题是,每年毕业的大学生都在做这个梦,好的职位却只有500个。
      人都是要面子的,也是喜欢攀比的,即使在工作上也喜欢攀比,不管那是不是自己想要的。大家认为外企公司很好,可是好在哪里呢?好吧,他们在比较好的写字楼,这是你想要的么?他们出差住比较好的酒店,这是你想要的么?别人会羡慕一份外企公司的工作,这是你想要的么?那一切都是给别人看的,你干吗要活得那么辛苦给别人看?另一方面,他们薪水福利一般,并没有特别了不起,他们的晋升机会比较少,很难做到很高阶的主管,他们虽然厌恶常常加班,却不敢不加班,因为“你不干有得是人干”,大部分情况下会找个台湾人香港人新加坡人来管你,而这些人又往往有些莫名其妙的优越感。你想清楚了么?500强一定好么?找工作究竟是考虑你想要什么,还是考虑别人想看什么?
      我的大学同学们大多数都到美国了,甚至毕业这么多年了,还有人最近到国外去了。出国真的有那么好么?我的大学同学们,大多数还是在博士、博士后、访问学者地挣扎着,至今只有一个正经在一个美国大学里拿到个正式的教职。国内的教授很难当么?我有几个表亲也去了国外了,他们的父母独自在国内,没有人照顾,有好几次人在家里昏倒都没人知道,出国,真的这么光彩么?就像有人说的“很多事情就像看A片,看的人觉得很爽,做的人未必。”
      人总想找到那个最好的,可是,什么是最好的?你觉得是最好的那个,是因为你的确了解,还是因为别人说他是最好的?即使他对于别人是最好的,对于你也一定是最好的么?
      对于自己想要什么,自己要最清楚,别人的意见并不是那么重要。很多人总是常常被别人的意见所影响,亲戚的意见,朋友的意见,同事的意见……问题是,你究竟是要过谁的一生?人的一生不是父母一生的续集,也不是儿女一生的前传,更不是朋友一生的外篇,只有你自己对自己的一生负责,别人无法也负不起这个责任。自己做的决定,至少到最后,自己没什么可后悔。对于大多数正常智力的人来说,所做的决定没有大的对错,无论怎么样的选择,都是可以尝试的。比如你没有考自己上的那个学校,没有入现在这个行业,这辈子就过不下去了?就会很失败?不见得。
      我想,好工作,应该是适合你的工作,具体点说,应该是能给你带来你想要的东西的工作,你或许应该以此来衡量你的工作究竟好不好,而不是拿公司的大小,规模,外企还是国企,是不是有名,是不是上市公司来衡量。小公司,未必不是好公司,赚钱多的工作,也未必是好工作。你还是要先弄清楚你想要什么,如果你不清楚你想要什么,你就永远也不会找到好工作,因为你永远只看到你得不到的东西,你得到的,都是你不想要的。
      可能,最好的,已经在你的身边,只是,你还没有学会珍惜。人们总是盯着得不到的东西,而忽视了那些已经得到的东西。

     

    四、普通人

      我发现中国人的励志和国外的励志存在非常大的不同,中国的励志比较鼓励人立下大志愿,卧薪尝胆,有朝一日成富成贵。而国外的励志比较鼓励人勇敢面对现实生活,面对普通人的困境,虽然结果也是成富成贵,但起点不一样,相对来说,我觉得后者在操作上更现实,而前者则需要用999个失败者来堆砌一个成功者的故事。
      我们都是普通人,普通人的意思就是,概率这件事是很准的。因此,我们不会买彩票中500万,我们不会成为比尔盖茨或者李嘉诚,我们不会坐飞机掉下来,我们当中很少的人会创业成功,我们之中有30%的人会离婚,我们之中大部分人会活过65岁……
      所以请你在想自己要什么的时候,要得“现实”一点,你说我想要做李嘉诚,抱歉,我帮不上你。成为比尔盖茨或者李嘉诚这种人,是靠命的,看我写的这篇文章绝对不会让你成为他们,即使你成为了他们,也绝对不是我这篇文章的功劳。“王侯将相宁有种乎”但真正当皇帝的只有一个人,王侯将相,人也不多。目标定得高些对于喜欢挑战的人来说有好处,但对于大多数普通人来说,反而比较容易灰心沮丧,很容易就放弃了。
      回过头来说,李嘉诚比你有钱大致50万倍,他比你更快乐么?或许。有没有比你快乐50万倍,一定没有。他比你最多也就快乐一两倍,甚至有可能还不如你快乐。寻找自己想要的东西不是和别人比赛,比谁要得更多更高,比谁的目标更远大。虽然成为李嘉诚这个目标很宏大,但你并不见得会从这个目标以及追求目标的过程当中获得快乐,而且基本上你也做不到。你必须听听你内心的声音,寻找真正能够使你获得快乐的东西,那才是你想要的东西。
      你想要的东西,或者我们把它称之为目标,目标其实并没有高低之分,你不需要因为自己的目标没有别人远大而不好意思,达到自己的目标其实就是成功,成功有大有小,快乐却是一样的。我们追逐成功,其实追逐的是成功带来的快乐,而非成功本身。职业生涯的道路上,我们常常会被攀比的心态蒙住眼睛,忘记了追求的究竟是什么,忘记了是什么能使我们更快乐。
      社会上一夜暴富的新闻很多,这些消息,总会在我们的心里面掀起很多涟漪,涟漪多了就变成惊涛骇浪,心里的惊涛骇浪除了打翻承载你目标的小船,并不会使得你也一夜暴富。“只见贼吃肉,不见贼挨揍。”我们这些普通人既没有当贼的勇气,又缺乏当贼的狠辣绝决,虽然羡慕吃肉,却更害怕挨揍,偶尔看到几个没挨揍的贼就按奈不住,或者心思活动,或者大感不公,真要叫去做贼,却也不敢。
      我还是过普通人的日子,要普通人的快乐,至少,晚上睡得着觉。
       
    五、跳槽与积累

      首先要说明,工作是一件需要理智的事情,所以不要在工作上耍个性,天涯上或许会有人觉得你很有个性而叫好,煤气公司电话公司不会因为觉得你很有个性而免了你的帐单。当你很帅地炒掉了你的老板,当你很酷地挖苦了一番招聘的HR,账单还是要照付,只是你赚钱的时间更少了,除了你自己,没人受损失。
      我并不反对跳槽,但跳槽决不是解决问题的办法,而且频繁跳槽的后果是让人觉得没有忠诚度可言,而且不能安心工作。现在很多人从网上找工作,很多找工作的网站常常给人出些馊主意,要知道他们是盈利性企业,当然要从自身盈利的角度来考虑,大家越是频繁跳槽频繁找工作他们越是生意兴隆,所以鼓动人们跳槽是他们的工作。所以他们会常常告诉你,你拿的薪水少了,你享受的福利待遇差了,又是“薪情快报”又是“赞叹自由奔放的灵魂”。至于是否会因此让你不能安心,你跳了槽是否解决问题,是否更加开心,那个,他们管不着。
      要跳槽肯定是有问题,一般来说问题发生了,躲是躲不开的,很多人跳槽是因为这样或者那样的不开心,如果这种不开心,在现在这个公司不能解决,那么在下一个公司多半也解决不掉。你必须相信,90%的情况下,你所在的公司并没有那么烂,你认为不错的公司也没有那么好。就像围城里说的,“城里的人拼命想冲出来,而城外的人拼命想冲进去。”每个公司都有每个公司的问题,没有问题的公司是不存在的。换个环境你都不知道会碰到什么问题,与其如此,不如就在当下把问题解决掉。很多问题当你真的想要去解决的时候,或许并没有那么难。有的时候你觉得问题无法解决,事实上,那只是“你觉得”。
      人生的曲线应该是曲折向上的,偶尔会遇到低谷但大趋势总归是曲折向上的,而不是象脉冲波一样每每回到起点,我见过不少面试者,30多岁了,四五份工作经历,每次多则3年,少则1年,30多岁的时候回到起点从一个初级职位开始干起,拿基本初级的薪水,和20多岁的年轻人一起竞争,不觉得有点辛苦么?这种日子好过么?
      我非常不赞成在一个行业超过3年以后换行业,基本上,35岁以前我们的生存资本靠打拼,35岁以生存的资本靠的就是积累,这种积累包括人际关系,经验,人脉,口碑……如果常常更换行业,代表几年的积累付之东流,一切从头开始,如果换了两次行业,35岁的时候大概只有5年以下的积累,而一个没有换过行业的人至少有了10年的积累,谁会占优势?工作到2-3年的时候,很多人觉得工作不顺利,好像到了一个瓶颈,心情烦闷,就想辞职,乃至换一个行业,觉得这样所有一切烦恼都可以抛开,会好很多。其实这样做只是让你从头开始,到了时候还是会发生和原来行业一样的困难,熬过去就向上跨了一大步,要知道每个人都会经历这个过程,每个人的职业生涯中都会碰到几个瓶颈,你熬过去了而别人没有熬过去你就领先了。跑长跑的人会知道,开始的时候很轻松,但是很快会有第一次的难受,但过了这一段又能跑很长一段,接下来会碰到第二次的难受,坚持过了以后又能跑一段,如此往复,难受一次比一次厉害,直到坚持不下去了。大多数人第一次就坚持不了了,一些人能坚持到第二次,第三次虽然大家都坚持不住了,可是跑到这里的人也没几个了,这点资本足够你安稳活这一辈子了。
      一份工作到两三年的时候,大部分人都会变成熟手,这个时候往往会陷入不断的重复,有很多人会觉得厌倦,有些人会觉得自己已经搞懂了一切,从而懒得去寻求进步了。很多时候的跳槽是因为觉得失去兴趣了,觉得自己已经完成比赛了。其实这个时候比赛才刚刚开始,工作两三年的人,无论是客户关系,人脉,手下,和领导的关系,在业内的名气……还都是远远不够的,但稍有成绩的人总是会自我感觉良好的,每个人都觉得自己跟客户关系铁得要命,觉得自己在业界的口碑好得很。其实可以肯定地说,一定不是,这个时候,还是要拿出前两年的干劲来,稳扎稳打,积累才刚刚开始。
      你足够了解你的客户吗?你知道他最大的烦恼是什么吗?你足够了解你的老板么?你知道他最大的烦恼是什么吗?你足够了解你的手下么?你知道他最大的烦恼是什么吗?如果你不知道,你凭什么觉得自己已经积累够了?如果你都不了解,你怎么能让他们帮你的忙,做你想让他们做的事情?如果他们不做你想让他们做的事情,你又何来的成功?

    六、等待

      这是个浮躁的人们最不喜欢的话题,本来不想说这个话题,因为会引起太多的争论,而我又无意和人争论这些,但是考虑到对于职业生涯的长久规划,这是一个躲避不了的话题,还是决定写一写,不爱看的请离开吧。
      并不是每次穿红灯都会被汽车撞,并不是每个罪犯都会被抓到,并不是每个错误都会被惩罚,并不是每个贪官都会被枪毙,并不是你的每一份努力都会得到回报,并不是你的每一次坚持都会有人看到,并不是你每一点付出都能得到公正的回报,并不是你的每一个善意都能被理解……这个,就是世道。好吧,世道不够好,可是,你有推翻世道的勇气么?如果没有,你有更好的解决办法么?有很多时候,人需要一点耐心,一点信心。每个人总会轮到几次不公平的事情,而通常,安心等待是最好的办法。
      有很多时候我们需要等待,需要耐得住寂寞,等待属于你的那一刻。周润发等待过,刘德华等待过,周星驰等待过,王菲等待过,张艺谋也等待过……看到了他们如今的功成名就的人,你可曾看到当初他们的等待和耐心?你可曾看到金马奖影帝在街边摆地摊?你可曾看到德云社一群人在剧场里给一位观众说相声?你可曾看到周星驰的角色甚至连一句台词都没有?每一个成功者都有一段低沉苦闷的日子,我几乎能想象得出来他们借酒浇愁的样子,我也能想象得出他们为了生存而挣扎的窘迫。在他们一生最中灿烂美好的日子里,他们渴望成功,但却两手空空,一如现在的你。没有人保证他们将来一定会成功,而他们的选择是耐住寂寞。如果当时的他们总念叨着“成功只是属于特权阶级的”,你觉得他们今天会怎样?
      曾经我也不明白有些人为什么并不比我有能力却要坐在我的头上,年纪比我大就一定要当我的领导么?为什么有些烂人不需要努力就能赚钱?为什么刚刚改革开放的时候的人能那么容易赚钱,而轮到我们的时候,什么事情都要正规化了?有一天我突然想,我还在上学的时候他们就在社会里挣扎奋斗了,他们在社会上奋斗积累了十几二十年,我们新人来了,他们有的我都想要,我这不是在要公平,我这是在要抢劫。因为我要得太急,因为我忍不住寂寞。二十多岁的男人,没有钱,没有事业,却有蓬勃的欲望。
      人总是会遇到挫折的,人总是会有低潮的,人总是会有不被人理解的时候的,人总是有要低声下气的时候,这些时候恰恰是人生最关键的时候,因为大家都会碰到挫折,而大多数人过不了这个门槛,你能过,你就成功了。在这样的时刻,我们需要耐心等待,满怀信心地去等待,相信,生活不会放弃你,机会总会来的。至少,你还年轻,你没有坐牢,没有生治不了的病,没有欠还不起的债。比你不幸的人远远多过比你幸运的人,你还怕什么?路要一步步走,虽然到达终点的那一步很激动人心,但大部分的脚步是平凡甚至枯燥的,但没有这些脚步,或者耐不住这些平凡枯燥,你终归是无法迎来最后的那些激动人心。
      逆境,是上帝帮你淘汰竞争者的地方。要知道,你不好受,别人也不好受,你坚持不下去了,别人也一样,千万不要告诉别人你坚持不住了,那只能让别人获得坚持的信心,让竞争者看着你微笑的面孔,失去信心,退出比赛。胜利属于那些有耐心的人。
      在最绝望的时候,我会去看电影《The Pursuit of Happyness》《JerryMaguire》,让自己重新鼓起勇气,因为,无论什么时候,我们总还是有希望。当所有的人离开的时候,我不失去希望,我不放弃。每天下班坐在车里,我喜欢哼着《隐形的翅膀》看着窗外,我知道,我在静静等待,等待属于我的那一刻。
      原贴里伊吉网友的话我很喜欢,抄录在这里:
      每个人都希望,自己是独一无二的特殊者
      含着金匙出生、投胎到好家庭、工作安排到电力局拿1w月薪这样的小概率事件,当然最好轮到自己
      红军长征两万五、打成右派反革命、胼手胝足牺牲尊严去奋斗,最好留给祖辈父辈和别人
      自然,不是每个吃过苦的人都会得到回报
      但是,任何时代,每一个既得利益者身后,都有他的祖辈父辈奋斗挣扎乃至流血付出生命的身影
      羡慕别人有个好爸爸,没什么不可以
      问题是,你的下一代,会有一个好爸爸吗?
      至于问到为什么不能有同样的赢面概率?我只能问:为什么物种竞争中,人和猴子不能有同样的赢面概率?
      物竞天择。猴子的灵魂不一定比你卑微,但你身后有几十万年的类人猿进化积淀。


     


    七、入对行跟对人

      在中国,大概很少有人是一份职业做到底的,虽然如此,第一份工作还是有些需要注意的地方,有两件事情格外重要,第一件是入行,第二件事情是跟人。第一份工作对人最大的影响就是入行,现代的职业分工已经很细,我们基本上只能在一个行业里成为专家,不可能在多个行业里成为专家。很多案例也证明即使一个人在一个行业非常成功,到另外一个行业,往往完全不是那么回事情,“你想改变世界,还是想卖一辈子汽水?”是乔布斯邀请百事可乐总裁约翰·斯考利加盟苹果时所说的话,结果这位在百事非常成功的约翰,到了苹果表现平平。其实没有哪个行业特别好,也没有哪个行业特别差,或许有报道说哪个行业的平均薪资比较高,但是他们没说的是,那个行业的平均压力也比较大。看上去很美的行业一旦进入才发现很多地方其实并不那么完美,只是外人看不见。
      说实话,我自己都没有发大财,所以我的建议只是让人快乐工作的建议,不是如何发大财的建议,我们只讨论一般普通打工者的情况。我认为选择什么行业并没有太大关系,看问题不能只看眼前。比如,从前年开始,国家开始整顿医疗行业,很多医药公司开不下去,很多医药行业的销售开始转行。其实医药行业的不景气是针对所有公司的,并非针对一家公司,大家的日子都不好过,这个时候跑掉是非常不划算的,大多数正规的医药公司即使不做新生意撑个两三年总是能撑的,大多数医药销售靠工资撑个两三年也是可以撑的,国家不可能永远捏着医药行业不放的,两三年以后光景总归还会好起来的,那个时候别人都跑了而你没跑,那时的日子应该会好过很多。有的时候觉得自己这个行业不行了,问题是,再不行的行业,做得人少了也变成了好行业,当大家都觉得不好的时候,往往却是最好的时候。大家都觉得金融行业好,金融行业门槛高不说,有多少人削尖脑袋要钻进去,竞争激励,进去以后还要时时提防,一个疏忽,就被后来的人给挤掉了,压力巨大,又如何谈得上快乐?也就未必是“好”工作了。
      太阳能这个东西至今还不能进入实际应用的阶段,但是中国已经有7家和太阳能有关的公司在纽交所上市了,国美苏宁永乐其实是贸易型企业,也能上市,鲁泰纺织连续10年利润增长超过50%,卖茶的一茶一座,卖衣服的海澜之家都能上市……其实选什么行业真的不重要,关键是怎么做。事情都是人做出来的,关键是人。
      有一点是需要记住的,这个世界上,有史以来直到我们能够预见得到的未来,成功的人总是少数,有钱的人总是少数,大多数人是一般的,普通的,不太成功的。因此,大多数人的做法和看法,往往都不是距离成功最近的做法和看法。因此大多数人说好的东西不见得好,大多数人说不好的东西不见得不好。大多数人都去炒股的时候说明跌只是时间问题,大家越是热情高涨的时候,跌的日子越近。大多数人买房子的时候,房价不会涨,而房价涨的差不多的时候,大多数人才开始买房子。不会有这样一件事情让大家都变成功,发了财,历史上不曾有过,将来也不会发生。有些东西即使一时运气好得到了,还是会在别的时候别的地方失去的。
      年轻人在职业生涯的刚开始,尤其要注意的是,要做对的事情,不要让自己今后几十年的人生总是提心吊胆,更不值得为了一份工作赔上自己的青春年华。我的公司是个不行贿的公司,以前很多人不理解,甚至自己的员工也不理解,不过如今,我们是同行中最大的企业,客户乐意和我们打交道,尤其是在国家打击腐败的时候,每个人都知道我们做生意不给钱的名声,都敢于和我们做生意。而勇于给钱的公司,不是倒了,就是跑了,要不就是每天睡不好觉,人还是要看长远一点。很多时候,看起来最近的路,其实是最远的路,看起来最远的路,其实是最近的路。
      跟对人是说,入行后要跟个好领导好老师,刚进社会的人做事情往往没有经验,需要有人言传身教。对于一个人的发展来说,一个好领导是非常重要的。所谓“好”的标准,不是他让你少干活多拿钱,而是以下三个。
      首先,好领导要有宽广的心胸,如果一个领导每天都会发脾气,那几乎可以肯定他不是个心胸宽广的人,能发脾气的时候却不发脾气的领导,多半是非常厉害的领导。中国人当领导最大的毛病是容忍不了能力比自己强的人,所以常常可以看到的一个现象是,领导很有能力,手下一群庸才或者手下一群闲人。如果看到这样的环境,还是不要去的好。
      其次,领导要愿意从下属的角度来思考问题,这一点其实是从面试的时候就能发现的,如果这位领导总是从自己的角度来考虑问题,几乎不听你说什么,这就危险了。从下属的角度来考虑问题并不代表同意下属的说法,但他必须了解下属的立场,下属为什么要这么想,然后他才有办法说服你,只关心自己怎么想的领导往往难以获得下属的信服。
      第三,领导敢于承担责任,如果出了问题就把责任往下推,有了功劳就往自己身上揽,这样的领导不跟也罢。选择领导,要选择关键时刻能抗得住的领导,能够为下属的错误买单的领导,因为这是他作为领导的责任。
      有可能,你碰不到好领导,因为,中国的领导往往是屁股决定脑袋的领导,因为他坐领导的位置,所以他的话就比较有道理,这是传统观念官本位的误区,可能有大量的这种无知无能的领导,只是,这对于你其实是好事,如果将来有一天你要超过他,你希望他比较聪明还是比较笨?相对来说这样的领导其实不难搞定,只是你要把自己的身段放下来而已。多认识一些人,多和比自己强的人打交道,同样能找到好的老师,不要和一群同样郁闷的人一起控诉社会,控诉老板,这帮不上你,只会让你更消极。和那些比你强的人打交道,看他们是怎么想的,怎么做的,学习他们,然后跟更强的人打交道。

    八、选择

      我们每天做的最多的事情,其实是选择,因此在谈职业生涯的时候不得不提到这个话题。
      我始终认为,在很大的范围内,我们究竟会成为一个什么样的人,决定权在我们自己,每天我们都在做各种各样的选择,我可以不去写这篇文章,去别人的帖子拍拍砖头,也可以写下这些文字,帮助别人的同时也整理自己的思路,我可以多注意下格式让别人易于阅读,也可以写成一堆,我可以就这样发上来,也可以在发以前再看几遍,你可以选择不刮胡子就去面试,也可以选择出门前照照镜子……每天,每一刻我们都在做这样那样的决定,我们可以漫不经心,也可以多花些心思,成千上万的小选择累计起来,就决定了最终我们是个什么样的人。
      从某种意义上来说我们的未来不是别人给的,是我们自己选择的,很多人会说我命苦啊,没得选择阿,如果你认为“去微软还是去IBM”“上清华还是上北大”“当销售副总还是当厂长”这种才叫选择的话,的确你没有什么选择,大多数人都没有什么选择。但每天你都可以选择是否为客户服务更周到一些,是否对同事更耐心一些,是否把工作做得更细致一些,是否把情况了解得更清楚一些,是否把不清楚的问题再弄清楚一些……你也可以选择在是否在痛苦中继续坚持,是否抛弃掉自己的那些负面的想法,是否原谅一个人的错误,是否相信我在这里写下的这些话,是否不要再犯同样的错误……生活每天都在给你选择的机会,每天都在给你改变自己人生的机会,你可以选择赖在地上撒泼打滚,也可以选择咬牙站起来。你永远都有选择。有些选择不是立杆见影的,需要累积,比如农民可以选择自己常常去浇地,也可以选择让老天去浇地,诚然你今天浇水下去苗不见得今天马上就长出来,但常常浇水,大部分苗终究会长出来的,如果你不浇,收成一定很糟糕。
      每天生活都在给你机会,他不会给你一叠现金也不会拱手送你个好工作,但实际上,他还是在给你机会。我的家庭是一个普通的家庭,没有任何了不起的社会关系,我的父亲在大学毕业以后就被分配到了边疆,那个小县城只有一条马路,他们那一代人其实比我们更有理由抱怨,他们什么也没得到,年轻的时候文化大革命,书都没得读,支援边疆插队落户,等到老了,却要给年轻人机会了。他有足够的理由象成千上万那样的青年一样坐在那里抱怨生不逢时,怨气冲天。然而在分配到边疆的十年之后,国家恢复招研究生,他考回了原来的学校。研究生毕业,他被分配到了安徽一家小单位里,又是3年以后,国家第一届招收博士生,他又考回了原来的学校,成为中国第一代博士,那时的他比现在的我年纪还大。生活并没有放弃他,他也没有放弃生活。10年的等待,他做了他自己的选择,他没有放弃,他没有破罐子破摔,所以时机到来的时候,他改变了自己的人生。你最终会成为什么样的人,就决定在你的每个小小的选择之间。
      你选择相信什么?你选择和谁交朋友?你选择做什么?你选择怎么做?……
    我们面临太多的选择,而这些选择当中,意识形态层面的选择又远比客观条件的选择来得重要得多,比如选择做什么产品其实并不那么重要,而选择怎么做才重要。选择用什么人并不重要,而选择怎么带这些人才重要。大多数时候选择客观条件并不要紧,大多数关于客观条件的选择并没有对错之分,要紧的是选择怎么做。一个大学生毕业了,他要去微软也好,他要卖猪肉也好,他要创业也好,他要做游戏代练也好,只要不犯法,不害人,都没有什么关系,要紧的是,选择了以后,怎么把事情做好。
      除了这些,你还可以选择时间和环境,比如,你可以选择把这辈子最大的困难放在最有体力最有精力的时候,也可以走一步看一步,等到了40岁再说,只是到了40多岁,那正是一辈子最脆弱的时候,上有老下有小,如果在那个时候碰上了职业危机,实在是一件很苦恼的事情。与其如此不如在20多岁30多岁的时候吃点苦,好让自己脆弱的时候活得从容一些。你可以选择在温室里成长,也可以选择到野外磨砺,你可以选择在办公室吹冷气的工作,也可以选择40度的酷热下,去见你的客户,只是,这一切最终会累积起来,引导你到你应得的未来。
      我不敢说所有的事情你都有得选择,但是绝大部分事情你有选择,只是往往你不把这当作一种选择。认真对待每一次选择,才会有比较好的未来。

    九、选择职业

      职业的选择,总的来说,无非就是销售、市场、客服、物流、行政、人事、财务、技术、管理几个大类,有个有趣的现象就是,500强的CEO当中最多的是销售出身,第二多的人是财务出身,这两者加起来大概超过95%。现代IT行业也有技术出身成为老板的,但实际上,后来他们还是从事了很多销售和市场的工作,并且表现出色,公司才获得了成功,完全靠技术能力成为公司老板的,几乎没有。这是有原因的,因为销售就是一门跟人打交道的学问,而管理其实也是跟人打交道的学问,这两者之中有很多相通的东西,他们的共同目标就是“让别人去做某件特定的事情。”而财务则是从数字的层面了解生意的本质,从宏观上看待生意的本质,对于一个生意是否挣钱,是否可以正常运作有着最深刻的认识。
      公司小的时候是销售主导公司,而公司大的时候是财务主导公司,销售的局限性在于只看人情不看数字,财务的局限性在于只看数字不看人情。公司初期,运营成本低,有订单就活得下去,跟客户也没有什么谈判的条件,别人肯给生意做已经谢天谢地了,这个时候订单压倒一切,客户的要求压倒一切,所以当然要顾人情。公司大了以后,一切都要规范化,免得因为不规范引起一些不必要的风险,同时运营成本也变高,必须提高利润率,把有限的资金放到最有产出的地方。对于上市公司来说,股东才不管你客户是不是最近出国,最近是不是那个省又在搞严打,到了时候就要把业绩拿出来,拿不出来就抛股票,这个时候就是数字压倒一切。
      前两天听到有人说一句话觉得很有道理,开始的时候我们想“能做什么?”,等到公司做大了有规模了,我们想“不能做什么。”很多人在工作中觉得为什么领导这么保守,这也不行那也不行,错过很多机会。很多时候是因为,你还年轻,你想的是“能做什么”,而作为公司领导要考虑的方面很多,他比较关心“不能做什么”。
      我并非鼓吹大家都去做销售或者财务,究竟选择什么样的职业,和你究竟要选择什么样的人生有关系,有些人就喜欢下班按时回家,看看书听听音乐,那也挺好,但就不适合找个销售的工作了,否则会是折磨自己。有些人就喜欢出风头,喜欢成为一群人的中心,如果选择做财务工作,大概也干不久,因为一般老板不喜欢财务太积极,也不喜欢财务话太多。先想好自己要过怎样的人生,再决定要找什么样的职业。有很多的不快乐,其实是源自不满足,而不满足,很多时候是源自于心不定,而心不定则是因为不清楚究竟自己要什么,不清楚要什么的结果就是什么都想要,结果什么都没得到。
      我想,我们还是因为生活而工作,不是因为工作而生活,生活是最要紧的,工作只是生活中的一部分。我总是觉得生活的各方方面都是相互影响的,如果生活本身一团乱麻,工作也不会顺利。所以要有娱乐、要有社交、要锻炼身体,要有和睦的家庭……最要紧的,要开心,我的两个销售找我聊天,一肚子苦水,我问他们,2年以前,你什么都没有,工资不高,没有客户关系,没有业绩,处于被开的边缘,现在的你比那时条件好了很多,为什么现在却更加不开心了?如果你做得越好越不开心,那你为什么还要工作?首先的首先,人还是要让自己高兴起来,让自己心态好起来,这种发自内心的改变会让你更有耐心,更有信心,更有气质,更能包容……否则,看看镜子里的你,你满意么?
      有人会说,你说得容易,我每天加班,不加班老板就会把我炒掉,每天累得要死,哪有时间娱乐、社交、锻炼?那是人们把目标设定太高的缘故,如果你还在动不动就会被老板炒掉的边缘,那么你当然不能设立太高的目标,难道你还想每天去打高尔夫?你没时间去健身房锻炼身体,但是上下班的时候多走几步可以吧,有楼梯的时候走走楼梯不走电梯可以吧?办公的间隙扭扭脖子拉拉肩膀做做俯卧撑可以吧?谁规定锻炼就一定要拿出每天2个小时去健身房?你没时间社交,每月参加郊游一次可以吧,周末去参加个什么音乐班,绘画班之类的可以吧,去尝试认识一些同行,和他们找机会交流交流可以吧?开始的时候总是有些难的,但迈出这一步就会向良性循环的方向发展。而每天工作得很苦闷,剩下的时间用来咀嚼苦闷,只会陷入恶性循环,让生活更加糟糕。
        虽然离开惠普仅有十五天,但感觉上惠普已经离我很远。我的心思更多放在规划自己第二阶段的人生,这并非代表我对惠普没有任何眷恋,主要还是想以此驱动自己往前走。
      万科王石登珠穆朗玛峰的体验给我很多启发,虽然在出发时携带大量的物资,但是登顶的过程中,必须不断减轻负荷,最终只有一个氧气瓶和他登上峰顶。登山如此,漫长的人生又何尝不是。
      我宣布退休后,接到同事朋友同学的祝贺。大部分人都认为我能够在这样的职位上及年龄选择退休,是一种勇气,也是一种福气。          
      还有一部分人怀疑我只是借此机会换个工作,当然还有一些人说我在HP做不下去了,趁此机会离开。
      我多年来已经习惯别人对我的说三道四,但对于好友,我还是挺关心大家是否真正理解我的想法,这也是写这篇文章的目的。
      由于受我父亲早逝的影响,我很早就下定决心,要在有生之年实现自己的愿望,我不要像我父亲一样,为家庭生活忙碌一辈子,临终前感伤,懊恼自己有很多没有实现的理想。
      一本杂志的文章提到我们在生前就应该思考自己的墓志铭,因为那代表你自己对完美人生的定义,我们应该尽可能在有生之年去实现它。
      我希望我的墓志铭上除了与家人及好友有关的内容外,是这样写着:
      1.这个人曾经服务于一家全球最大的IT公司(HP)25年,和她一起经历过数次重大的变革,看着她从以电子仪表为主要的业务变革成全球最大的IT公司。
      2.这个人曾经在全球发展最快的国家(中国)工作16年,并担任HP中国区总裁7年,见证及经历过中国改革开放的关键最新突破阶段,与中国一起成长。
      3.这个人热爱飞行,曾经是一个有执照的飞行员,累积飞行时数超过X小时,曾经在X个机场起降过。
      4.这个人曾经获得管理硕士学位,在领导管理上特别关注中国企业的组织行为及绩效,并且在这个领域上获得中国企业界的认可。
      我费时25年才总结1和2两项成果,我不知还要费时多久才能达成3和4的愿望,特别是第4个愿望需要经历学术的训练,才能将我的经验总结成知识。
        否则我的经验将无法有效影响及传授他人。因此重新进入学校学习,拿一个管理学位是有必要的,更何况这是我一个非常重要的愿望。
      另一方面,我25年的时间都花在运营(operation)的领域,兢兢业业的做好职业人士的工作,它是一份好工作,特别是在HP,这份工作也帮助我建立财务的基础,支持家庭的发展。
      但是我不想终其一生,都陷入在运营的领域,我想象企业家一样,有机会靠一些点子(ideas)赚钱,虽然风险很高,但是值得一试,即使失败,也不枉走一回,这也是第4个愿望其中的一部份。
      Carly Fiorina曾经对我说过“这个世界上有好想法的人很多,但有能力去实现的人很少”,2007年5月21日在北大演讲时,有人问起那些书对我影响较大,我想对我人生观有影响的其中一本书叫“TriggerPoint”,它的主要观点是:人生最需要的不是规划,而是在适当的时机掌握机会,采取行动。
      我这些愿望在我心中已经酝酿一段很长的时间,开始的时候,也许一年想个一两次,过了也就忘掉,但逐渐的,这个心中的声音,愈来愈大,出现的频率也愈来愈高,当它几乎每一个星期都会来与我对话时,我知道时机已经成熟。
      但和任何人一样,要丢掉自己现在所拥有的,所熟悉的环境及稳定的收入,转到一条自己未曾经历过,存在未知风险的道路,需要绝大的勇气,家人的支持和好友的鼓励。有舍才有得,真是知易行难,我很高兴自己终于跨出了第一步。
      我要感谢HP的EER提前退休优惠政策,它是其中一个关键的TriggerPoints,另一个关键因素是在去年五六月发生的事。
      当时我家老大从大学毕业,老二从高中毕业,在他们继续工作及求学前,这是一个黄金时段,让我们全家可以相聚一段较长的时间,我为此很早就计划休一个长假,带着他们到各地游玩。
      但这个计划因为工作上一件重要的事情(Mark Hurd访华)不得不取消。这个事件刺激了我必须严肃的去对待那心中的声音,我会不会继续不断的错失很多关键的机会?
      我已经年过50,我会不会走向和我父亲一样的道路?人事部老总Charles跟我说,很多人在所有对他有利的星星都排成一列时,还是错失时机。
      我知道原因,因为割舍及改变对人是多么的困难,我相信大部分的人都有自己人生的理想,但我也相信很多人最终只是把这些理想当成是幻想,然后不断的为自己寻找不能实现的藉口,南非前总统曼德拉曾经说过,“与改变世界相比,改变自己更困难”,真是一针见血。
      什么是快乐及有意义的人生?我相信每一个人的定义都不一样,对我来说,能实现我墓志铭上的内容就是我的定义。
      在中国惠普总裁的位置上固然可以吸引很多的关注及眼球,但是我太太及较亲近的好友,都知道那不是我追求的,那只是为扮演好这个角色必须尽力做好的地方。
      做一个没有名片的人士,虽然只有十多天的时间,但我发现我的脑袋里已经空出很多空间及能量,让我可以静心的为我ChapterII的新生活做细致的调研及规划。
      我预订以两年的时间来完成转轨的准备工作,并且花多点时间与家人共处。这两年的时间我希望拿到飞行执照,拿到管理有关的硕士学位,提升英文的水平,建立新的网络,多认识不同行业的人,保持与大陆的联系。希望两年后,我可以顺利回到大陆去实现我第四个愿望。
      毫不意外,在生活上,我发现很多需要调整的地方。
      二十多年来,我生活的步调及节奏,几乎完全被公司及工作所左右,不断涌出的deadline及任务驱动我每天的安排,一旦离开这样的环境,第一个需要调整的就是要依靠自己的自律及意志力来驱动每天的活动,睡觉睡到自然醒的态度绝对不正确,放松自己,不给事情设定目标及时间表,或者对错失时间目标无所谓,也不正确,没有年度,季度,月及周计划也不正确。
      担任高层经理多年,已经养成交待事情的习惯,自己的时间主要花在思考,决策及追踪项目的进展情况,更多是依靠一个庞大的团队来执行具体的事项及秘书来处理很多协调及繁琐的事情。
      到美国后,很多事情需要打800号电话联系,但这些电话很忙,常让你在waitingline上等待很长的时间,当我在等待时,我可以体会以前秘书工作辛苦的地方,但同时也提醒我自己,在这个阶段要改变态度,培养更大的耐性及自己动手做的能力。
      生活的内容也要做出很大的调整,多出时间锻炼身体,多出时间关注家人,多出时间关注朋友,多出时间体验不同的休闲活动及飞行,一步步的,希望生活逐步调整到我所期望的轨道上,期待这两年的生活既充实又充满乐趣及意义。
      第一个快乐的体验就是准备及参加大儿子的订婚礼,那种全心投入,不需担忧工作数字的感觉真好。同时我也租好了公寓,买好了家具及车子,陪家人在周末的时候到Reno及Lake Tahoe玩了一趟,LakeTahoe我去了多次,但这次的体验有所不同,我从心里欣赏到它的美丽。
      但同时我也在加紧调研的工作,为申请大学及飞行学校做准备,这段时间也和在硅谷的朋友及一些风险投资公司见面,了解不同的产业。
      我的人生观是“完美的演出来自充分的准备”,“勇于改变自己,适应不断变化的环境,机会将不断出现”,“快乐及有意义的人生来自于实现自己心中的愿望,而非外在的掌声”。
      我离开时,有两位好朋友送给我两个不同的祝语,Baron的是“多年功过化烟尘”,杨华的是“莫春者,风乎舞雩,咏而归”,它们分别代表了我离开惠普及走向未来的心情。
      我总结人生有三个阶段,一个阶段是为现实找一份工作,一个阶段是为现实,但可以选择一份自己愿意投入的工作,一个阶段是为理想去做一些事情。
      我珍惜我的福气,感激HP及同事、好朋友给我的支持,鼓励及协助,这篇文字化我心声的文章与好友分享。

     

     

     

  • java 读取和写入URLConnection 范例参考

    2010-08-07 17:18:17

    转自:http://download-llnw.oracle.com/javase/tutorial/networking/urls/readingWriting.html



    Reading from and Writing to a URLConnection
    The URLConnection class contains many methods that let you communicate with the URL over the network. URLConnection is an HTTP-centric class; that is, many of its methods are useful only when you are working with HTTP URLs. However, most URL protocols allow you to read from and write to the connection. This section describes both functions.

    Reading from a URLConnection

    The following program performs the same function as the URLReader program shown in Reading Directly from a URL.

    However, rather than getting an input stream directly from the URL, this program explicitly retrieves a URLConnection object and gets an input stream from the connection. The connection is opened implicitly by calling getInputStream. Then, like URLReader, this program creates a BufferedReader on the input stream and reads from it. The bold statements highlight the differences between this example and the previous

    import java.net.*;
    import java.io.*;
    
    public class URLConnectionReader {
        public static void main(String[] args) throws Exception {
            URL yahoo = new URL("http://www.yahoo.com/");
            URLConnection yc = yahoo.openConnection();
            BufferedReader in = new BufferedReader(
                                    new InputStreamReader(
                                    yc.getInputStream()));
            String inputLine;
    
            while ((inputLine = in.readLine()) != null) 
                System.out.println(inputLine);
            in.close();
        }
    }
    
    The output from this program is identical to the output from the program that opens a stream directly from the URL. You can use either way to read from a URL. However, reading from a URLConnection instead of reading directly from a URL might be more useful. This is because you can use the URLConnection object for other tasks (like writing to the URL) at the same time.

    Again, if the program hangs or you see an error message, you may have to set the proxy host so that the program can find the Yahoo server.

    Writing to a URLConnection

    Many HTML pages contain forms-- text fields and other GUI objects that let you enter data to send to the server. After you type in the required information and initiate the query by clicking a button, your Web browser writes the data to the URL over the network. At the other end the server receives the data, processes it, and then sends you a response, usually in the form. of a new HTML page.

    Many of these HTML forms use the HTTP POST METHOD to send data to the server. Thus writing to a URL is often called posting to a URL. The server recognizes the POST request and reads the data sent from the client.

    For a Java program to interact with a server-side process it simply must be able to write to a URL, thus providing data to the server. It can do this by following these steps:

    1. Create a URL.
    2. Retrieve the URLConnection object.
    3. Set output capability on the URLConnection.
    4. Open a connection to the resource.
    5. Get an output stream from the connection.
    6. Write to the output stream.
    7. Close the output stream.

    Here is a small servlet named ReverseServlet ( or if you prefer a cgi-bin script. ). You can use this servlet to test the following example program.

    The servlet running in a container reads from its InputStream, reverses the string, and writes it to its OutputStream. The servlet requires input of the form. string=string_to_reverse, where string_to_reverse is the string whose characters you want displayed in reverse order.

    Here's an example program that runs the ReverseServlet over the network through a URLConnection:

    import java.io.*;
    import java.net.*;
    
    public class Reverse {
        public static void main(String[] args) throws Exception {
    
    	if (args.length != 2) {
    	    System.err.println("Usage:  java Reverse " +
                                   "http://<location of your servlet/script>" + 
                                   " string_to_reverse");
    	    System.exit(1);
    	}
    
    	String stringToReverse = URLEncoder.encode(args[1], "UTF-8");
    
    	URL url = new URL(args[0]);
    	URLConnection connection = url.openConnection();
    	connection.setDoOutput(true);
    
    	OutputStreamWriter ut = new OutputStreamWriter(
                                  connection.getOutputStream());
    	out.write("string=" + stringToReverse);
    	out.close();
    
    	BufferedReader in = new BufferedReader(
    				new InputStreamReader(
    				connection.getInputStream()));
    				
    	String decodedString;
    
    	while ((decodedString = in.readLine()) != null) {
    	    System.out.println(decodedString);
    	}
    	in.close();
        }
    }
    
    Let's examine the program and see how it works. First, the program processes its command-line arguments:
    if (args.length != 2) {
        System.err.println("Usage:  java Reverse " +
                            "http://<location of your servlet/script>" + 
    	                " string_to_reverse");
        System.exit(1);
    }	
    
    String stringToReverse = URLEncoder.encode(args[1], "UTF-8");
    
    These statements ensure that the user provides two and only two command-line arguments to the program. The command-line arguments are the location of the ReverseServlet and the string that will be reversed. It may contain spaces or other non-alphanumeric characters. These characters must be encoded because the string is processed on its way to the server. The URLEncoder class methods encode the characters.

    Next, the program creates the URL object, and sets the connection so that it can write to it:

    URL url = new URL(args[0]);
    URLConnection connection = url.openConnection();
    connection.setDoOutput(true);
    
    The program then creates an output stream on the connection and opens an OutputStreamWriter on it:
    OutputStreamWriter ut = new OutputStreamWriter(connection.getOutputStream());
    
    If the URL does not support output, getOutputStream method throws an UnknownServiceException. If the URL does support output, then this method returns an output stream that is connected to the input stream of the URL on the server side--the client's output is the server's input.

    Next, the program writes the required information to the output stream and closes the stream:

    out.write("string=" + stringToReverse);
    out.close();
    
    This code writes to the output stream using the write method. So you can see that writing data to a URL is as easy as writing data to a stream. The data written to the output stream on the client side is the input for the servlet on the server side. The Reverse program constructs the input in the form. required by the script. by prepending string= to the encoded string to be reversed.

    The serlvet reads the information you write, performs a reverse operation on the string value, and then sends this back to you. You now need to read the string the server has sent back. The Reverse program does it like this:

    BufferedReader in = new BufferedReader(
                        new InputStreamReader(
                        connection.getInputStream()));
    				
    String decodedString;
    
    while ((decodedString = in.readLine()) != null) {
        System.out.println(decodedString);
    }
    in.close();
    
    If your ReverseServlet is located at http://foobar.com/servlet/ReverseServlet, then when you run the Reverse program using
    http://foobar.com/servlet/ReverseServlet "Reverse Me"
    
    as the argument (including the double quote marks), you should see this output:
    Reverse Me
     reversed is: 
    eM esreveR
    
  • linux下mysql命令

    2010-08-07 13:32:16

    linux下mysql命令

    启动命令:
    $ ./mysqld_safe --defaults-file=/home/mysql/local/mysql_sale_mirror/etc/my.cnf --basedir=/home/mysql/local/mysql_sale_mirror/ --datadir=/home/mysql/local/mysql_sale_mirror/var/ --pid-file=/home/mysql/local/mysql_sale_mirror/var/mysql.pid --skip-external-locking --port=8100 --socket=/home/mysql/local/mysql_sale_mirror/tmp/mysql.sock &
    [1] 14815
    [mysql@db-testing-ecom959.db01.baidu.com bin]$ Starting mysqld daemon with databases from /home/mysql/local/mysql_sale_mirror/var/

    一、总结一下:

    1.linux下启动mysql的命令:
       mysqladmin start
    /ect/init.d/mysql start (前面为mysql的安装路径)

    2.linux下重启mysql的命令:
       mysqladmin restart
    /ect/init.d/mysql restart (前面为mysql的安装路径)

    3.linux下关闭mysql的命令:
       mysqladmin shutdown
       /ect/init.d/mysql   shutdown (前面为mysql的安装路径)

    4.连接本机上的mysql:
    进入目录mysql\bin,再键入命令mysql -uroot -p, 回车后提示输入密码。
    退出mysql命令:exit(回车)

    5.修改mysql密码:
    mysqladmin -u用户名 -p旧密码 password 新密码
    或进入mysql命令行SET PASSWORD FOR root=PASSWORD("root");

    6.增加新用户。(注意:mysql环境中的命令后面都带一个分号作为命令结束符)
    grant select on 数据库.* to 用户名@登录主机 identified by "密码"
    如增加一个用户test密码为123,让他可以在任何主机上登录, 并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入mysql,然后键入以下命令:
    grant select,insert,update,delete on *.* to " Identified by "123";

    二、有关mysql数据库方面的操作
          必须首先登录到mysql中,有关操作都是在mysql的提示符下进行,而且每个命令以分号结束

    1、显示数据库列表。
         show databases;
    2、显示库中的数据表:
          use mysql; //打开库
          show tables;
    3、显示数据表的结构:
        describe 表名;
    4、建库:
        create database 库名;
    5、建表:
        use 库名;
        create table 表名(字段设定列表);
    6、删库和删表:
         drop database 库名;
          drop table 表名;
    7、将表中记录清空:
         delete from 表名;
    8、显示表中的记录:
        select * from 表名;

    9、编码的修改
    如果要改变整个mysql的编码格式:
    启动mysql的时候,mysqld_safe命令行加入
    --default-character-set=gbk

    如果要改变某个库的编码格式:在mysql提示符后输入命令
    alter database db_name default character set gbk;

    三、数据的导入导出

    1、文本数据转到数据库中
        文本数据应符合的格式:字段数据之间用tab键隔开,null值用来代替。例:
        1 name duty 2006-11-23
        数据传入命令 load data local infile "文件名" into table 表名;

    2、导出数据库和表
        mysqldump --opt news > news.sql(将数据库news中的所有表备份到news.sql文件,news.sql是一个文本文件,文件名任取。)
        mysqldump --opt news author article > author.article.sql(将数据库news中的author表和article表备份到author.article.sql文件, author.article.sql是一个文本文件,文件名任取。)
        mysqldump --databases db1 db2 > news.sql(将数据库dbl和db2备份到news.sql文件,news.sql是一个文本文件,文件名任取。)
         mysqldump -h host -u user -p pass --databases dbname > file.dump
    就是把host上的以名字user,口令pass的数据库dbname导入到文件file.dump中
        mysqldump --all-databases > all-databases.sql(将所有数据库备份到all-databases.sql文件,all-databases.sql是一个文本文件,文件名任取。)

    3、导入数据
        mysql < all-databases.sql(导入数据库)
        mysql>source news.sql;(在mysql命令下执行,可导入表)


    一、连接MySQL
            格式: mysql -h主机地址 -u用户名 -p用户密码

            1、例1:连接到本机上的MYSQL。

            首先在打开DOS窗口,然后进入目录 mysqlbin,再键入命令mysql -uroot -p,回车后提示你输密码,如果刚安装好MYSQL,超级用户root是没有密码的,故直接回车即可进入到MYSQL中了,MYSQL的提示符是: mysql>。

            2、例2:连接到远程主机上的MYSQL。假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123。则键入以下命令:

            mysql -h110.110.110.110 -uroot -pabcd123

            (注:u与root可以不用加空格,其它也一样)

            3、退出MYSQL命令: exit (回车)。

            二、修改密码

            格式:mysqladmin -u用户名 -p旧密码 password 新密码

            1、例1:给root加个密码ab12。首先在DOS下进入目录mysqlbin,然后键入以下命令:

            mysqladmin -uroot -password ab12

            注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。

            2、例2:再将root的密码改为djg345。

            mysqladmin -uroot -pab12 password djg345

            三、增加新用户。(注意:和上面不同,下面的因为是MySQL环境中的命令,所以后面都带一个分号作为命令结束符)

            格式:grant select on 数据库.* to 用户名@登录主机 identified by \"密码\"

            例1、增加一个用户test1密码为abc,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入MySQL,然后键入以下命令:

            grant select,insert,update,
            delete on *.* to test1@\"%\" Identified by \"abc\";

            但例1增加的用户是十分危险的,你想如某个人知道test1的密码,那么他就可以在internet上的任何一台电脑上登录你的MySQL数据库并对你的数据可以为所欲为了,解决办法见例2。

            例2、增加一个用户test2密码为abc,让他只可以在localhost上登录,并可以对数据库mydb进行查询、插入、修改、删除的操作 (localhost指本地主机,即MySQL数据库所在的那台主机),这样用户即使用知道test2的密码,他也无法从internet上直接访问数据 库,只能通过MySQL主机上的web页来访问。

            grant select,insert,update,
            delete on mydb.* to test2@localhost identified by \"abc\";

            如果你不想test2有密码,可以再打一个命令将密码消掉。

            grant select,insert,update,delete on mydb
            .* to test2@localhost identified by \"\";

            在上面讲了登录、增加用户、密码更改等问题。下面我们来看看MySQL中有关数据库方面的操作。注意:你必须首先登录到MySQL中,以下操作都是在MySQL的提示符下进行的,而且每个命令以分号结束。

    一、操作技巧

            1、如果你打命令时,回车后发现忘记加分号,你无须重打一遍命令,只要打个分号回车就可以了。也就是说你可以把一个完整的命令分成几行来打,完后用分号作结束标志就完成。

            2、你可以使用光标上下键调出以前的命令。但以前我用过的一个MySQL旧版本不支持。我现在用的是mysql-3.23.27-beta-win。

            二、显示命令

            1、显示数据库列表:

            show databases;

            刚开始时才两个数据库:mysql和test。MySQL库很重要它里面有MYSQL的系统信息,我们改密码和新增用户,实际上就是用这个库进行操作。

            2、显示库中的数据表:

            use mysql; //打开库,学过FOXBASE的一定不会陌生吧

            show tables;

            3、显示数据表的结构:

            describe 表名;

            4、建库:

            create database 库名;

            5、建表:

            use 库名;

            create table 表名 (字段设定列表);

            6、删库和删表:

            drop database 库名;

            drop table 表名;

            7、将表中记录清空:

            delete from 表名;

            8、显示表中的记录:

            select * from 表名;

            三、一个建库和建表以及插入数据的实例

            drop database if exists school; //如果存在SCHOOL则删除

            create database school; //建立库SCHOOL

            use school; //打开库SCHOOL

            create table teacher //建立表TEACHER

            (

            id int(3) auto_increment not null primary key,

            name char(10) not null,

            address varchar(50) default ’深圳’,

            year date

            ); //建表结束

            //以下为插入字段

            insert into teacher values(’’,’glchengang’,’深圳一中’,’1976-10-10’);

            insert into teacher values(’’,’jack’,’深圳一中’,’1975-12-23’);

            注:在建表中(1)将ID设为长度为3的数字字段:int(3)并让它每个记录自动加一:auto_increment并不能为空:not null而且让他成为主字段primary key(2)将NAME设为长度为10的字符字段(3)将ADDRESS设为长度50的字符字段,而且缺省值为深圳。varchar和char有什么区别 呢,只有等以后的文章再说了。(4)将YEAR设为日期字段。

            如果你在MySQL提示符键入上面的命令也可以,但不方便调试。你可以将以上命令原样写入一个文本文件中假设为school.sql,然后复制到c:\\下,并在DOS状态进入目录\\mysql\\bin,然后键入以下命令:

            mysql -uroot -p密码 < c:\\school.sql

            如果成功,空出一行无任何显示;如有错误,会有提示。(以上命令已经调试,你只要将//的注释去掉即可使用)。

     

    四、将文本数据转到数据库中

            1、文本数据应符合的格式:字段数据之间用tab键隔开,null值用\\n来代替。

            例:

            3 rose 深圳二中 1976-10-10

            4 mike 深圳一中 1975-12-23

            2、数据传入命令 load data local infile \"文件名\" into table 表名。

            注意:你最好将文件复制到\\mysql\\bin目录下,并且要先用use命令打表所在的库。

            五、备份数据库:

            1、mysqldump --opt school>school.bbb

            mysqldump --opt school>school.bbb
            (命令在DOS的\\mysql\\bin目录下执行)

            注释:将数据库school备份到school.bbb文件,school.bbb是一个文本文件,文件名任取,打开看看你会有新发现。

            后记:其实MySQL的对数据库的操作与其它的SQL类数据库大同小异,您最好找本将SQL的书看看。我在这里只介绍一些基本的,其实我也就只懂这些了, 呵呵。最好的MYSQL教程还是“晏子“译的“MYSQL中文参考手册“不仅免费每个相关网站都有下载,而且它是最权威的。可惜不是象\"PHP4中文手 册\"那样是chm的格式,在查找函数命令的时候不太方便。

            2、修改登录密码

            1) mysqladmin -u用户名 -p旧密码 password 新密码:

            例:mysqladmin -u root password 21century

            注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。

            2)直接修改user表的root用户口令:

            mysql> user mysql;
            mysql> update user set pasword=password('21century') where user='root';
            mysql> flush privileges;

            注:flush privileges的意思是强制刷新内存授权表,否则用的还是缓冲中的口令。

            3、测试密码是否修改成功:

            1)不用密码登录:

            [root@test1 local]# mysql
            ERROR 1045: Access denied for user: 'root@localhost' (Using password: NO)

            显示错误,说明密码已经修改。

            2)用修改后的密码登录:

            [root@test1 local]# mysql -u root -p
            Enter password: (输入修改后的密码21century)
            Welcome to the MySQL monitor. Commands end with ; or \g.
            Your MySQL connection id is 177 to server version: 3.23.48
            Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
            mysql>

            成功!

            这是通过mysqladmin命令修改口令,也可通过修改库来更改口令。

     

    4、启动和停止:

            启动:Mysql从3.23.15版本开始作了改动,默认安装后服务要用MySQL用户来启动,不允许root用户启动。

            如果非要用root用户来启动,必须加上--user=root参数(./safe_mysqld --user=root &)停止:mysqladmin -u root -p shutdown。

            5、导出meeting数据库:

            mysqldump -uroot -p21century meeting > db_meeting.sql

            导人dbname数据库:

            mysqldump -uroot -p21century dbname < xxx.sql

            导入数据库还可用类似于oracle中@my_script.sql的方式一次执行大量sql语句,这在使用mysqldump不起作用时非常有用。

            例:#./mysql -uroot -p < /home/xuys/db_meeting_2003.sql

            (注:create database、use databasename、create table和insert into语句都可写在上面的脚步文件中)

            6、给表改名:

            RENAME TABLE ztemp TO ztemp4;

            7、修改字段属性:

            ALTER TABLE bbabase CHANGE news_id id VARCHAR(5) NOT NULL;

            8、在表中的content后增加一字段:

            ALTER TABLE bbabase ADD leave_time DATETIME NOT NULL AFTER

     

     

     


    ----------------------------------------

     

     

     

     


    linux下安装mysql 2009-11-25 09:35:14  www.hackbase.com  来源:互联网
      linux下安装mysql    一、引言    想使用Linux已经很长时间了,由于没有硬性任务一直也没有系统学习,近日由于工作需要必须使用Linux下的MySQL。本以为有    Windows下使用SQL Server的经验,觉 ...
      linux下安装mysql
      
      一、引言
      
      想使用Linux已经很长时间了,由于没有硬性任务一直也没有系统学习,近日由于工作需要必须使用Linux下的MySQL。本以为有
      
      Windows下使用SQL Server的经验,觉得在Linux下安装MySql应该是易如反掌的事,可在真正安装和使用MySQL时走了很多弯路,遇见
      
      很多问题,毕竟Linux 和Windows本身就有很大区别。为了让和我一样的初学者在学习的过程中少走弯路,尽快入门,写了此文,希
      
      望对您有所帮助。
      
      
      二、安装Mysql
      
      1、下载MySQL的安装文件
      安装MySQL需要下面两个文件:
      MySQL-server-5.0.22-0.i386.rpm
      MySQL-client-5.0.22-0.i386.rpm
      http://download.mysql.cn/download_file/rpm/5.0/MySQL-server-5.0.22-0.i386.rpm
      http://download.mysql.cn/download_file/rpm/5.0/MySQL-client-5.0.22-0.i386.rpm
      2、安装MySQL
      rpm文件是Red Hat公司开发的软件安装包,rpm可让Linux在安装软件包时免除许多复杂的手续。该命令在安装时常用的参数是
      
      –ivh ,其中i表示将安装指定的rmp软件包,V表示安装时的详细信息,h表示在安装期间出现“#”符号来显示目前的安装过程。这个
      
      符号将持续到安装完成后才停止。
      1)安装服务器端
      在有两个rmp文件的目录下运行如下命令:
      [root@test1 local]# rpm -ivh MySQL-server-5.0.22-0.i386.rpm
      显示如下信息。
      warning: MySQL-server-5.0.9-0.i386.rpm: V3 DSA signature: NOKEY, key ID 5072e1f5
      Preparing...       ########################################### [100%]
      1:MySQL-server     ########################################### [100%]
      。。。。。。(省略显示)
      /usr/bin/mysqladmin -u root password 'new-password'
      /usr/bin/mysqladmin -u root -h test1 password 'new-password'
      。。。。。。(省略显示)
      Starting mysqld daemon with databases from /var/lib/mysql
      如出现如上信息,服务端安装完毕。测试是否成功可运行netstat看Mysql端口是否打开,如打开表示服务已经启动,安装成功。
      
      Mysql默认的端口是3306。
      [root@test1 local]# netstat -nat
      Active Internet connections (servers and established)
      Proto Recv-Q Send-Q Local Address      Foreign Address     State
      tcp  0  0 0.0.0.0:3306     0.0.0.0:*      LISTEN
      上面显示可以看出MySQL服务已经启动。
      2)安装客户端
      运行如下命令:
      [root@test1 local]# rpm -ivh MySQL-client-5.0.22-0.i386.rpm
      warning: MySQL-client-5.0.9-0.i386.rpm: V3 DSA signature: NOKEY, key ID 5072e1f5
      Preparing...    ########################################### [100%]
      1:MySQL-client  ########################################### [100%]
      显示安装完毕。
      用下面的命令连接mysql,测试是否成功。
      三、登录MySQL
      
      登录MySQL的命令是mysql, mysql 的使用语法如下:
      mysql [-u username] [-h host] [-p[password]] [dbname]
      username 与 password 分别是 MySQL 的用户名与密码,mysql的初始管理帐号是root,没有密码,注意:这个root用户不是
      
      Linux的系统用户。MySQL默认用户是root,由于初始没有密码,第一次进时只需键入mysql即可。
      [root@test1 local]# mysql
      Welcome to the MySQL monitor. Commands end with ; or \g.
      Your MySQL connection id is 1 to server version: 4.0.16-standard
      
      Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
      mysql>
      出现了“mysql>”提示符,恭喜你,安装成功!
      增加了密码后的登录格式如下:
      mysql -u root -p
      Enter password: (输入密码)
      其中-u后跟的是用户名,-p要求输入密码,回车后在输入密码处输入密码。
      
      注意:这个mysql文件在/usr/bin目录下,与后面讲的启动文件/etc/init.d/mysql不是一个文件。
      
      四、MySQL的几个重要目录
      
      MySQL安装完成后不象SQL Server默认安装在一个目录,它的数据库文件、配置文件和命令文件分别在不同的目录,了解这些目
      
      录非常重要,尤其对于Linux的初学者,因为 Linux本身的目录结构就比较复杂,如果搞不清楚MySQL的安装目录那就无从谈起深入学
      
      习。
      
      下面就介绍一下这几个目录。
      
      1、数据库目录
      /var/lib/mysql/
      
      2、配置文件
      /usr/share/mysql(mysql.server命令及配置文件)
      
      3、相关命令
      /usr/bin(mysqladmin mysqldump等命令)
      
      4、启动脚本
      /etc/rc.d/init.d/(启动脚本文件mysql的目录)
      五、修改登录密码
      
      MySQL默认没有密码,安装完毕增加密码的重要性是不言而喻的。
      
      1、命令
      usr/bin/mysqladmin -u root password 'new-password'
      格式:mysqladmin -u用户名 -p旧密码 password 新密码
      
      2、例子
      例1:给root加个密码123456。
      键入以下命令 :
      [root@test1 local]# /usr/bin/mysqladmin -u root password 123456
      注:因为开始时root没有密码,所以-p旧密码一项就可以省略了。
      
      3、测试是否修改成功
      1)不用密码登录
      [root@test1 local]# mysql
      ERROR 1045: Access denied for user: 'root@localhost' (Using password: NO)
      显示错误,说明密码已经修改。
      2)用修改后的密码登录
      [root@test1 local]# mysql -u root -p
      Enter password: (输入修改后的密码123456)
      Welcome to the MySQL monitor. Commands end with ; or \g.
      Your MySQL connection id is 4 to server version: 4.0.16-standard
      Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
      mysql>
      成功!
      这是通过mysqladmin命令修改口令,也可通过修改库来更改口令。
      
      六、启动与停止
      
      1、启动
      MySQL安装完成后启动文件mysql在/etc/init.d目录下,在需要启动时运行下面命令即可。
      [root@test1 init.d]# /etc/init.d/mysql start
      
      2、停止
      /usr/bin/mysqladmin -u root -p shutdown
      
      3、自动启动
      1)察看mysql是否在自动启动列表中
      [root@test1 local]# /sbin/chkconfig –list
      2)把MySQL添加到你系统的启动服务组里面去
      [root@test1 local]# /sbin/chkconfig – add mysql
      3)把MySQL从启动服务组里面删除。
      [root@test1 local]# /sbin/chkconfig – del mysql
      七、更改MySQL目录
      
      MySQL默认的数据文件存储目录为/var/lib/mysql。假如要把目录移到/home/data下需要进行下面几步:
      
      1、home目录下建立data目录
      cd /home
      mkdir data
      
      2、把MySQL服务进程停掉:
      mysqladmin -u root -p shutdown
      
      3、把/var/lib/mysql整个目录移到/home/data
      mv /var/lib/mysql /home/data/
      这样就把MySQL的数据文件移动到了/home/data/mysql下
      
      4、找到my.cnf配置文件
      如果/etc/目录下没有my.cnf配置文件,请到/usr/share/mysql/下找到*.cnf文件,拷贝其中一个到/etc/并改名为my.cnf)中。
      
      命令如下:
      
      [root@test1 mysql]# cp /usr/share/mysql/my-medium.cnf /etc/my.cnf
      
      5、编辑MySQL的配置文件/etc/my.cnf
      为保证MySQL能够正常工作,需要指明mysql.sock文件的产生位置。修改socket=/var/lib/mysql/mysql.sock一行中等号右边的
      
      值为:/home/mysql/mysql.sock 。操作如下:
      vi  my.cnf    (用vi工具编辑my.cnf文件,找到下列数据修改之)
      # The MySQL server
      [mysqld]
      port   = 3306
      #socket  = /var/lib/mysql/mysql.sock(原内容,为了更稳妥用“#”注释此行)
      socket  = /home/data/mysql/mysql.sock   (加上此行)
      
      6、修改MySQL启动脚本/etc/rc.d/init.d/mysql
      最后,需要修改MySQL启动脚本/etc/rc.d/init.d/mysql,把其中datadir=/var/lib/mysql一行中,等号右边的路径改成你现在
      
      的实际存放路径:home/data/mysql。
      [root@test1 etc]# vi /etc/rc.d/init.d/mysql
      #datadir=/var/lib/mysql    (注释此行)
      datadir=/home/data/mysql   (加上此行)
      
      7、重新启动MySQL服务
      /etc/rc.d/init.d/mysql start
      或用reboot命令重启Linux
      如果工作正常移动就成功了,否则对照前面的7步再检查一下。
      
      八、MySQL的常用操作
      
      注意:MySQL中每个命令后都要以分号;结尾。
      
      1、显示数据库
      mysql> show databases;
      +----------+
      | Database |
      +----------+
      | mysql  |
      | test    |
      +----------+
      2 rows in set (0.04 sec)
      Mysql刚安装完有两个数据库:mysql和test。mysql库非常重要,它里面有MySQL的系统信息,我们改密码和新增用户,实际上
      
      就是用这个库中的相关表进行操作。
      
      2、显示数据库中的表
      mysql> use mysql; (打开库,对每个库进行操作就要打开此库,类似于foxpro )
      Database changed
      
      mysql> show tables;
      +-----------------+
      | Tables_in_mysql |
      +-----------------+
      | columns_priv  |
      | db       |
      | func       |
      | host      |
      | tables_priv      |
      | user      |
      +-----------------+
      6 rows in set (0.01 sec)
      
      3、显示数据表的结构:
      describe 表名;
      
      4、显示表中的记录:
      select * from 表名;
      例如:显示mysql库中user表中的纪录。所有能对MySQL用户操作的用户都在此表中。
      Select * from user;
      
      5、建库:
      create database 库名;
      例如:创建一个名字位aaa的库
      mysql> create databases aaa;
      6、建表:
      use 库名;
      create table 表名 (字段设定列表);
      例如:在刚创建的aaa库中建立表name,表中有id(序号,自动增长),xm(姓名),xb(性别),csny(出身年月)四个字段
      use aaa;
      mysql> create table name (id int(3) auto_increment not null primary key, xm char(8),xb char(2),csny date);
      可以用describe命令察看刚建立的表结构。
      mysql> describe name;
      
      +-------+---------+------+-----+---------+----------------+
      | Field | Type  | Null | Key | Default | Extra                  |
      +-------+---------+------+-----+---------+----------------+
      | id  | int(3) |   | PRI | NULL  | auto_increment       |
      | xm  | char(8) | YES |   | NULL  |        |
      | xb  | char(2) | YES |   | NULL   |        |
      | csny | date  | YES |   | NULL  |        |
      
      +-------+---------+------+-----+---------+----------------+
      
      7、增加记录
      例如:增加几条相关纪录。
      mysql> insert into name values('','张三','男','1971-10-01');
      mysql> insert into name values('','白云','女','1972-05-20');
      可用select命令来验证结果。
      mysql> select * from name;
      +----+------+------+------------+
      | id | xm  | xb  | csny    |
      +----+------+------+------------+
      | 1 | 张三 | 男  | 1971-10-01 |
      | 2 | 白云 | 女  | 1972-05-20 |
      +----+------+------+------------+
      
      8、修改纪录
      例如:将张三的出生年月改为1971-01-10
      mysql> update name set csny='1971-01-10' where xm='张三';
      
      9、删除纪录
      例如:删除张三的纪录。
      mysql> delete from name where xm='张三';
      
      10、删库和删表
      drop database 库名;
      drop table 表名;
      
      九、增加MySQL用户
      
      格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码"
      例1、增加一个用户user_1密码为123,让他可以在任何主机上登录,并对所有数据库有查询、插入、修改、删除的权限。首先用以
      
      root用户连入MySQL,然后键入以下命令:
      
      mysql> grant select,insert,update,delete on *.* to user_1@"%" Identified by "123";
      例1增加的用户是十分危险的,如果知道了user_1的密码,那么他就可以在网上的任何一台电脑上登录你的MySQL数据库并对你的数据
      
      为所欲为了,解决办法见例2。
      
      例2、增加一个用户user_2密码为123,让此用户只可以在localhost上登录,并可以对数据库aaa进行查询、插入、修改、删除的
      
      操作(localhost指本地主机,即MySQL数据库所在的那台主机),这样用户即使用知道user_2的密码,他也无法从网上直接访问数据
      
      库,只能通过 MYSQL主机来操作aaa库。
      
      mysql>grant select,insert,update,delete on aaa.* to user_2@localhost identified by "123";
      
      用新增的用户如果登录不了MySQL,在登录时用如下命令:
      
      mysql -u user_1 -p -h 192.168.113.50 (-h后跟的是要登录主机的ip地址)
      
      十、备份与恢复
      
      1、备份
      
      例如:将上例创建的aaa库备份到文件back_aaa中
      
      [root@test1 root]# cd /home/data/mysql (进入到库目录,本例库已由val/lib/mysql转到/home/data/mysql,见上述第七
      
      部分内容)
      [root@test1 mysql]# mysqldump -u root -p --opt aaa > back_aaa
      
      2、恢复
      
      [root@test mysql]# mysql -u root -p ccc < back_aaa


    本篇文章来源于 黑客基地-全球最大的中文黑客站 原文链接:http://www.hackbase.com/tech/2009-11-25/58298.html

     

    mysql> show master status;

    mysql> show slave status\G

     

  • 数据统计

    • 访问量: 708653
    • 日志数: 415
    • 图片数: 1
    • 文件数: 3
    • 建立时间: 2008-12-07
    • 更新时间: 2015-07-14

    RSS订阅

    Open Toolbar