Let's Go!

发布新日志

  • java堆与栈 java String分配内存空间(详解)(转载)

    2011-02-23 13:18:37

    java堆与栈 java String分配内存空间(详解)

    http://hi.baidu.com/zojoyo/blog/item/99b24c24d30d390b4d088d46.html

    栈内存

    堆内存

    基础类型,对象引用(堆内存地址

    new创建的对象和数组,

    存取速度快

    相对于栈内存较慢

    数据大小声明周期必须确定

    分配的内存由java虚拟机自动垃圾回收器管理。动态分配内存大小

    共享特性

    栈中如果有字符串,则直接引用

    如果没有,开辟新的空间存入值

    new一次在堆内存中生成一个新的对象。

    创建之后值可以改变

    String类声明后则不可改变    

    一、栈内存

    基础类型int, short, long, byte, float, double, boolean, char和对象引用

     

    栈的共享特性

    String str1 = "abc";
    String str2 = "abc";
    System.out.println(str1==str2); //true

    1、编译器先处理String str1 = "abc";它会在栈中创建一个变量为str1的引用,然后查找栈中是否有abc这个值,如果没找到,就将abc存放进来,然后将str1指向abc

    2   接着处理String str2 = "abc";在创建完b的引用变量后,因为在栈中已经有abc这个值,便将str2直接指向abc。这样,就出现了str1str2同时均指向abc的情况。

    二、堆内存

    newnewarrayanewarraymultianewarray等指令建立

       要注意: 我们在使用诸如String str = "abc";的格式定义类时,总是想当然地认为,创建了String类的对象str。担心陷阱!对象可能并没有被创建!而可能只是指向一个先前已经创建的 对象。只有通过new()方法才能保证每次都创建一个新的对象。 由于String类的immutable性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

    三、  ==   内存地址比对

    String str1 = "abc";
    String str2 = "abc";
    System.out.println(str1==str2); //true    str1
    str2同时指向 栈内存 中同一个内存空间

    String str3 = "abc";
    String str4 = new String("abc") ;

    System.out.println(str3 == str4);    //flase str3值在栈内存中,str4值在堆内存中

     

    String hello = "hello" ;

    String hel = "hel" ;

    String lo = "lo" ;

    System.out.println(hello == "hel" + "lo") ; //true

    //两个常量相加,先检测栈内存中是否有hello如有有,指向已有的栈中的hello空间

    System.out.println(hello == "hel" + lo) ;   //flase

    System.out.println(hello == hel + lo) ;     //flase

     //lo是在常量池中,不检查栈内存,在堆中产生一个新的hello

     

     四、  equals  值进行比对

     public boolean equals(Object anObject)

    将此字符串与指定的对象比较。当且仅当该参数不为 null,并且是与此对象表示相同字符序列的 String 对象时,结果才为 true

     String str5 = "abc";
    String str6 = new String("abc") ;

    System.out.println(str5.equals(str6));    //true   str5的值str6的值比对

     五、  intern    栈中值的内存地址

     

    Public String intern()

    当调用 intern 方法时

    1、如果池已经包含一个等于此 String 对象的字符串(用equals(Object) 方法确定),则返回池中的字符串。

    2、将此 String 对象添加到池中,并返回此 String 对象的引用。

     

    String s7 = new String("abc") ;

    String s8 = "abc" ;

     

    System.out.println(s7 == s7.intern()) ;//flase

    System.out.println(s8 == s7.intern() );//true

     

    1.检查栈内存中有没有abc对象如果有

    2.s7指向poolabc

  • 软件自动化测试框架设计参考准则 (转载)

    2011-02-23 09:35:37

    软件自动化测试框架设计参考准则

      测试框架是在所有不同的测试自动化阶段定义的一整套指导准则:需求分析阶段、脚本设计阶段、执行阶段、报告和维护阶段。框架即对于内部复杂架构的一种包装,这样的包装可以使得最终用户方便的使用。框架还具有对于流程标准的强制执行性。

      目前为止,还没有一种关于如何开发测试框架以及在开发过程中需要考虑哪些因素的准则。有很多记载着各式各样的测试框架以及它们各自是如何工作的白皮书,但是这些白皮书中还没有任何一篇文档是记录着测试框架设计共同需要考虑的因素。本文基于测试框架需求,涵盖了测试框架各个方面以及一些必备的基本要素。

      1. 自动化测试框架的类型 – 目前普遍存在的框架有以下几种:

      ●  数据驱动框架 – 当测试对象流程固定不变(仅仅数据发生变化),可以使用这种测试框架。测试数据是由外部提供的,比如说Excel表、XML等等

      ●  关键字驱动框架 – 这种自动化测试框架提供了一些通用的关键字,这些关键字适用于各种类型的系统。它还为自动化测试工具和被测系统提供了抽象性。举个例子,它可以使用相同的测试用例来测试类似的Web和Windows系统。

      ●  混合型的框架 – 混合型自动化测试框架同时具有数据驱动型和关键字驱动型框架的优点。这种测试框架不但具有通用的关键字,还有基于被测系统业务逻辑的关键字。例如“登录”、“退出”是可以被使用的仅局限于某系统的关键字。

      2. 不要过分的改造 – 自动化测试框架应该尽可能的使自动化测试工具发挥它自己强大的功能,而不是通过实现新的关键字来重新定义整套语言。开发一套关键字驱动的自动化测试框架的代价是很大的而且非常耗时。开发一套混合型的自动化测试框架的代价就相对较小而且开发周期短。

      3. 可重用性 – 测试框架应该尽最大可能提高可重用性。把单独的Action组合成业务逻辑可以提供可重用性。举个例子,可以把类似于“输入用户名”、“输入密码”和“点击登录”这些Action组合成一个可被重用的模块:“登录”

      4. 支持系统的不同版本 – 自动化测试框架应该允许重复使用基线化脚本,这样可以保证这份脚本能被用来对被测系统的多个版本进行测试。对不同系统的支持有两种方式:

      ●  复制和修改 – 这种方法包含了新建基线脚本的一个拷贝、修改这份拷贝用以测试特定版本的项目。51Testing软件测试网 ^b1o.N8W0Y

      ●  重用和升级 – 这种方法包含了重用基线脚本、提供一个此脚本的升级和优化用以测试特定版本的项目。这样做可以最大化的保障可重用性,这也是推荐的方法。

      5. 支持脚本版本化 – 测试脚本应该被储存在类似于CVS、微软的VSS等版本控制工具中。这样做可以保障在灾难发生的时候可以被恢复。

      6. 将开发和发布环境分开 – 自动化应当和其它开发项目同等看待。测试脚本应当在一个测试环境下创建和调试。一旦测试脚本测试通过后唯一该做的就是将它部署到发布环境。在紧急发布版本的情况也同样适用这种方法。

      7. 外部可配置性 – 脚本的可配置项应当被保存在一个外部文档中。系统的URL、版本、路径等都可以被视作可配置项放在外部文件中。这样做可以使得在不同的环境中都可以执行测试脚本。需要注意的是外部配置文件的路径不要写死,如果把它写死了虽然在任何环境中都还是可以运行脚本,但是每次只能在一个环境运行。配置文件的路径使用相对路径即可解决这个问题。

      8. 自身可配置性 – 理想的测试框架应该是自身可配置的。一旦部署到系统中之后应当不需要再做任何手工配置,脚本应当自动配置完成一些必要的设置。

      9. 任何对象改动引起的变动应该是最小的 – 自动化过程中最为常见的问题是对象识别的变更。测试框架应该支持可以很容易的来完成这些修改。这可以通过将所有的对象识别设置储存在一个共享文件来实现。这个文件可以是XML文件、Excel文件、数据库或者自动化所特有的格式。这里有两种可能的方式来实现对象识别设置的方式:51Testing软件测试网PX6}0j&re

      ●  静态方法 – 这种方法中,所有对象定义都在测试最初被加载到内存中。任何对象定义变更只能通过停止和重新运行测试来实现。

      ●  动态方法 – 对象定义是通过需求拉动的。这种方式和静态方式比较而言显得较为缓慢。但是对于非常大的脚本而言,并且对象识别需要在运行时做修正的情况下,动态方法是适用的。

      10. 测试执行 – 自动化测试框架也许需要满足以下需求(基于实际需求)

      ●  执行单独的测试用例;

      ●  批量执行测试用例(一组测试用例);

      ●  只执行失败的测试用例;

      ●  可以在前一个(一组)测试用例执行结果的基础上,执行下一个(一组)测试用例;

      根据实际需求还会有许多其他情况。一个框架可能无法实现所有这些需求,但它应具有足够的灵活性以适应今后此类需求。51Testing软件测试网?#q!U l!Y%K1n

      11. 状态监测 - 一个框架应允许实时监控执行状态,一旦失败能够发出警报。这样可以在出现failure之后迅速反馈。

      12. 报表 – 不同的系统对报表有不同的需求,有时候需要一组测试的整体报表,有时候只需要单个测试用例级别的测试执行报表。一个好的测试框架应该有足够的弹性来按需支持不同的报表。

      13. 发生更改的时候对测试工具尽量小的依赖性 – 一些测试脚本的更改可能只能在打开测试工具后,在测试工具中进行修改,然后保存。测试脚本应该在没有测试工具的情况下也可以对脚本进行更改。这样的实现可以减少license的购买从而为公司节省开支。这样的实现还可以让所有想去修改脚本的人无需安装测试工具也可以很方便的对脚本进行修改。

      14. 方便的调试 – 调试在自动化过程中占据了大量的时间,因此在调试这个过程中需要加以特别的关注。关键字驱动的测试框架因为使用了外部的数据源(比如Excel数据表)去读取脚本中的关键字和测试过程,所以较难调试。

      15. 日志 - 生成日志是执行的重要组成部分。在一个测试案例的不同点生成调试信息这是非常重要的。这些信息有助于快速地找到问题的范围,同时缩短了修改时间。

      16. 易用性 - 该框架应易于学习和使用。对框架的人员培训费时且昂贵。有一个好文档的框架更容易理解和使用。

      17. 灵活性 - 框架应该足够的灵活,以适应任何改进,而不会影响已有的测试案例。

      18. 性能的影响 – 框架还应考虑对执行性能的影响。一个复杂的框架会增加脚本的加载或执行时间,这一定不是我们所期望的。像缓存技术,当执行时编译所有代码到单个库中等...只要可能都应该用于性能的改善。

      19. 框架支持工具 – 开发一些外部工具来完成任务,这对框架设计会有帮助。这是一些例子:51Testing软件测试网:N v7nsq

      ●  从本地文件夹上传脚本到QC51Testing软件测试网F}'Z]F&J Ah

      ●  结合库文件到当前打开的脚本51Testing软件测试网+[SF1nR"]N

      ●  同步本地和QC上的脚本文件

      20. 编码标准 - 编码标准应确保脚本的一致性,可读性和易于维护。编码标准应包含下列内容:

      ●  命名规范(变量、子程序、函数、文件名、脚本名称等),例如i_VarName为整数变量, fn_i_FuncName为返回值是整数的函数;

      ●  库、子程序、函数的头部注释。这应包含,如版本历史,创建者,最后修订者,最后修订日期,说明,参数,示例;

      ●  对象命名规范。例如txt_FieldName为一个文本框;

      我们应该把自动化测试看作是一个开发项目,而不仅仅是记录和回放事件。先有一个良好的框架,再开始自动化测试,这样可以确保较低的维护成本。当你在开发一个框架,进行框架的需求分析时,可以参考本文谈到的这些准则。

    google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);


  • 软件测试中通用数据生成方法

    2011-02-23 09:32:36

    软件测试中通用数据生成方法

    http://softtest.chinaitlab.com/zixun/810015.html

    软件测试中非常重要的一个工作就是生成和维护测试数据,而这个工作恰恰是繁琐、重复而极易出错的。无疑找到一种通用的数据生成方法是极具意义的。本文阐释了如何使用脚本语言 PHP,加上简单的 ini 配置文件来达到这个目的的。

      测试的数据生成和维护在软件测试中是非常重要的一环。很多用例实际上就是在修改所测程序的输入数据以确保程序的逻辑是按照自己的预期进行地。

      比如我们测试一个用户登录系统,我们需要测试正常用户名 + 正常密码、正常用户名 + 错误密码、错误用户名 + 错误密码等基本的用例。在执行用例之前,就需要事先在数据库中设置好相应的数据,比如有一条记录为正常用户名 + 正常密码,然后我们在登陆界面输入该用户名和密码,预期结果为正常登陆。

      不同的程序有不同格式的输入数据。但不管格式千变万化,我们总可以把它们归结为基于行和列的格式,就像数据库中的表一样。一行为一条记录,每一条记录都有相同的字段组成,每一个字段有自己的数据格式,字段和字段之间可能有分隔符。

      我们可以在执行每一个用例时,手工修改数据,然后再执行用例。但这样存在一些问题。

      1. 重复,数据重用性差。当前用例所需的数据很有可能在下个用例中被破坏了。

      2. 效率低,尤其是当数据格式比较复杂,而且又需要大量数据的时候。

      3. 不灵活。但数据发生变动的时候,数据的维护成本会很高。

      4. 容易出错。

      那有没有一种方法来解决这个问题呢?答案是肯定的。下面我们一起来实现一个简单的工具来解决这个问题。

      需要实现的基本功能

      首先我们来列举一下这个软件测试工具需要实现的基本功能:

      1. 通用性:能够描述各种不同格式的数据。

      2. 扩展性:当需要新的数据格式时,可以任意扩展。

      3. 易用性:配置文件不易复杂。

      4. 跨平台:我们需要一款可以在windows、linux、FreeBSD等系统下面运行的工具。

      我们选择的开发工具

      我们选择的开发工具是 PHP,配置文件采用了 ini 格式的文件。

      之所以选择 PHP,是因为 PHP 是解释性脚本语言,其弱类型的特点以及强大的数组、字符串处理功能,十分适合我们这种应用场合。而且 PHP 有着良好的扩平台性,使用 PHP 开发的脚本基本上不用修改就可以在各个平台下面运行。

      之所以选择 ini 格式的文件来作为配置,是因为 ini 文件相比较于 xml 而言比较简单。而且程序处理起来也非常的方便。在 PHP 中使用 parse_ini_file 的内置函数就可以解析整个 ini 文件。

      配置语法

      首先我们需要来定义一下我们的配置语法。前面讲到,数据是由行和列组成,每一列中有若干字段,每一个字段有自己的生成数据类型,有自己的前缀,字段和字段之间还有分隔符。我们最终的配置语法格式如下:

      清单一:example.ini

      [field1]

      datatype="list, range=[10-20]"

      prefix="int_"

      postfix=" "

      [field2]

      datatype="list, range=[A-Z, a-z]"

      prefix="char_"

      postfix=" "

      [field3]

      prefix=""

      datatype="list, range=[abc,123,xyz, 100-110]"

      postfix=" "

      [field4]

      prefix=""

      datatype="list, range=[100-200:2]"

      postfix=" "

      我们来解释一下语法的格式:

      1. 字段名使用[]引起来。后面使用 key=value 的形式来定义这个字段的属性。

      2. 字段有三个基本的属性:datatype 指定字段的取值范围,prefix 设定字段的前缀,postfix 则设定字段的后缀。

      3. datatype 中最基本的数据类型就是 list,一个无所不包的列表。你所需要指定的就是这个字段的取值范围参数 range。

      4. range 参数可以采用 1-10 这样的区间表达,也可以用逗号“ , ”来连接多个区间或者元素。区间还可以指定递增的步长。

      上面的 example.ini 文件中定义了四个字段,字段和字段之间使用两个空格分隔,第一个字段的取值范围为 10-20,前缀为 int_,第二个字段取值范围是大小写英文字母,前缀为 char_,第三个字段取值范围是混合的,第四个字段则从 100 到 200,递增步长为 2 。

      清单二:生成的数据

      int_10 char_A abc 100

      int_11 char_B 123 102

      int_12 char_C xyz 104

      int_13 char_D 100 106

      int_14 char_E 101 108

      int_15 char_F 102 110

      int_16 char_G 103 112

      int_17 char_H 104 114

      int_18 char_I 105 116

      int_19 char_J 106 118

      代码实现:

      第一步:解析 ini 文件

      error_reporting(0);

      $iniFile = $argv[1]; // 第一个参数为配置文件。

      $dataCount = $argv[2]; // 第二个参数为要生成的记录数。

      $fields = parse_ini_file($iniFile, true); // 将 ini 配置文件转换为一个数组。

      第二步:生成每一个字段的取值列表

      foreach($fields as $fieldName => $field)

      {

      $list = array();

      $equalPos = strpos($field['datatype'], '='); // 取得等号的为止。 range=[]

      $range = substr($field['datatype'], $equalPos + 2, -1); // 取得 range 的列表(去掉了 [])

      $items = explode(',', $range); // 得到所有的 item 元素。

      /* 循环处理每一个 item,如果是一个区间,则调用 range 函数。 */

      foreach($items as $item)

      {

      if(strpos($item, '-'))

      {

      list($min, $max) = explode('-', $item);

      $list = array_merge($list, range($min, $max)); // 追加到 field 的 list 列表中。

      }

      else

      {

      $list[] = $item;

      }

      }

      $field['list'] = $list; // 将最终的 list 列表赋值给 field 。

      $field['pointer'] = 0; // 初始化这个列表的指针。

      $fields[$fieldName] = $field; // 写回整个 fields 数组。

      }

      第三步:循环输出数据

      /* 循环输出数据。 */

      for($i = 0; $i < $dataCount; $i ++)

      {

      foreach($fields as $fieldName => $field)

      {

      $pointer = $field['pointer'];

      /* 如果指针已经到到了列表的尾部,重新指向列表开始。 */

      if($pointer == count($field['list'])) $pointer = 0;

      echo $field['prefix']; // 输出前缀。

      echo $field['list'][$pointer]; // 输出当前指针所对应的列表中的取值。

      echo $field['postfix']; // 输出后缀。

      $pointer ++;

      $fields[$fieldName]['pointer'] = $pointer;

      }

      echo "\n";

      }

      这样我们用了不到 50 行的代码就完成了一个基本的数据生成工具。这其实已经可以满足基本的数据生成任务了。但是还需要进一步进行完善。

      需要进一步完善的地方

      第一:数据的扩展性

      虽然 list 类型已经足够灵活,但有时候还无法满足需要。比如一个比较复杂的字段,由若干小字段组成。这时可以将这个复合字段再通过一个 ini 文件来定义,这样就有了无限可能。

      比如,我们在 example.ini 文件中增加一个日期的字段,格式为 yyyy 年 mm 月 dd 日的格式

      清单三:example.ini 中新增一个字段

      [field5]

      prefix=""

      datatype="custom" " 定义这个字段的数据类型为 custom

      datacfg="custom.ini" " 定义这个字段的配置文件为 custom.ini

      postfix=""

      清单四:custom.ini

      [field5.1]

      prefix=""

      datatype="list, range=[1980-1999]"

      postfix=" 年 "

      [field5.2]

      prefix=""

      datatype="list, range=[1-12]"

      postfix=" 月 "

      [field5.3]

      prefix=""

      datatype="list, range=[1-31]"

      postfix=" 日 "

      这可以通过 php 中的递归函数来实现这个解析。即当解析到一个字段发现是自定义类型的时候,就读取这个字段所对应的 ini 配置文件,然后再解析它的每一个字段。具体的代码就不给出了,读者朋友们可以尝试实现。

      第二:列表可以更加灵活

      列表 range 参数还可以更加灵活,比如:

      1. 可以指定步长:range=[1-100:2],表示从 1 到 100,步长为 2 递增。

      2. 可以指定输出的格式:range=[1-100:2]&format=0.2f,这个地方的 format 可以是 sprintf 函数的格式标签。

      3. 可以指定是否随机。现在生成的数据是按照列表中的顺序来生成的。可以通过一个 rand 参数来指定是否随机。

      第三:不同的输出格式

      我们现在输出的是行与列的格式,其实我们还可以定义其他不同的输出格式。比如输出为数据库的 insert sql 语句。输出为 xml 格式的数据。这些实现起来都不是特别的麻烦,代码中做些处理就可以了。

      结束语

      PHP 是一款非常优秀的脚本语言(虽然它主要用在 web 开发上)。使用 PHP 可以快速地写出很多小工具来帮助我们来完成某个任务。本文只是给出了一个数据生成方法的简单实现,各位读者朋友完全可以发挥自己的想象,开发出更加灵活、好用的工具来。具体到我们公司的应用,我们现在基本上可以使用这个工具来生成各种各样不同的测试数据。而且有了这些固定的测试数据,就可以实现自动化测试。
    google_protectAndRun("render_ads.js::google_render_ad", google_handleError, google_render_ad);
  • [java]junit4

    2011-02-22 11:20:11

    Junit4,与3.x有所区别

    [java]junit4 - believefym的专栏 - CSDN博客.rar(147 KB)


    1. 测试类不需要extends TestCase,代之以annotation,即测试类(不需要extends TestCase)的方法只要有@Test就可以了
    2. 测试方法命名不需要一定要以test开头

    package junit;

    public class Unit ...{
        private int data;
       
        public Unit(int data)...{
            this.data = data;
        }
        public boolean test()...{
            return true;
        }
       
        public boolean equals(Object o)...{
            if(o instanceof Unit)...{
                return ((Unit)o).data == data;           
            }
           
            return false;
        }
       
        public void exception()...{
            if (this.data==0)
                throw new IndexOutOfBoundsException("exception in Unit");
        }
    }

    可以用eclipse自动生成测试类,选中要测试的类,然后new -junit test case

    测试类:
    package junit;

    import org.junit.*;

    public class UnitTest ...{

        private Unit unit1 = new Unit(1);
        private Unit unit2 = new Unit(2);   
       
        @BeforeClass
        public static void setUpBeforeClass() throws Exception ...{
            System.out.println("setUpBeforeClass");
        }

        @AfterClass
        public static void tearDownAfterClass() throws Exception ...{
            System.out.println("tearDownAfterClass");
        }

        @Before
        public void setUp() throws Exception ...{
            System.out.println("setUp");
        }

        @After
        public void tearDown() throws Exception ...{
            System.out.println("tearDown");
        }

        @Test
        public void notestTest() ...{    // 方法名不以test开头
            //fail("Not yet implemented");
            Assert.assertTrue(unit1.test());
        }

        @Test
        public void testEqualsObject() ...{
            //fail("Not yet implemented");
            Assert.assertEquals(unit1, new Unit(1));
            Assert.assertEquals(unit1, unit2);
        }

        @Test(expected = IndexOutOfBoundsException.class)
        public void testException() ...{
            //fail("Not yet implemented");
            new Unit(0).exception();
        }
    }

    测试结果如下


    为了进行TestSuit,再增加一个testcase
    package junit;

    public class Unit2 ...{
        public boolean test()...{
            return true;
        }
    }

    package junit;


    import org.junit.Test;

    public class Unit2Test ...{

        @Test
        public void testTest() ...{
            //fail("Not yet implemented");
            org.junit.Assert.assertTrue(new Unit2().test());
        }

    }

    ==================================================================================
    增加一个TestSuit(使用ecilpse的new -junit Test Suit只能找到3.x风格的extends TestCase的测试类,不知为何)
    package junit;

    import org.junit.runner.RunWith;
    import org.junit.runners.Suite;
    import org.junit.runners.Suite.SuiteClasses;

    @RunWith(Suite.class)
    @SuiteClasses( ...{ UnitTest.class, Unit2Test.class })
    public class Suit ...{
    }

    TestSuit测试结果


    以下是控制台输出信息,跟测试类的各种annotation有关


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

  • lamp整合安装包 appserv

    2011-01-18 17:06:38

     http://www.appservnetwork.com/

  • LoadRunner之编写Tuxedo脚本(转载)

    2011-01-17 16:00:04

     

    LoadRunner之编写Tuxedo脚本

    当我们所测试的项目是Tuxedo通信,并且不能使用工具录制脚本,手头只有一些数据(比如服务器报文等等)的时候,我们只有通过手工编写测试脚本啦。

      我暂且把编写Tuxedo脚本的工作分为三个重要部分吧。

      一、脚本调研部分

      1、了解服务器端Tuxedo版本,本地控制机安装Tuxedo客户端,配置环境变量;

      2、了解WSL访问方式(IP:Port);

      3、了解研发使用的Tuxedo服务名、数据缓冲类型(如CARRAY、FML32等)、缓冲区长度(如1024*1024*3);

      4、了解这个缓冲区类型的缓冲结构(包括哪些字段、这些字段的属性(数据类型、数据长度等),以及这些字段要放置什么数据,是任意数据还是指定的死数据);

      5、了解报文(报文长度、内容、详细信息;哪些数据需要做参数化;调研报文的格式,是否可以通过在脚本中组装报文,是否可以通过从报文文件中获取报文[从文件中读取的保温不能做参数化处理]),文章最后有对报文的组装形式简要说明;

      6、了解报文发送后服务器返回的数据内容、长度等,用作在脚本中判断事务是否成功。

      二、脚本编写部分

      1、在脚本开头书写脚本详细描述,也就是脚本的名称、脚本语言、作者、脚本编写时间,当然这些都是注释掉的,也是常识,但也是我们容易忽视的地方。

      2、在脚本中设定Tuxedo环境变量。

       static char *env_allow_array[] = {

        "WSNADDR=//163.192.1.126:90900",

        "FLDTBLDIR32=c:\bea\tuxedo8.1\etc",

        "FIELDTBLS32=ftpflds",

        NULL

        };
     


    3、定义脚本中变量类型

      4、初始化数据

      5、lrt_tpalloc分配缓冲区空间

      pFml = (FBFR32 *)lrt_tpalloc("FML32",0,4096);

      6、lrt_Finitialize32初始化缓冲区

      lrt_Finitialize32((FBFR32 *)pFml);

      7、组装报文,lrt_Fadd32_fld根据缓冲区结构把字段信息添加到缓冲区

      lrt_Fadd32_fld((FBFR32*)pFml,"id=167813666","value=\220\074""3\001\n",LRT_END_OF_PARMS);

      8、发送lrt_tpcall请求

      lrt_tpcall( "SVCName", (char *)pFml, 0, &MsgRcv, &rcvlen, 0 );

      9、判断返回的信息是否正确(看你是不是有这个需求)

      10、使用lrt_tpfree释放申请的请求和应答buffer空间(也就是对有lrt_tpalloc获取的缓冲区进行释放)

      lrt_tpfree((char *)pFml);

      11、对每个变量和每一步执行代码做注释,要养成写完脚本后做注释的习惯

      三、脚本调试部分

      对与调试部分对脚本来说是十分重要的一块,写完脚本后,必须验证脚本。运行脚本对不同的日志提示进行相应的调试即可,可以通过设置断点(F9),单步执行(F10),增加日志函数等方法调试脚本。由于脚本调试过程中遇到的问题多样化,解决的办法也各不相同,这里不再赘述。

      补充:

      组装报文的形式(据我知道的):

      1、在脚本中直接通过strcat()函数和lr_eval_string()函数组合或使用sprintf()函数和lr_eval_string()函数组合组装报文(在其中可以对报文做参数化操作),然后把报文串赋值给一个字符串。

      2、如果本次性能测试不要求对报文做参数化,并且项目组给的报文数据是以二进制格式或其他格式的文件(如****.bin、***文件)存在的话,我们也可以写C代码读取数据文件信息(具体读取文件操作的代码可以参照VuGen帮助文档),把报文发给后端。

      手工编写脚本是一项技术性要求很强的工作,更能提高测试工程师的技术水平。尽管通过纯手工编写的脚本也对服务器施加了压力,但是它忽视了用户端的处理逻辑。在尽量模拟真实环境中用户操作的原则下,这样是否更能真实模拟用户的操作,还有待进一步研究。

     

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

  • Loadrunner的Tuxedo脚本分析,基本流程和基本函数介绍

    2011-01-17 15:47:06

     

    #include "lrt.h"
    #include "replay.vdf"

    vuser_init()
    {


     //=================================================================================================================
     // 第一个交易
     
        // 1.设置变量组: Sets a list of environment variables.
     lrt_set_env_list(env_allow_array);

        // 2.从配置文件读取环境变量:  Adds variables to the environment from a file.
     lrt_tuxreadenv("C:\\Program Files\\test\\test8\\etc\\tuxedoenv.ini", "TUXCOMM");

        //事务开始
     lr_start_transaction("01_login");

        // 3. Modifies an existing environment value or adds a value to the environment.
     lrt_tuxputenv("ULOGPFX=c:\\log\\330100-300302");

     lr_think_time(25);

        // 4.分配空间: Allocates a new buffer.
     // The lrt_tpalloc function allocates a new buffer and returns a pointer to a buffer of specified type. Since some buffer types
     // require initialization before they can be used, lrt_tpalloc initializes a buffer after it is allocated, before it is returned.
     data_0 = lrt_tpalloc("FML32", "", 65000);

     // 5.进行初始化: Initializes an existing FML buffer.
       //  注意:  data_0 在replay.vdf 中已经被定义,同时在此处被初始化,初始化后,就可以向里面添加field-value对了.
     lrt_Finitialize32((FBFR32*)data_0);

     // 6.向data_0中加field-value对,就是传给后台tuxedo服务的数据:
     lrt_Fadd32_fld((FBFR32*)data_0, "id=167772364", "value=330100", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=167772373", "value=10.253.1.138", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=167772374", "value=000000000000", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=167772375", "value=1", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=167772422", "value=300302", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=167772423", "value=000000", LRT_END_OF_PARMS);

       // 7. 分配空间给data_1: Allocates a new buffer.
     data_1 = lrt_tpalloc("FML32", "", 65000);


     // 8. 使用lrt_tpcall 调用服务,发送的数据是data_0,服务器的返回信息保存在data_1中.
     // lrt_tpcall Sends a service request and awaits its reply.
        // int lrt_tpcall ( char *svc, char *idata, long ilen, char **odata, long *olen, long flags );

     // svc  Requested service (can be parameterized). 
     // idata  Data portion of the request. 
     // ilen  Length of request data to send. 
     // odata  Reply data. 
     // olen  Length of reply data. 
     // flags  Valid flags: TPNOTRAN- SVC will not be performed on behalf of caller's transaction,
     //    TPNOCHANGE - buffer type of reply data is not allowed to change, TPNOBLOCK - request not sent if blocking condition exists,
     //    TPNOTIME - caller immune to blocking timeouts, TPSIGRSTRT - any interrupted system calls are re-issued after lrt_tpcall. 

     tpresult_int = lrt_tpcall("new_css_Login",
      data_0,
      0,
      &data_1,
      &olen,
      0);
     /* Returned FML32 buffer 1 */


     // 9.使用lrt_save32_fld_val 从服务器返回信息中获取需要的数据:
     // The lrt_save32_fld_val function saves the current value of an FML32 buffer to a parameter specified by paramName.
     // lrt_save32_fld_val(fbfr, "id=xxxx", 0, "parameter");
     // lrt_save32_fld_val(fbfr, "name=xxxx", 0, "parameter");
     lrt_save32_fld_val((FBFR32*)data_1,"id=167772363",0,"returnValue") ;
        // print
     lr_output_message("返回值:%s",lr_eval_string("{returnValue}") ) ;

        // 10.如果出错,则停止事务Aborts the current transaction if the previous Tuxedo function resulted in an error.
     lrt_abort_on_error();

     


     //11.释放之前的空间和连接:
     // The lrt_tpfree function frees a buffer that was previously obtained by either lrt_tpalloc or lrt_tprealloc.
     lrt_tpfree(data_0);
     lrt_tpfree(data_1);
     // The lrt_tpterm function removes a client from a System/T application.
     // If the client is in transaction mode, then the transaction is rolled back.
     lrt_tpterm();


        // 第一个交易已经完成.
        //=================================================================================================================

     // 进行第二个交易:
     
        // 其他的操作和第一轮操作类似:
        //分配新的空间
     data_0 = lrt_tpalloc("FML32", "", 65535);
     // 重新初始化:
     lrt_Finitialize32((FBFR32*)data_0);
     //设置数据
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554633", "value=5084013", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554637", "value=9901", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554640", "value=1", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554642", "value=920041", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=42755520", "value=0", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=67109070", "value=0", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=67109071", "value=1", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=67109076", "value=Q", LRT_END_OF_PARMS);
        // 为返回值分配空间:
     data_1 = lrt_tpalloc("FML32", "", 65535);
     // 调用服务:
     tpresult_int = lrt_tpcall("csi_01",
      data_0,
      0,
      &data_1,
      &olen,
      0);
     /* Returned FML32 buffer 2 */
     lrt_abort_on_error();
     

    // 释放
     lrt_tpfree(data_0);
     lrt_tpfree(data_1);
     lrt_tpterm();


       // 第二个交易完成
       //=================================================================================================================

     lr_end_transaction("01_login", LR_AUTO);

     


     lr_start_transaction("05_select");

       
     // 第三个及以后的所有交易,都与之前的交易类似:
     //=================================================================================================================

     lr_think_time(55);
     data_0 = lrt_tpalloc("FML32", "", 65535);
     lrt_Finitialize32((FBFR32*)data_0);
     
     lrt_Fadd32_fld((FBFR32*)data_0, "id=1101360", "value=1", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=1101360", "value=0", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=1101360", "value=0", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=1101360", "value=0", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554633", "value=5084013", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554637", "value=9901", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554640", "value=1", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=33554642", "value=110001", LRT_END_OF_PARMS);

     data_1 = lrt_tpalloc("FML32", "", 65535);
     tpresult_int = lrt_tpcall("csi_01",
      data_0,
      0,
      &data_1,
      &olen,
      0);
     /* Returned FML32 buffer 3 */
     lrt_abort_on_error();

     lrt_tpfree(data_0);
     lrt_tpfree(data_1);
     lrt_tpterm();


    //=================================================================================================================

     data_0 = lrt_tpalloc("FML32", "", 65535);
     lrt_Finitialize32((FBFR32*)data_0);
     
     lrt_Fadd32_fld((FBFR32*)data_0, "id=1101225", "value=0", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=1101307", "value=0", LRT_END_OF_PARMS);
     lrt_Fadd32_fld((FBFR32*)data_0, "id=168873390", "value=", LRT_END_OF_PARMS);

     data_1 = lrt_tpalloc("FML32", "", 65535);
     tpresult_int = lrt_tpcall("csi_01",
      data_0,
      0,
      &data_1,
      &olen,
      0);
     /* Returned FML32 buffer 11 */
     lrt_abort_on_error();
     
     lrt_tpfree(data_0);
     lrt_tpfree(data_1);
     lrt_tpterm();
     lr_end_transaction("05_select", LR_AUTO);

    //=================================================================================================================

     return 0;
    }

     

     

     

    Action()
    {
     return 0;
    }

    vuser_end()
    {
     return 0;
    }

    replay.vdf

    #ifndef TUXVDF_H
    #define TUXVDF_H
    char* data_0;
    char* data_1;

    /* Returned FML32 buffer 1
    field: "id=33554633", "occurrence=0", "value=5084013"
    field: "id=33554637", "occurrence=0", "value=9901"
    Reply buffer */

    #endif /* TUXVDF_H */

     

    loadrunner wdiff对比返回结果,分析异同,进行关联
    也可以监测服务器收到的和返回的信息,分析

     

     

  • java中的ssh框架

    2011-01-11 10:09:16

    http://wenwen.soso.com/z/q104191536.htm

    struts框架 hibernate框架 spring框架
    结合方式: 1. struts + hibernate
    2. spring + hibernate
    3. ssh结合
    请高手们谈下 那种结合比较好

    问题补充   个人感觉 struts 跟 spring 功能都差不多 只不过struts是继承 spring是接口
    ssh结合的话 C层感觉有点乱 功能冲突
    ssh结合有必要吗? 有什么特点啊?

     

    你说的3中方式我都用过,结合3年的工作经验,人认为ssh结合最好用,spring管理事物处理,struts控制页面跳转,hibernate处理数据层东西,各司其职,如果单单的用其中的一种或者两中都有很大的不方便。struts建议采用struts2,比struts1好用的多。。。答案补充 建议楼主每个框架结合都做一个简单的项目,只有自己真正动手做过,才能真正体会到你这个问题的结果。

     

    说分多少层,每层干什么用都是假的,到最后还是根据实际需要来分层。
    你做个最简单的程序,像学校的习题或者毕业设计之类的,根本就不用分层照样能满足需求

    没有最好,只有最合适。

    你喜欢怎么用就怎么用,你觉得不用某一层那你就别用,到你感觉不够用的时候,你对原来没用的那一层理解会非常深。人家说什么就照做,永远只能停留于表面理解,无法深刻体会。

     

     

    在项目中,SSH分为三层:Struts表示层,Spring业务逻辑层,Hibernate持久化层。具体来说,是这样的:(7)Struts框架提供了极丰富的视图组件,扩展了Web应用。Hibernate实现对象-关系映射(ORM),封装操作的数据库语句。Spring是一个依赖于控制反转(Inversion of Control,IoC)设计模式的轻量级框架,具有很好的松散耦合特性,Spring对Hibernate提供大量的封装好的类。在这里我们可以看到SSH的完美结合,整合后项目得到了最大的优化,因为(讲Spring整合)Struts中Action的实例生成不再由Struts自己负责,而交Spring容器去管理 。Hibernate的SessionFactory的配置交于了Spring,即我们可以不要hibernate.cfg.xml,而将sessionFactory的配置作为bean来交给Spring的配置文件等。Spring对Hibernate进行了封装,而Hibernate对数据库进行了封装。它们的完美结合使项目更加完善。

     

    更详细一点的看下面

    表示层(The Presentation Layer)
    一般来讲,一个典型的Web应用的的末端应该是表示层。 很多Java发者也理解Struts所提供的。 象业务逻辑之类的被打包到org.apache.struts.Action., 因此,我们很赞成使用Struts这样的框架。
    下面是Struts所负责的:
    * 管理用户的请求,做出相应的响应。
    * 提供一个Controller ,委派调用业务逻辑和其它上层处理。
    * 处理异常,抛给Struts Action
    * 为显示提供一个模型
    * UI验证。
    以下条款,不该在Struts显示层的编码中经常出现。 它们与显示层无关的。
    * 直接的与数据库通信,例如JDBC调用。
    * 与你应用程序相关联的业务逻辑以及校验。
    * 事物管理。
    在表示层引入这些代码,则会带来高偶合和麻烦的维护。

    持久层(The Persistence Layer)
    典型的Web应用的另一个末端是持久层。这里通常是程序最容易失控的地方。开发者总是低估构建他们自己的持久框架的挑战性。系统内部的持续层不但需要大量调试时间,而且还经常缺少功能使之变得难以控制,这是持久层的通病。 还好有几个ORM开源框架很好的解决了这类问题。尤其是Hibernate。 Hibernate为java提供了OR持久化机制和查询服务, 它还给已经熟悉SQL和JDBC API 的Java开发者一个学习桥梁,他们学习起来很方便。 Hibernate的持久对象是基于POJO和Java collections。此外,使用Hibernate并不妨碍你正在使用的IDE。
    请看下面的条目,你在持久层编码中需要了解的。
    * 查询对象的相关信息的语句。 Hibernate通过一个OO查询语言(HQL)或者正则表达的API来完成查询。 HQL非常类似于SQL-- 只是把SQL里的table和columns用Object和它的fields代替。 你需要学习一些新的HQL语言; 不管怎样,他们容易理解而文档也做的很好。 HQL是一种对象查询的自然语言,花很小的代价就能学习它。
    * 如何存储,更新,删除数据库记录。
    * 象Hibernate这类的高级ORM框架支持大部分主流数据库,并且他们支持 Parent/child关系,事物处理,继承和多态。

    业务层(The Business Layer)
    一个典型Web应用的中间部分是业务层或者服务层。 从编码的视角来看,这层是最容易被忽视的一层。 而我们却往往在UI层或持久层周围看到这些业务处理的代码,这其实是不正确的,因为它导致了程序代码的紧密偶合,这样一来,随着时间推移这些代码很难维护。幸好,针对这一问题有好几种Frameworks存在。 最受欢迎的两个框架是Spring和PicoContainer。 这些为也被称为microcontainers,他们能让你很好的把对象搭配起来。 这两个框架都着手于‘依赖注射’(dependency injection)(还有我们知道的‘控制反转’Inversion of Control=IoC)这样的简单概念。 这篇文章将关注于Spring的注射(译注:通过一个给定参数的Setter方法来构造Bean,有所不同于Factory), Spring还提供了Setter Injection(type2),Constructor Injection(type3)等方式供我们选择。 Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handler(事物管理控制)、Object Factoris(对象工厂)、service objects(服务组件)——都通过XML来配置联系起来。
    后面我们会举个例子来揭示一下Spring 是怎样运用这些概念。
    业务层所负责的如下:
    * 处理应用程序的 业务逻辑和业务校验
    * 管理事物
    * 允许与其它层相互作用的接口
    * 管理业务层级别的对象的依赖。
    * 在显示层和持久层之间增加了一个灵活的机制,使得他们不直接的联系在一起。
    * 通过揭示 从显示层到业务层之间的Context来得到business services。
    * 管理程序的执行(从业务层到持久层)。

    Spring框架和Hibernate框架有较大的区别,Hibernate是一个对象持久化工具,通过其强大的O/R映射功能将Java对象与存放于关系数据库中的数据进行映射,避免了开发人员使用大量的SQL语句,通过JDBC底层编程的方式对数据库进行操作。一般来说,业务层适合用Spring,而持久层适合用Hibernate。
    Spring框架最大的优点是可以动态替换业务对象;核心是一个实现了IoC(Inversion of Control)模式的轻量级容器(Container);是开发效率很高,使用POJO(纯粹Java对象)的,优秀的轻量级的J2EE开发框架。
    关于什么时候使用这些框架,在项目比较大的时候使用,会大大节省开发成本的投入,大家都按照统一的标准来,能节约时间。但是如果项目很小,那还是不要使用了,因为使用框架需要配置很多东西,会觉得乱七八糟的,完全没有必要了,用一句话来说就是杀鸡焉用牛刀。

     

     

     

    我感觉spring和struts 结合并不是太好,spring 和 hibernate结合很好使,不过我感觉spring的mvc不如struts好使,所以
    平常用的还是ssh多,但是hibernate在复杂的数据库中并不好使,在复杂的数据库时,还是用jdbc。或ibatis

    答案补充

    spring功能要比sturts多,在着实现接口要比继承更灵活,
    结合后只是spring 将hibernate的一些东西包涵了,
    用的灵活的话结合后,开发简单而且快,不熟悉的话反而更乱

     

     

  • mysql取出以上用户名(去除重复),score值最高的所有记录,查出重复记录

    2011-01-06 16:15:42

    tt 表:
    有如下数据:

    insert into tt values('yy1',35) ;
    insert into tt values('yy1',36) ;
    insert into tt values('yy1',357) ;
    insert into tt values('yy1',351) ;


    insert into tt values('yy2',35) ;
    insert into tt values('yy2',36) ;
    insert into tt values('yy2',357) ;
    insert into tt values('yy2',351) ;

    insert into tt values('yy3',35) ;
    insert into tt values('yy3',36) ;
    insert into tt values('yy3',357) ;
    insert into tt values('yy3',351) ;

    insert into tt values('yy4',351) ;

     

    1.取出以上用户名(去除重复),score值最高的所有记录 :

     
     select name ,max(score) as max_score  from tt group by name ;

    其他聚合函数:
    select name ,sum(score) as max_score  from tt group by name ;
     
     select name ,min(score) as max_score  from tt group by name ;

     
     
     查出重复的记录:
     
     select name,score from tt group by name having count(name) > 2 ;
     
     
    select name,max(score) max_score from tt group by name having count(name) > 2 ;
     

     

  • mysql下如何执行sql脚本

    2011-01-06 15:47:35

    mysql下如何执行sql脚本

    首要步骤(一般可省略):
    开启mysql服务(默认是开机时就自动运行了):
    控制面板-->管理工具-->服务,在里面找到名称为mysql的项,双击就可看它的服务状态是启动还是停止,把它设为启动

    连接mysql:
    在命令行下输入 mysql -h localhost -u root -p回车,然后输入密码即可;或直接运行mysql自带的连接工具,然后输入密码即可.

    1.编写sql脚本,假设内容如下:

    create database dearabao;
    use dearabao;
    create table niuzi (name varchar(20));

    保存脚本文件,假设我把它保存在F盘的hello world目录下,于是该文件的路径为:F:\hello world\niuzi.sql


    2.执行sql脚本,可以有2种方法:
    第一种方法:
    在命令行下(未连接数据库),输入 mysql -h localhost -u root -p123456 < F:\hello world\niuzi.sql (注意路径不用加引号的!!) 回车即可.
    第二种方法:
    在命令行下(已连接数据库,此时的提示符为 mysql> ),输入 source F:\hello world\niuzi.sql (注意路径不用加引号的) 或者 \. F:\hello world\niuzi.sql (注意路径不用加引号的) 回车即可


    在程序初始化时一般会把要执行的SQL语句放到一个SQL文件,在程序安装时自动执行,其实就是批处理执行SQL命令。同样,可以手动执行sql文件,具体步骤如下:
           1、使用root帐户登录到MySQL服务器;
           2、执行source命令:
            mysql> source c:/test.sql
            注意:文件路径中建议使用“/”,如果使用“\”,要首先进行转义即“\\”,否则可能会出现错误。

           另外还有一个load命令可以批量插入数据,但是这个对文件中数据格式的要求比较严格,否则容易出现错误,很少使用。


    mysql 查看所有用户的语句

    输入指令select user();
     

  • Delete、Drop、Truncate的比较

    2011-01-03 11:33:30

    http://java-007.javaeye.com/blog/450636

     

    2009-08-16
    Delete、Drop、Truncate的比较
    关键字: delete、drop、truncate
    相同点:truncate和不带where子句的delete, 以及drop都会删除表内的数据

    不同点:
    1. truncate和 delete只删除数据不删除表的结构(定义)
    drop语句将删除表的结构被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态.

    2.delete语句是DML,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.
    truncate,drop是DDL, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.

    3.delete语句不影响表所占用的extent, 高水线(high watermark)保持原位置不动
    显然drop语句将表所占用的空间全部释放
    truncate 语句缺省情况下见空间释放到 minextents个 extent,除非使用reuse storage; truncate会将高水线复位(回到最开始).

    4.速度,一般来说: drop> truncate > delete

    5.安全性:小心使用drop 和truncate,尤其没有备份的时候.否则哭都来不及
    使用上,想删除部分数据行用delete,注意带上where子句. 回滚段要足够大.
    想删除表,当然用drop
    想保留表而将所有数据删除. 如果和事务无关,用truncate即可. 如果和事务有关,或者想触发trigger,还是用delete.
    如果是整理表内部的碎片,可以用truncate跟上reuse stroage,再重新导入/插入数据

    附加DDL,DML,DCL区别:
    DDL is Data Definition Language statements. Some examples:

    * CREATE - to create objects in the database
    * ALTER - alters the structure of the database
    * DROP - delete objects from the database
    * TRUNCATE - remove all records from a table, including all spaces allocated for the records are removed
    * COMMENT - add comments to the data dictionary
    * GRANT - gives user's access privileges to database
    * REVOKE - withdraw access privileges given with the GRANT command

    DML is Data Manipulation Language statements. Some examples:

    * SELECT - retrieve data from the a database
    * INSERT - insert data into a table
    * UPDATE - updates existing data within a table
    * DELETE - deletes all records from a table, the space for the records remain
    * CALL - call a PL/SQL or Java subprogram
    * EXPLAIN PLAN - explain access path to data
    * LOCK TABLE - control concurrency

    DCL is Data Control Language statements. Some examples:

    * COMMIT - save work done
    * SAVEPOINT - identify a point in a transaction to which you can later roll back
    * ROLLBACK - restore database to original since the last COMMIT
    * SET TRANSACTION - Change transaction options like what rollback segment to use

     

     

     

     


    DML、DDL、DCL区别
    总体解释:
    DML(data manipulation language):
           它们是SELECT、UPDATE、INSERT、DELETE,就象它的名字一样,这4条命令是用来对数据库里的数据进行操作的语言
    DDL(data definition language):
           DDL比DML要多,主要的命令有CREATE、ALTER、DROP等,DDL主要是用在定义或改变表(TABLE)的结构,数据类型,表之间的链接和约束等初始化工作上,他们大多在建立表时使用
    DCL(Data Control Language):
           是数据库控制功能。是用来设置或更改数据库用户或角色权限的语句,包括(grant,deny,revoke等)语句。在默认状态下,只有sysadmin,dbcreator,db_owner或db_securityadmin等人员才有权力执行DCL

    详细解释:
    一、DDL is Data Definition Language statements. Some examples:数据定义语言,用于定义和管理 SQL 数据库中的所有对象的语言
          1.CREATE - to create objects in the database   创建
          2.ALTER - alters the structure of the database   修改
          3.DROP - delete objects from the database   删除
          4.TRUNCATE - remove all records from a table, including all spaces allocated for the records are removed
          TRUNCATE TABLE [Table Name]。
      下面是对Truncate语句在MSSQLServer2000中用法和原理的说明:
      Truncate table 表名 速度快,而且效率高,因为:
      TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。
      DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
      TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。
      对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。
      TRUNCATE TABLE 不能用于参与了索引视图的表。
           5.COMMENT - add comments to the data dictionary 注释
           6.GRANT - gives user's access privileges to database 授权
           7.REVOKE - withdraw access privileges given with the GRANT command   收回已经授予的权限

    二、DML is Data Manipulation Language statements. Some examples:数据操作语言,SQL中处理数据等操作统称为数据操纵语言
           1.SELECT - retrieve data from the a database           查询
           2.INSERT - insert data into a table                    添加
            3.UPDATE - updates existing data within a table    更新
           4.DELETE - deletes all records from a table, the space for the records remain   删除
           5.CALL - call a PL/SQL or Java subprogram
           6.EXPLAIN PLAN - explain access path to data
           Oracle RDBMS执行每一条SQL语句,都必须经过Oracle优化器的评估。所以,了解优化器是如何选择(搜索)路径以及索引是如何被使用的,对优化SQL语句有很大的帮助。Explain可以用来迅速方便地查出对于给定SQL语句中的查询数据是如何得到的即搜索路径(我们通常称为Access Path)。从而使我们选择最优的查询方式达到最大的优化效果。
           7.LOCK TABLE - control concurrency 锁,用于控制并发

    三、DCL is Data Control Language statements. Some examples:数据控制语言,用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等
           1.COMMIT - save work done 提交
            2.SAVEPOINT - identify a point in a transaction to which you can later roll back 保存点
           3.ROLLBACK - restore database to original since the last COMMIT   回滚
           4.SET TRANSACTION - Change transaction options like what rollback segment to use   设置当前事务的特性,它对后面的事务没有影响.

     

     

     

    turncate,delete,drop异同点分析 收藏
     从功能上区别,turncate,delete都是只删除表中的数据,而表结构,索引,约束等都保持不变;而 drop语句将删除表的结构以及被依赖的约束(constrain),触发器(trigger),索引(index); 依赖于该表的存储过程/函数将保留,但是变为invalid状态。

    再分析turncate与delete异同:

    相同点: turncate talbe 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。

    不同点:

    1 事务管理:delete语句是dml,这个操作会放到rollback segement中,事务提交之后才生效;如果有相应的trigger,执行的时候将被触发.delele可以回滚。  truncate是ddl, 操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger.

               

    2 速度:turncate table比delete速度快,且使用的系统和事务日志资源少。

                原因是delete语句每次删除一行,并在事务日志中为删除的每一行记录一项;而turncate table通过释放存储表数据的数据页来删除数据,并且只在事务日志中记录页的释放。  

    3 对于由FOREIGN   KEY 约束引用的表,不能使用   TRUNCATE   TABLE,而应使用不带   WHERE   子句的   DELETE   语句。由于   TRUNCATE   TABLE   不记录在日志中,所以它不能激活触发器。

    应用中,如果不再需要该表时,用drop

    如果想要保留表结构,但要删除所有记录,用turncate

    如果只删除部分记录,用带where条件的delete

     

     

     

     

    JVM内存分配 收藏
    如果对JVM的内存分配不合理,应用程序运行中常常用抛出java.lang.OutOfMemory和java.lang.OutOfMemoryError: PermGen space异常。

    所以我们要对JVM调优以避免出现此类问题。

    JVM的内存分配主要通过这几个参数设定:-Xms -Xmx -XX:PermSize -XX:MaxPermSize

    我们先对几个概念进行解释:

          ◆堆(Heap)和非堆(Non-heap)内存

      按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配。堆是在 Java 虚拟机启动时创建的。”在JVM中堆之外的内存称为非堆内存(Non-heap memory)”。可以看出JVM主要管理两种类型的内存:堆和非堆。简单来说堆就是Java代码可及的内存,是留给开发人员使用的;非堆就是JVM留给自己用的,所以方法区、JVM内部处理或优化所需的内存(如JIT编译后的代码缓存)、每个类结构(如运行时常数池、字段和方法数据)以及方法和构造方法的代码都在非堆内存中。

        堆内存主要存放类实例(Instance)等,而非堆区为java永久生成对象(Permanate generation)如,class对象、方法对象这些可反射(reflective)对象分配内存,Class被loader的时候就会被放到非堆区。

      ◆堆内存分配

      JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4。默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。因此服务器一般设置 -Xms、-Xmx相等以避免在每次GC 后调整堆的大小。

          说明:如果-Xmx不指定或者指定偏小,应用可能会导致java.lang.OutOfMemory错误,此错误来自JVM不是Throwable的,无法用try...catch捕捉。

      ◆非堆内存分配

      JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。

         如果应用程序使用了大量第三方的jar包,非堆内存分配过小就会导致:java.lang.OutOfMemoryError: PermGen space。GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的APP会LOAD很多CLASS的话,就很可能出现PermGen space错误。这种错误常见在web服务器对JSP进行pre compile的时候。

      ◆JVM内存限制(最大值)

      首先JVM内存限制于实际的最大物理内存(废话!呵呵),假设物理内存无限大的话,JVM内存的最大值跟操作系统有很大的关系。简单的说就32位处理器虽然可控内存空间有4GB,但是具体的操作系统会给一个限制,这个限制一般是2GB-3GB(一般来说Windows系统下为1.5G-2G,Linux系统下为2G-3G),而64bit以上的处理器就不会有限制了。

          通过上面对JVM内存管理的介绍我们已经了解到JVM内存包含两种:堆内存和非堆内存,另外JVM最大内存首先取决于实际的物理内存和操作系统。

          我们在实际配置中还要注意以下几点:

          1) 参数中-Xms的值大于-Xmx,或者-XX:PermSize的值大于-XX:MaxPermSize;

      2) -Xmx的值和-XX:MaxPermSize的总和超过了JVM内存的最大限制,比如当前操作系统最大内存限制,或者实际的物理内存等等。说到实际物理内存这里需要说明一点的是,如果你的内存是1024MB,但实际系统中用到的并不可能是1024MB,因为有一部分被硬件占用了。

    示例:-Xmx1024m -Xms1024m -XX:PermSize:256m -XX:MaxPermSize:512m

  • 阿里巴巴马云:最怕别人把我看成圣人和教父(转载)

    2010-12-31 12:58:36

    阿里巴巴马云:最怕别人把我看成圣人和教父
    http://www.sina.com.cn  2010年12月25日 02:39  21世纪经济报道[ 微博 ]

      侯继勇

      10年间,坐观西子湖,马云却永远心潮澎湃。从一名教师、翻译,到全球市值最大电子商务公司的领袖,他是无数创业青年心中的“偶像”。

      但10年后的当下,坐在记者对面的他却用全力要打碎这个“偶像”的幻境。“我不知道创业教父是什么东西,也从来没有想过做创业教父!”阿里巴巴集团主席兼CEO马云大声说。

      企业的成功靠的是什么,通常的解答是企业领袖的远见,技术、管理的创新;而马云将个人的成功归结于这个时代。“是我的同事,是这个时代,是中国互联网的高速发展,给了我成功的机会,并不是每个人遇到这些东西,靠机缘,甚至运气。”

      马云说,一个人有他的时代,有他的环境,只有在这样的时代,才有这样的成功,创业者不能重走别人的路。

      “我跟所有人一样,一开始榜样是比尔·盖茨、李嘉诚。后来发现他们不是的榜样,没法学习,太大太强。真正的榜样一定在你附近,你做小饭馆,榜样就是斜对面的小饭馆,他为什么门口排队而我们家服务员比客户多?他是你的榜样。”

      马云认为,“失去榜样的一代”,一定比“自己这一代”更强:“我爷爷认为我父亲不如他,你父亲认为我不如他,事实却是一代比一代强。我20岁的时候,提不出今天的90后提出的问题,他们更强,能做更大的事业。社会正因此而进步。”

      “上一代人都会告诉下一代,我们比你们这一代难多了。结果是每一代人都超过了上一代。”他的不经意回答,仿佛打开了10年的坎坷成败后的心结。

      平凡人不凡事

      《21世纪》:如果你现在一无所有,还是一个学生,你有信心说自己会成功,会成为未来的创业的教父吗?

      马云:我不知道创业教父是什么东西?我从来没有想做过创业教父。

      现在我各方面的能力都比十年以前的我强得多,假如我再回到十年以前,按照今天的能力重新走一遍,我一定走不过来。很多天时地利人和的事情过去了。十年以前的我比现在刚毕业的大学生更糟糕,大学考了好几次,比我能干的人很多。

      这十年走下来,绝大部分的人犯的错误我也犯过,我自己也说不清楚为什么我能走出来,这是讲实话。不是我自己有多么能干,没有我的团队,没有这个时代,没有互联网,没有中国的改革开放,那什么都没有。

      我父亲跟我说过,早生20年我肯定给抓进去了;晚生20年,我会坐在这跟另外一个马云对话。时代给了我的机会。

      《21世纪》:你觉得自己是个传奇吗?

      马云:我挺喜欢听《传奇》这首歌,但我不是传奇,我是平凡的人。

      我最怕别人把我看成圣人、教父。晕了。我跟大家没什么区别,是淘宝和阿里巴巴给了我光环,不是我给淘宝、阿里巴巴、支付宝光环。是两万多名员工帮了我,不是我帮了他们。我跟每个人都一样。我经历了一个好的时代。

      《21世纪》:阿里巴巴创业的“十八罗汉”也是凡人?这些平凡人如何做成了不凡事?

      马云:其实就像我选择员工、员工选择我一样。选择什么样的员工?我选择平凡的人。什么是平凡的人?就是没把自己当精英的人。我不喜欢那些精英,精英眼睛都长在这(指着头顶)。这个世界没有一个人就可以做成的事,需要团队与配合。

      平凡的人有平凡的梦想,不是为社会主义奋斗终生、改变全人类,而就是买房、买车、娶老婆、生孩子,这是人最基本的梦想。这些梦想真实,为自己干,我觉得这样的员工我喜欢、实在。

      阿里巴巴创业十八人都是平凡的人,平凡的人在一起做一件不平凡的事。什么是伟大的事?伟大的事就是无数次平凡、重复、单调、枯燥的做同一件事情,就会成为伟大。我们相互影响,相互激励,一路走下去,一切就会变得不平凡。

      创业之痛与乐

      《21世纪》:现在社会不乏激情,但不足10%的创业成功率让人惶惑,怎么办?

      马云:创业其实是很艰辛的。我一方面鼓励大家创业,另一方面我想告诉大家一个很现实的问题:100个人创业95个人死掉,连声音都没听见。还有4个人,你是看着他们死的。最后剩下1个人,你看到他成功了。

      这个人很勤奋但未必是最勤奋的,这个人很努力很聪明,但未必是最努力最聪明的。有很多的机缘、有很多的因素使得他成功。

      创业者要永远去想,我是为五年以后十年以后创业,不是为今天。我希望大家既要有激情但更要有耐性。要有像兔子一样的速度,但要像乌龟一样有耐心。

      《21世纪》:很多创业者无法平衡自己的工作和家庭,你是怎么做的?

      马云:真正的创业者是平衡不了的。你如果选择了创业这条路,你就没办法想平衡。

      创业者应该做到把生活和工作融为一体,在里面获得乐趣。今天如果有谁说,我可以把工作和生活分的很开,我相信这是职业经理人,我也不相信他的企业会做的很好。

      我年轻的时候,最大的理想是早上在伦敦吃早饭,中午在巴黎吃午饭,晚上到布宜诺斯艾利斯沙滩上走走,觉得太美了。今天我觉得世界上最残酷的事情就是这样,我天天在飞,去日本早上去晚上就回来,回来赶会议,却也快乐。我也得到家人的支持,都已经适应了。

      《21世纪》:创业者面对许多诱惑,如何在永不放弃与选择放弃之间平衡?

      马云:要想成功一定要永不放弃,克服各种困难,但是你学会放弃的时候你才开始进步。假如这是一堵墙,你撞在墙上永不放弃的撞还是撞不过去,学会放弃退一步看一看,从边上绕过去。永不放弃的是使命感、价值观。

      中国式超越

      《21世纪》:热钱涌向电子商务,你觉得未来电子商务会朝一个什么样的方向发展?

      马云:我希望很多学生去看看中国本土的电子商务,其发展远远超过欧美。不管大家信不信,10年以后70%左右的商务都会以电子商务形式展开,这是时代的未来。

      美国电子商务发展比较艰难,尽管今天美国有的eBay、亚马逊等。美国整个传统商业的环境非常好,银行体系非常好,零售体系非常好,信用体系比较好,这使电子商务只是美国商务中的小小的补充而已。中国不同,由于整个商务环境,整个零售体系、物流体系、信息体系、诚信体系都比较糟糕,所以电子商务就有可能成为整个中国商务体系的主要框架。

      在中国,电子商务只是开始,他将重塑中国的整个商业环境,成为中国面向未来的核心竞争力。这就是后发优势。

      《21世纪》:十年前,你讲电子商务未来的时候,没人听得懂,觉得假大空,你如何说服你的同事坚持过来的?

      马云:我跟我同事讲话的时候,是希望唤醒他们心中的共鸣。我讲的也许是错的,但我相信我在讲的话。很多人演讲的话全是对的,但是他们自己不相信。忽悠跟不忽悠的区别是什么?忽悠是自己不相信让人家相信;真实是我相信,并相信你们慢慢也会相信。

      我们看到的是愿景,我是为未来工作,我绝不为今天工作。

      《21世纪》:中国的商业环境存在哪些问题?

      马云:今年发生了富士康事件、国美事件、360和腾讯事件。我们每个人在想什么呢?我们天天想的是打败竞争对手,整个社会非常浮躁。每个人都希望把自己的企业越来越强大,越来越大,越来越壮。

      我们的人都学会了埋怨,埋怨政府、埋怨体制、埋怨社会、埋怨没有机会,总是埋怨,而自己好像没有一点问题。

      我一直在思考一个问题,生态这样了,心态这样了,我们得不断地研究自己的姿态,每个人研究自己做事的方法。我相信心态不好,姿态一定不好,心态和姿态不好的话,整个生态是会越来越差。

      也许我们应该停下来做些事情,思考如何把自己的心态调整更好,如何把自己的姿态做的更好,如何保持商业的生态。比如互联网,就不是消灭谁,而是完善谁。

  • LR9系列安装报错解决(a previous installation has not completed.)

    2010-12-30 10:14:30

    LR9系列安装报错解决(Setup has determined that a previous installation has not completed.)

    在一个新的XP系统中装HP LoadRunner 9.10,点击安装后提示“Setup has determined that a previous installation has not completed.
    You should restart the system in order to complete this process.”

    重启电脑后问题还存在,用网上下的deletelicense.exe和优化大师清处注册表信息也不行。 后来从网上找到一种可以解决的方法,那就是:

    1. 打开临时文件夹,开始—>运行—>输入%temp%
    2. 找到“Prereq_Mgr.HP_LoadRunner_9.10.log”文件,这个文件记录着不能安装的原因。

    我的这个日志文件记录在一个新的XP系统中装HP LoadRunner 9.10,点击安装后提示“Setup has determined that a previous installation has not completed.
    You should restart the system in order to complete this process.”

    重启电脑后问题还存在,用网上下的deletelicense.exe和优化大师清处注册表信息也不行。 后来从网上找到一种可以解决的方法,那就是:

    1. 打开临时文件夹,开始—>运行—>输入%temp%
    2. 找到“Prereq_Mgr.HP_LoadRunner_9.10.log”文件,这个文件记录着不能安装的原因。

    我的这个日志文件记录如下:
    [04/23/09 12:58:31] INFO: (IsRebootRequired) The registry value [PendingFileRenameOperations] exists under [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager] and cannot be ignored

    3、删除注册表项(如果要操作注册表,最好要把注册表备份好,防止误操作)
    把注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager下的项PendingFileRenameOperations删除。

    再安装HP LoadRunner 9.10就可以正常安装了!
    如下:
    [04/23/09 12:58:31] INFO: (IsRebootRequired) The registry value [PendingFileRenameOperations] exists under [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager] and cannot be ignored

    3、删除注册表项(如果要操作注册表,最好要把注册表备份好,防止误操作)
    把注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager下的项PendingFileRenameOperations删除。

    再安装HP LoadRunner 9.10就可以正常安装了!
     

     

     

  • LR/QTP 提示以前安装没有完成,要求重启的问题

    2010-12-28 13:54:38


    LR/QTP 提示以前安装没有完成,要求重启的问题


    之前朋友电脑安装过QTP,再次安装提示以下错误“安装程序已确定以前安装未完成。您应重新启动系统以便完成此过程”,便建议他清理下注册表,就可以了。

    今天自己重装系统,再装QTP/LR时,也出现了类似的错误提示,郁闷了,C盘是完全格式化的,
    怎么也会有这样的提示呢...也没有论坛上提到的问题存在,为什么还是不行呢...再次清理所有临时文件和注册表,才成功安装。


    总结如下:
    1、用优化大师清理注册表、历史文件记录和临时文件
    2、搜索注册表是否存在pendingoperation键值,若有,二话不说,删掉...
    3、重启电脑

    打开注册表编辑器,在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\ Control\Session Manager中找到PendingFileRenameOperations项目,并删除它。这样就可以清除安装暂挂项目


    注册表和文件都删除干净就应该能重装上。
    注册表中记得是第二,第三个文件夹中的software下都有qtp文件,必须都删了才行。

     

    还有一个QTP卸载的清除工具:

    http://knowledgeinbox.com/downloads/qtp/qtp-clean-uninstaller-tool/

    QTPCleanUninstallerV2.10.zip(29.5 KB)

     

  • 记录_忘记root密码后怎么办?之Redhat篇

    2010-12-27 16:53:34

     linux字符界面和图形界面切换
    1、硬盘安装的linux,在系统图形界面启动后,可使用Ctrl+Alt+F1~6切换到字符界面,再用Ctrl+Alt+F7切换到图形界面。
    对于使用虚拟机安装的linux,由于虚拟机屏蔽了Ctrl+Alt键,必须使用其他热键:Ctrl+Alt+shift+F1~6切换到字符界面;使用Alt+F7返回到图形界面。
    2、如果为了每次启动直接进入字符界面,则要修改etc/inittab文件,将启动级别由5改为3即可

     

    1. 首先使用上面的方法进入到 grub启动的引导界面

       使用Alt+F7返回到图形界面
       注意,光标要进入到虚拟机中,否则点击键盘实际上没有对虚拟机起作用。

    忘记root密码后怎么办?之Redhat篇
     
      
       1. 在出现grub画面时,用上下键选中你平时启动linux的那一项(别选dos哟),然后按e键
      2. 再次用上下键选中你平时启动linux的那一项(类似于kernel /boot/vmlinuz-2.4.18-14 ro root=LABEL=/),然后按e键
      3. 修改你现在见到的命令行,在相应的位置而不是末尾---加入single,结果如下:
       kernel /boot/vmlinuz-2.4.18-14 single ro root=LABEL=/
      4. 回车返回,然后按b键启动,即可直接进入linux命令行
         sh-2.05#
         现在,你便可以改变根命令,键入:
     
         bash# passwd root
         bash# jonathan
         bash# jonathan
       
     
    你会被要求重新键入口令来校验。结束后, 口令就会被改变,你便可以在提示下键入 reboot 来重新引导;然后,象平常一样登录为根用户。

     

     

     

     
    2010-08-04
    linux忘记root密码怎么办 linux字符界面和图形界面切换
    文章分类:操作系统

    Linux忘记root密码怎么办?                                     
    在机器启动到grub进行操作系统选择时,对于Redhat linux:
    用上下键将光标放在linux系统上,按“e”
    在有kernel那一行按“e”,输入“空格 single”,然后回车
    按“b”,启动,系统会自动进入单用户模式,
    使用passwd root命令,按提示输入新口令
    修改口令后,输入reboot 命令重启系统即可
    对于SUSE linux:
    先按"esc"键,从grub的图形界面转至字符界面
    然后,用上下键将光标放在linux系统上,按“e”
    在有kernel那一行按“e”,输入“空格 1”,然后回车
    按“B”启动,系统会自动进入“runlevel 1”。
    然后执行“passwd”,按提示输入新口令
    修改完口令后,输入reboot命令重启系统即可。
    linux字符界面和图形界面切换
    1、硬盘安装的linux,在系统图形界面启动后,可使用Ctrl+Alt+F1~6切换到字符界面,再用Ctrl+Alt+F7切换到图形界面。
    对于使用虚拟机安装的linux,由于虚拟机屏蔽了Ctrl+Alt键,必须使用其他热键:Ctrl+Alt+shift+F1~6切换到字符界面;使用Alt+F7返回到图形界面。
    2、如果为了每次启动直接进入字符界面,则要修改etc/inittab文件,将启动级别由5改为3即可

     

     

    忘记了以前用的ORACLE的用户和密码   该怎么办?

    问题补充:

    忘记的是登陆SQL*PLUS的用户和密码

     

    *

       
    #7楼 得分:1回复于:2008-05-26 20:08:49
    you can enter single mode or rescue mode mode to modify you root password, how to enter these mode please ask google or baidu.

    *

    *

       
    #8楼 得分:0回复于:2010-01-12 14:41:44
    一、按e键进入grub编辑模式

    二、选择RHEL(Elsmp)按e键进入编辑,并选择第二条含ro root选项进入编辑状态

    在ro后面输入single,后按enter键保存该条目后,按b键启动单用户模式

    三、进入单用户模式后,用passwd命令更改密码,更改完成后重启系统,正常启动后使用更改后的密码登录即可。

  • java 图形化显示,及系统状态图形化展示,监控技术

    2010-12-24 17:26:38

  • Java中关于空格替换的正则表达式,实例代码

    2010-12-24 17:18:56

     

    句点符号 . 是通配符 ,  * 零次或多次,+ 一次或多次,? 零次或一次,{n} 恰好n次,{n,m} 从n到m次
    要记住,老是拿*当通配符,实际是 句号 . 是通配符

     

     

    package test.function.excel;

    public class RegTest {
     
     public static void main(String[] args) {
       
      //Java中关于空格的正则表达式
      
      
        String str2 = "GET             /index.html HTTP/1.1";  //字符串s由“GET”、“/index.html”和“HTTP/1.1”组成,中间有一个或多个空格
        String tt[] = str2.split("\\s{1,}");   //按照空格分割字符串,多个空格作为一个空格对字符串进行分割
        for(String str: tt)//增强的for循环
        System.out.println(str);//输出:GET
                                           //  /index.html
                                          //  HTTP/1.1         
       
        String qq = str2.replaceAll(" {2,}", " ");//把字符串s中的多个空格替换为一个空格
        System.out.println(qq);//输出:GET /index.html HTTP/1.1
        System.out.println(str2);//输出:GET             /index.html HTTP/1.1
       
       
        // //split 按照空格分割字符串,多个空格作为一个空格对字符串进行分割
        String strTest = "668947   18  109451074 0                0        33       700198   2335821 " ;
        String resSplit[] = strTest.split("\\s{1,}")  ;
        for(int j =0 ;j< resSplit.length;j++){
         System.out.println(resSplit[j]);
        }
       
       
        //句点符号 . 是通配符 ,  * 零次或多次,+ 一次或多次,? 零次或一次,{n} 恰好n次,{n,m} 从n到m次
        String time = "dfda11:50:39" ;
        if(time.matches(".*\\d{2}:\\d{2}:\\d{2}")){
         System.out.println("fu he");
           }else{
           System.out.println("bu fu he");
           }
       
        // 不使用句点
        String time2 = "dfda11:50:39" ;
        if(time2.matches("\\d{2}:\\d{2}:\\d{2}")){
         System.out.println("fu he");
           }else{
           System.out.println("bu fu he");
           }
       


     }  

    }

     

     

     

     

     

  • shell脚本及命令使用小结及Informix监控脚本

    2010-12-24 17:05:56

     

    要求监控informix数据库,一开始是用java分析所有的onstat结果数据,因为起初不了解怎么做好,慢慢有了思路,就转为全部用shell实现。

     

    shell脚本及命令使用小结


    1. awk的使用:

    $ awk -F":" '{ print "username: " $1 "\t\tuid:" $3 }' /etc/passwd

    说明:-F":"指定分隔符,为冒号,awk默认的分隔符是一个空格,"username: ","\t\tuid:",自定义,添加的字符串,


    将awk取的值赋予变量:

     # echo aa bb cc | awk '{ print $3; }'
     cc
     # var=$(echo aa bb cc | awk '{ print $3; }')
     #echo $var
     cc
    ======================================================================================================

    2. sed 的使用

    sed -n '2p' file 
    说明:输出第二行
    onstat -p | sed -n '6p' | awk '{print $4 $8 }' 
    说明:先用sed过滤行,然后用awk过滤自己指定的列
    onstat -p | sed -n '18,20p' > sed_result      
    说明:输出第18到第20行


    sed有查找、替换、删除等功能:

    1) 部分行的输出与删除
      注意: SED本身不改变原文件内容, 删除仅指不输出该部分,重定向输出为文件时,与原文件比为删除
      sed -n '2,5p' file1 : 仅输出文件file1的2-5行
      sed -e '2,5d' file1 : 将文件file1的2-5行删除
      sed -e '/^#/d' file1 : 将文件file1的以#开头的行删除
      sed -ne '/HELLO/p' file1 : 仅输出file1中含HELLO的行
      sed -ne '/BEGIN/,/END/p' file1 : 仅输出file1中BEGIN与END间的部分
      首先,匹配含BEGIN的行作为块首, 然后向后以第一次匹配的含END的行为块尾,输出该块各行
      如果, 没有匹配到BEGIN,则不输出; 如果只匹配到BEGIN,则输出从该行到文件尾的各行
      在匹配到BEGIN的行后面,匹配到END的前面含有的BEGIN当作一般行,仍以第一个BEGIN为块首
      一个文件中, 可能有好几个这样匹配的区域块,都要输出

    2) 替换操作
      sed -e 's/foo/bar/' file1 : 将file1中第一次出现的foo替换为bar
      sed -e 's/foo/bar/g' file1 : 将file1中所有的foo替换为bar
      sed -e '1,8s/foo/bar/g' file1 : 将file1的1-8行中所以的foo替换为bar
      sed -e '/^$/,/^END/s/foo/bar/g' file1
      首先匹配以空行为块首,END为行首的行为块尾的所有区域块,
      然后将在这些区域块中出现的foo替换为bar
      sed -e 's/<.*>//g' file1 : 将file1各行中,<>间的文字删除(最大)
      is what meant ===> meant
      sed -e 's/<[^>]*.//g' file1 : 将file1各行中,<>间的文字删除(最小)
      is what meant ===> is what meant
      注意: .*表示任意格式的任意字符 [^>]*表示任意个数的非>的字符
      sed -e 's/girl/nice & hello/g' file1 : 将file1各行中的girl替换为nice girl hello
      这里&表示前面匹配的内容,在要替换的文字里引用
      更强的引用: 在匹配文字中用\(\)包含文字,在匹配文字中用\1到\9来引用
      sed -e 's/\(boy\) loves \(girl\)/\2 A loves \1 B/g' file1
      boy loves girl ===> girl A loves boy B'

    3)对同一对象执行多个sed操作时的3种方法
      1). sed -e 'command1;command2;command3' file1
      三个sed命令依次作用到file1的各行
      2). sed -e 'command1' -e 'command2 file1
      跟1)类似,比1)跟保险,1)不能用的时候可以尝试
      3). sed -f script_file file1
      一些复杂命令,必须写到一个script. 文件中

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


    3.  while读文件: shell按行读取文件

        变量的递增: let num=num+1   或者  let num+=1 或者  cs=`expr $cs + 1`


        #范例1:简单结构
      onstat -p > status
      while read line
      do
       echo $line
      done < status

        #范例2:
        top > status
      num=1
      while read line
      do    
      if [ $num -eq  6 ];
      then
      #echo $num
      #echo $line
      fi  
      let num=num+1
      done < status 
    ======================================================================================================


    4. until 循环;  以及读取命令行参数,  $#有特殊含义,获取了传入的参数的个数,类似的特殊标识还有几个。
      
      if [ $# -ne 3 ]
       then
        echo "Usage: 脚本名称 参数1 参数2 参数3, 参数1是循环次数,参数2是循环间隔时间,参数3是输出结果文件"
         exit 1
        fi  

       cs=1
       until [ $cs -gt $1 ]
       do
         cs=`expr $cs + 1`
         sleep $2
       done  

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

    5. 整数比较:
    -lt               Less than
    -gt               Greater than
    -le               Less than or equal to
    -ge               Greater than or equal to
    -eq               Equal to
    -ne              Not equal to

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

    6. shell的if语句格式:


      if [ $num -eq  6 ];
      then
      #echo $num
      fi
    ======================================================================================================

    7. cut 的使用,也可以对一行的数据进行指定截取。一般都可以指定分隔符号

    cut -c 1-5,10-14 file
    cut -f 1,3 file

    我们经常会遇到需要取出分字段的文件的某些特定字段,例如 /etc/password就是通过":"分隔各个字段的。
    可以通过cut命令来实现。例如,我们希望将系统账号名保存到特定的文件,就可以:
    cut -d: -f 1 /etc/passwd > /tmp/users
    -d用来定义分隔符,默认为tab键,-f表示需要取得哪个字段

    What’s cut?
    子曰:cut命令可以从一个文本文件或者文本流中提取文本列。
    命令用法:
       cut -b list [-n] [file ...]
       cut -c list [file ...]
       cut -f list [-d delim][-s][file ...]
    l    上面的-b、-c、-f分别表示字节、字符、字段(即byte、character、field);
    l    list表示-b、-c、-f操作范围,-n常常表示具体数字;
    l    file表示的自然是要操作的文本文件的名称;
    l    delim(英文全写:delimiter)表示分隔符,默认情况下为TAB;
    l    -s表示不包括那些不含分隔符的行(这样有利于去掉注释和标题)
    上面三种方式中,表示从指定的范围中提取字节(-b)、或字符(-c)、或字段(-f)。


    -c 和 -f 参数可以跟以下子参数:
    m 第m个字符或字段
    m- 从第m个字符或字段到文件结束
    m-n 从第m个到第n个字符或字段
    -n 从第1个到第n个字符或字段

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

     

     

     

     

     

    监控脚本原文:

     


    if [ $# -ne 3 ]
     then
      echo "Usage: 脚本名称 参数1 参数2 参数3, 参数1是循环次数,参数2是循环间隔时间,参数3是输出结果文件"
       exit 1
       fi  
      
       echo "Time,%cached read,ovlock,%ovbuff,bufwaits,lokwaits,lockreqs,deadlks,ckpwaits,seqscans,Fg Writes,Chunk Writes,Physical Logging pages/io,Physical Logging %used,Logical Logging pages/io,Logical Logging %used,active,total,hash buckets,lock table overflows"  >> informixStatus_$3.csv
      
       cs=1
       until [ $cs -gt $1 ]
       do

      var0=$(date | awk '{print $4}')
        
        onstat -p > status
      num=1
      while read line
      do   
      if [ $num -eq  6 ];
      then
      var1=$(echo $line | awk '{print $4 }' )
      fi 
      if [ $num -eq  15 ];
      then
      var2=$(echo $line | awk '{print $1 }' )
      var3=$(echo $line | awk '{print $3 }' )
      fi  
      if [ $num -eq  18 ];
      then
      var4=$(echo $line | awk '{print   $1 }' ) 
      var5=$(echo $line | awk '{print   $2 }'  ) 
      var6=$(echo $line | awk '{print  $3 }'  ) 
      var7=$(echo $line | awk '{print   $4 }'   ) 
      var8=$(echo $line | awk '{print   $6 }'  )  
      var9=$(echo $line | awk '{print   $8 }'  ) 
      fi 
      let num=num+1
      done < status 
     
     
        onstat -F > status
      num=1
      while read line
      do    
      if [ $num -eq  6 ];
      then
      var10=$(echo $line | awk '{print $1 }'  )
      var11=$(echo $line | awk '{print  $3 }'  )
      fi  
      let num=num+1
      done < status 

       
       
        onstat -l > status
      num=1
      while read line
      do  
      if [ $num -eq  6 ];
      then
      var12=$(echo $line | awk '{print $6 }' )
      fi  
      if [ $num -eq  8 ];
      then
      var13=$(echo $line | awk '{print  $5 }' )
      fi  
      if [ $num -eq  12 ];
      then
      var14=$(echo $line | awk '{print $8 }' )
      fi  
      if [ $num -eq  14 ];
      then
      var15=$(echo $line | awk '{print  $4 }' )
      fi      
      let num=num+1
      done < status 

       

        onstat -k | grep active > status
      num=1
      while read line
      do    
      if [ $num -eq  1 ];
      then
      var16=$(echo $line | awk '{print  $1 }')
      var17=$(echo $line | awk '{print $3 }' )
      var18=$(echo $line | awk '{print  $5 }' )
      var19=$(echo $line | awk '{print  $8 }')
      fi    
      let num=num+1
      done < status 

        echo "$var0,$var1,$var2,$var3,$var4,$var5,$var6,$var7,$var8,$var9,$var10,$var11,$var12,$var13,$var14,$var15,$var16,$var17,$var18,$var19" >> informixStatus_$3.csv

        cs=`expr $cs + 1`
        sleep $2
       done  
       rm status

     

    Informix监控脚本说明:
    1)监控脚本名称:monitorInfx
    2)监控脚本用法:monitorInfx 循环次数 循环间隔时间 结果文档名
    3)监控结果命名:informixStatus_输入的结果文档名(年月日_测试类型_用户数_运行时间_开始时间)

    4)脚本执行范例:
    nohup sh monitorInfx 600 3 20101245_HunHe_30Vuser_30Min_1401 &

    5)脚本执行结束后,会在当前目录下生成如下文件:
    informixStatus_20101245_HunHe_30Vuser_30Min_1401.csv

    6)可以将此文件另存为excel文件,然后生成图表

    7)注意输入的结果文档名中不要包含路径


     

     

     

    informix监控及shell脚本.rar(404 KB)

     

     

     

     

  • java poi 写入excel,一开始利用java分析数据并写入

    2010-12-24 17:00:25

     

     

    #这个是最初参考的文件,很简练,利于学习:

     

    package test.function.excel;

     

    import java.io.ByteArrayInputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;

    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFRichTextString;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.hwpf.extractor.WordExtractor;
    import org.apache.poi.poifs.filesystem.DirectoryEntry;
    import org.apache.poi.poifs.filesystem.DocumentEntry;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;

    // code run against the jakarta-poi-1.5.0-FINAL-20020506.jar.

    public class MyExcel {

     static public void main(String[] args) throws Exception {
     
     //------------在xls中写入数据
     FileOutputStream fos = new FileOutputStream("e:\\text.xls");
     HSSFWorkbook wb = new HSSFWorkbook();
     HSSFSheet s = wb.createSheet();
     wb.setSheetName(0, "first sheet");
     HSSFRow row = s.createRow(0);
     HSSFCell cell = row.createCell((int)0,0);
     HSSFRichTextString hts=new HSSFRichTextString("nihao");
     cell.setCellValue(hts);
     wb.write(fos);
     fos.flush();
     fos.close();
     
     //-------------------------
    // System.out.println("1111");
    // HSSFCell cell02 = row.createCell((int)1,0);
    // cell02.setCellValue(22);    // 当整型写入
    // System.out.println("222");
     //-------------------------
     
     //------------从xls读出数据
     wb = new HSSFWorkbook(new FileInputStream("e:\\text.xls"));
     s = wb.getSheetAt(0);
     HSSFRow r = s.getRow(0);
     cell=r.getCell((short)0);
     if(cell.getCellType() == HSSFCell.CELL_TYPE_STRING){
        System.out.println(cell.getRichStringCellValue());
     }
     
     
     //------------从doc读出数据
        FileInputStream in = new FileInputStream("e:\\text.doc");
        WordExtractor extractor = new WordExtractor(in);
        String text =extractor.getText();
           // 对DOC文件进行提取
        System.out.println(text);
        in.close();
     
     //------------------在doc中写入 

        byte[] a=new String("看见了!").getBytes();
        ByteArrayInputStream bs = new ByteArrayInputStream(a);
        POIFSFileSystem fs = new POIFSFileSystem();
        ///////////////////////////////////
        DirectoryEntry directory = fs.getRoot();
        DocumentEntry de = directory.createDocument("WordDocument", bs);
        //以上两句代码不能省略,否则输出的是乱码
        fos = new FileOutputStream("e:\\text.doc");
        fs.writeFilesystem(fos);
        bs.close();
        fos.flush();
        fos.close();
       
       
        //Java中关于空格的正则表达式
        String str2 = "GET             /index.html HTTP/1.1";//字符串s由“GET”、“/index.html”和“HTTP/1.1”组成,中间有一个或多个空格
        String tt[] = str2.split("\\s{1,}");//按照空格分割字符串,多个空格作为一个空格对字符串进行分割
        for(String str: tt)//增强的for循环
        System.out.println(str);//输出:GET
                                           //  /index.html
                                          //  HTTP/1.1         
        String qq = str2.replaceAll(" {2,}", " ");//把字符串s中的多个空格替换为一个空格
        System.out.println(qq);//输出:GET /index.html HTTP/1.1
        System.out.println(str2);//输出:GET             /index.html HTTP/1.1

       
       
       
       
     }
     }


     

     

     

    # 后来进行日志分析,然后获取数据,写入到excel中,代码如下:

     

    package test.function.excel;


    import java.io.BufferedReader;
    import java.io.ByteArrayInputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.Iterator;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    import org.apache.poi.hssf.usermodel.HSSFCell;
    import org.apache.poi.hssf.usermodel.HSSFRichTextString;
    import org.apache.poi.hssf.usermodel.HSSFRow;
    import org.apache.poi.hssf.usermodel.HSSFSheet;
    import org.apache.poi.hssf.usermodel.HSSFWorkbook;
    import org.apache.poi.hwpf.extractor.WordExtractor;
    import org.apache.poi.poifs.filesystem.DirectoryEntry;
    import org.apache.poi.poifs.filesystem.DocumentEntry;
    import org.apache.poi.poifs.filesystem.POIFSFileSystem;


    public class InformixAnalysisTwo {
     
     static public void main(String[] args) throws Exception {
      
      InformixAnalysisTwo myPro = new InformixAnalysisTwo() ;
      ArrayList<ArrayList> content = myPro.readDataFile() ;
      myPro.writeExcelFile(content)  ;
      
      
     } // main
     
     
     
     //读取监控数据:   // 可以改成传入参数,获取路径,循环路径下的文件
     public ArrayList readDataFile() throws Exception{
      
      //读取监控数据:
      //BufferedReader in = new BufferedReader(new FileReader("E:\\on_20101217_p_1_5-p","UTF-8"));
      BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("E:\\on_20101217_p_1_5-p"), "gbk"));
      
      String inStr = "" ;
      
      //String sheetName = in.readLine() ;
      
      //String[][] content = {} ;
      
      ArrayList<ArrayList> content = new ArrayList<ArrayList>() ;
      
    //  String dataParaName =
    //  "dskreads pagreads bufreads %cached dskwrits pagwrits bufwrits %cached"
    //  +" isamtot  open     start    read     write    rewrite  delete   commit   rollbk"
    //  +" gp_read  gp_write gp_rewrt gp_del   gp_alloc gp_free  gp_curs"
    //  +" ovlock   ovuserthread ovbuff   usercpu  syscpu   numckpts flushes"
    //  +" bufwaits lokwaits lockreqs deadlks  dltouts  ckpwaits compress seqscans"
    //  +" ixda-RA  idx-RA   da-RA    RA-pgsused lchwaits" ;
    //  
    //  String[] dataParaNameArray = dataParaName.split("\\s{1,}") ;
    //  for(int paraNum=0 ; paraNum < dataParaNameArray.length;paraNum++){
    //   String listName = dataParaNameArray[paraNum] ;
    //   //ArrayList<String> listName = new ArrayList<String>() ;
    //  }
      
      //Const String s = "" ;
      
      ArrayList<String> timeP = new ArrayList<String>() ;
      timeP.add("Time") ;
       
      ArrayList<String> dskreads = new ArrayList<String>() ;
      dskreads.add("dskreads") ;
      
      ArrayList<String> pagreads = new ArrayList<String>() ;
      pagreads.add("pagreads") ;
      
      content.add(timeP) ;
      content.add(dskreads) ;
      content.add(pagreads) ;
         
      while( (inStr=in.readLine()) != null   ){
       
    //   Pattern pattern = Pattern.compile("^Fri*");
    //   Matcher matcher = pattern.matcher(inStr);
    //      boolean b= matcher.matches();
    //      //当条件满足时,将返回true,否则返回false
    //     System.out.println(b);
        
       //System.out.println("内容:"+inStr);
       //Fri Dec 17 11:50:34 EAT 2010
    //   if(inStr.matches("*\\d{2}:\\d{2}:\\d{2}*")){
    //    System.out.println("eat");
    //   } 
       //System.out.println("行读取: "+inStr);
       
       if(inStr.endsWith("onstat -p")){
        inStr = in.readLine() ;
        String timeNow =inStr.split("\\s{1,}")[3] ; // 空格是固定的
        timeP.add(timeNow) ;
        //System.out.println ("读取 time "+timeNow) ;
        //timeP[num] = timeNow ;
        //num++ ;
       }
       if(inStr.startsWith("dskreads")){
        inStr = in.readLine() ;
        String[] paraValues = inStr.split("\\s{1,}") ;  // 空格的数量是不固定的
        dskreads.add(paraValues[0]) ;
        pagreads.add(paraValues[1]) ;
       }
         
      }
      
      System.out.println(content);
      System.out.println(timeP);
      System.out.println(dskreads);
      System.out.println(pagreads);
      
      return content ;
     }
     
     
     // 在xls中写入数据
     public void writeExcelFile(ArrayList<ArrayList> content) throws Exception {
      //------------在xls中写入数据
         
      FileOutputStream fos = new FileOutputStream("e:\\lianxi.xls");

      HSSFWorkbook wb = new HSSFWorkbook();
      
      HSSFSheet s = wb.createSheet();
      wb.setSheetName(0, "first sheet");   // 建立多个sheet,每个sheet 取不同的名字
      
      //for (int i=0 ;i<content.size() ;i++){ //行
       
      int m = 0 ;
       for(ArrayList paraValues : content) { //foreach语句 java SE5新增
        System.out.println("读取到的arrayList:"+paraValues);
        HSSFRow hssfRowFinal = s.createRow(m) ;
        m++ ;
        int n = 1 ; // 0 参数名,已被写入。
           //for(String value : paraValues){
        Iterator myIterator = paraValues.iterator() ;
        
             HSSFCell hssfCellFirstFinalHead = hssfRowFinal.createCell((int)0, 1) ; //HSSFCell.CELL_TYPE_STRING= 1 
              String prarameterName = myIterator.next().toString() ;
             hssfCellFirstFinalHead.setCellValue(prarameterName );
                     
        while(myIterator.hasNext()){ 
     
         String value = myIterator.next().toString() ;
            //System.out.println(value);
         
            if(value.matches("\\d{2}:\\d{2}:\\d{2}")){
             System.out.println("值符合日期格式:time:"+value);
             HSSFCell hssfCellFirstFinalTime = hssfRowFinal.createCell((int)n, 1) ;
             // int org.apache.poi.ss.usermodel.Cell.CELL_TYPE_STRING = 1 [0x1]
             hssfCellFirstFinalTime.setCellValue(value) ;         
            }else{
             System.out.println("参数值:value:"+value);
             HSSFCell hssfCellFirstFinal = hssfRowFinal.createCell((int)n, 0) ;
             hssfCellFirstFinal.setCellValue(Double.parseDouble(value) );
             
            }
              
         n++;
        }
          
       } 
         
       wb.write(fos);
       fos.flush();
       fos.close();
      
      System.out.print("over") ;
      
     }
     
     

    }

     

     

    java_poi写入excel.rar(4.73 KB)

     

     

     

  • csv是什么格式的文件,csv文件格式简介

    2010-12-23 12:46:06

     

    你可能问,为什么要了解这个文件格式,

    是这样的,在linux下用shell统计数据,写成csv文件格式

    下载到本机,就可以用excel进行处理了,包括生成图表。

    文件格式简单,通用,但是非常实用。

     

    CSVComma Separate Values,这种文件格式经常用来作为不同程序之间的数据交互的格式。

     

     

    具体文件格式

     

     

    每条记录占一行

    以逗号为分隔符

    逗号前后的空格会被忽略

    字段中包含有逗号,该字段必须用双引号括起来

    字段中包含有换行符,该字段必须用双引号括起来

    字段前后包含有空格,该字段必须用双引号括起来

    字段中的双引号用两个双引号表示

    字段中如果有双引号,该字段必须用双引号括起来

    第一条记录,可以是字段名

     

     

    CSV其实就是COMMA SEPARATED VALUE的缩写,出现在档案总管中的档案类型是「逗号分格」,依计算机原来的设定,如果直接点选该档案,计算机将以EXCEL的模式开启该档案。但建议您千万不要这么做,因为CSV档如果以EXCEL开启,由于计算机档案数据转换的原因,会将其CRC之数值改做科学记号方式储存,而造成档案中的 CRC值发生错误。这也是笔者初出茅庐时所得到的惨痛经验,但如果想一窥CSV档的真实面貌,笔者建议您使用WORDPAD或是记事本(NOTE)来开启,再则先另存新档后用EXCEL开启,也是方法之一。开启后的CSV档包含了四或五个字段(部分),由左至右分别记载着:文件名称(XXXX.JPG)、档案大小(以BYTE为单位)、CRC32值(八个英文字母或数字组成)、档案路径(档案储存的子目录名称)和档案内容描述(一般来说都是明星的英文姓名甚或是专辑名称,也可能空白)。而其中第四栏「档案路径」因为每个人储存整理图档的方式不同,所以本栏通常不存在,而一般有含有「档案路径」这栏的CSV档,又称为ECSV档案

     

     

    CSV" 逗号分隔文件 (Comma Separated Values) 的首字母英文缩写,是一种用来存储数据的纯文本格式,通常用于电子表格数据库软件。在 CSV 文件中,数据以逗号分隔,可允许程序通过读取文件为数据重新创建正确的栏结构,并在每次遇到逗号时开始新的一栏。
    创建 CSV 文件有许多方法。最常用的方法是用电子表格程序,如 Microsoft Excel。在 Microsoft Excel 中,选择文件”>“另存为,然后在文件类型下拉选择框中选择 "CSV (逗号分隔) (*.csv)"
    csv
    格式(即文件后缀为.csv,属于用excel软件可编辑的逗号分隔的一种文件格式)。

     

    xls 文件就是Microsoft excel电子表格的文件格式。我想就不用多介绍了吧,学校里多少都学过的。
    CSV
    是最通用的一种文件格式,它可以非常容易地被导入各种PC表格及数据库中。此文件,一行即为数据表的一行。生成数据表字段用半角逗号隔开。

    CSV是文本文件,用记事本就能打开,XLS是二进制的文件只有用EXCEL才能打

    CSV(以逗号分隔)

    CSV (*.csv) 文件格式只能保存活动工作表中的单元格所显示的文本和数值。工作表中所有的数据行和字符都将保存。数据列以逗号分隔,每一行数据都以回车符结束。如果单元格中包含逗号,则该单元格中的内容以双引号引起。

    如果单元格显示的是公式而不是数值,该公式将转换为文本方式。所有格式、图形、对象和工作表的其他内容将全部丢失。欧元符号将转换为问号。

    文本文件的内容有ASCII字符集中的字符组成

    首先:文本文件和二进制文件是有区别的,对于文本文件来说,每个字节(或每几个字节)的意义相同,你只要一个一个字节的读出来就OK了;而对于二进制文件来说,可能有4个字节保存了一个整形,接下去有4个字节保存了一个浮点型等等……所以要想打开二进制文件需要了解它的文件格式。
    要想知道文件格式,你可以用16进制编辑器打开一个二进制文件,然后猜测它的格式。

     

     

     

Open Toolbar