2009年5月13日星期三

We-Soft社区--大连程序员社区测试

今天开始测试论坛 大连程序员论坛 We-Soft社区

2009年4月10日星期五

几种媒体文件(MediaPlayer,Realplay,QuickTime)的调用代码

1.rm格式

2.mpg格式

3.wmv格式

4.mid

5.avi

6.flash

!!!换行键br自己去哈~~累死我了

2009年3月25日星期三

制作可执行的JAR文件包及jar命令详解

常常在网上看到有人询问:如何把 java 程序编译成 .exe 文件。通常回答只有两种,一种是制作一个可执行的 JAR 文件包,然后就可以像.chm 文档一样双击运行了;而另一种是使用 JET 来进行 编译。但是 JET 是要用钱买的,而且据说 JET 也不是能把所有的 Java 程序都编译成执行文件,性能也要打些折扣。所以,使用制作可执行 JAR 文件包的方法就是最佳选择了,何况它还能保持 Java 的跨平台特性。 

下面就来看看什么是 JAR 文件包吧: 

1. JAR 文件包 

JAR 文件就是 Java Archive File,顾名思意,它的应用是与 Java 息息相关的,是 Java 的一种文档格式。JAR 文件非常类似 ZIP 文件――准确的说,它就是 ZIP 文件,所以叫它文件包。JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中,包含了一个 META-INF/MANIFEST.MF 文件,这个文件是在生成 JAR 文件的时候自动创建的。举个例子,如果我们具有如下目录结构的一些文件: 

  == 

  `-- test 

    `-- Test.class 

把它压缩成 ZIP 文件 test.zip,则这个 ZIP 文件的内部目录结构为: 

  test.zip 

  `-- test 

    `-- Test.class 

如果我们使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar,则这个 JAR 文件的内部目录结构为: 

  test.jar 

  |-- META-INF 

  |  `-- MANIFEST.MF 

  `-- test 

    `--Test.class 

2. 创建可执行的 JAR 文件包 

制作一个可执行的 JAR 文件包来发布你的程序是 JAR 文件包最典型的用法。 

Java 程序是由若干个 .class 文件组成的。这些 .class 文件必须根据它们所属的包不同而分级分目录存放;运行前需要把所有用到的包的根目录指定给 CLASSPATH 环境变量或者 java 命令的 -cp 参数;运行时还要到控制台下去使用 java 命令来运行,如果需要直接双击运行必须写 Windows 的批处理文件 (.bat) 或者 Linux 的 Shell 程序。因此,许多人说,Java 是一种方便开发者苦了用户的程序设计语言。 

其实不然,如果开发者能够制作一个可执行的 JAR 文件包交给用户,那么用户使用起来就方便了。在 Windows 下安装 JRE (Java Runtime Environment) 的时候,安装文件会将 .jar 文件映射给 javaw.exe 打开。那么,对于一个可执行的 JAR 文件包,用户只需要双击它就可以运行程序了,和阅读 .chm 文档一样方便 (.chm 文档默认是由 hh.exe 打开的)。那么,现在的关键,就是如何来创建这个可执行的 JAR 文件包。 

创建可执行的 JAR 文件包,需要使用带 cvfm 参数的 jar 命令,同样以上述 test 目录为例,命令如下: 

jar cvfm test.jar manifest.mf test 

这里 test.jar 和 manifest.mf 两个文件,分别是对应的参数 f 和 m,其重头戏在 manifest.mf。因为要创建可执行的 JAR 文件包,光靠指定一个 manifest.mf 文件是不够的,因为 MANIFEST 是 JAR 文件包的特征,可执行的 JAR 文件包和不可执行的 JAR 文件包都包含 MANIFEST。关键在于可执行 JAR 文件包的 MANIFEST,其内容包含了 Main-Class 一项。这在 MANIFEST 中书写格式如下: 

Main-Class: 可执行主类全名(包含包名) 

例如,假设上例中的 Test.class 是属于 test 包的,而且是可执行的类 (定义了 public static void main(String[]) 方法),那么这个 manifest.mf 可以编辑如下: 

Main-Class: test.Test <回车>; 

这个 manifest.mf 可以放在任何位置,也可以是其它的文件名,只需要有 Main-Class: test.Test 一行,且该行以一个回车符结束即可。创建了 manifest.mf 文件之后,我们的目录结构变为: 

  == 

  |-- test 

  |  `-- Test.class 

  `-- manifest.mf 

这时候,需要到 test 目录的上级目录中去使用 jar 命令来创建 JAR 文件包。也就是在目录树中使用"=="表示的那个目录中,使用如下命令: 

jar cvfm test.jar manifest.mf test 

之后在"=="目录中创建了 test.jar,这个 test.jar 就是执行的 JAR 文件包。运行时只需要使用 java -jar test.jar 命令即可。 

需要注意的是,创建的 JAR 文件包中需要包含完整的、与 Java 程序的包结构对应的目录结构,就像上例一样。而 Main-Class 指定的类,也必须是完整的、包含包路径的类名,如上例的 test.Test;而且在没有打成 JAR 文件包之前可以使用 java <类名>; 来运行这个类,即在上例中 java test.Test 是可以正确运行的 (当然要在 CLASSPATH 正确的情况下)。 

3. jar 命令详解 

jar 是随 JDK 安装的,在 JDK 安装目录下的 bin 目录中,Windows 下文件名为 jar.exe,Linux 下文件名为 jar。它的运行需要用到 JDK 安装目录下 lib 目录中的 tools.jar 文件。不过我们除了安装 JDK 什么也不需要做,因为 SUN 已经帮我们做好了。我们甚至不需要将 tools.jar 放到 CLASSPATH 中。 

使用不带任何的 jar 命令我们可以看到 jar 命令的用法如下: 

jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目录] 文件名 ... 

其中 {ctxu} 是 jar 命令的子命令,每次 jar 命令只能包含 ctxu 中的一个,它们分别表示: 

-c 创建新的 JAR 文件包 

-t 列出 JAR 文件包的内容列表 

-x 展开 JAR 文件包的指定文件或者所有文件 

-u 更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中) 

[vfm0M] 中的选项可以任选,也可以不选,它们是 jar 命令的选项参数 

-v 生成详细报告并打印到标准输出 

-f 指定 JAR 文件名,通常这个参数是必须的 

-m 指定需要包含的 MANIFEST 清单文件 

-0 只存储,不压缩,这样产生的 JAR 文件包会比不用该参数产生的体积大,但速度更快 

-M 不产生所有项的清单(MANIFEST〕文件,此参数会忽略 -m 参数 

[jar-文件] 即需要生成、查看、更新或者解开的 JAR 文件包,它是 -f 参数的附属参数 

[manifest-文件] 即 MANIFEST 清单文件,它是 -m 参数的附属参数 

[-C 目录] 表示转到指定目录下去执行这个 jar 命令的操作。它相当于先使用 cd 命令转该目录下再执行不带 -C 参数的 jar 命令,它只能在创建和更新 JAR 文件包的时候可用。   

文件名 ... 指定一个文件/目录列表,这些文件/目录就是要添加到 JAR 文件包中的文件/目录。如果指定了目录,那么 jar 命令打包的时候会自动把该目录中的所有文件和子目录打入包中。 

下面举一些例子来说明 jar 命令的用法: 

1) jar cf test.jar test 

该命令没有执行过程的显示,执行结果是在当前目录生成了 test.jar 文件。如果当前目录已经存在 test.jar,那么该文件将被覆盖。 

2) jar cvf test.jar test 

该命令与上例中的结果相同,但是由于 v 参数的作用,显示出了打包过程,如下: 

标明清单(manifest) 

增加:test/(读入= 0) (写出= 0)(存储了 0%) 

增加:test/Test.class(读入= 7) (写出= 6)(压缩了 14%) 

3) jar cvfM test.jar test 

该命令与 2) 结果类似,但在生成的 test.jar 中没有包含 META-INF/MANIFEST 文件,打包过程的信息也略有差别: 

增加:test/(读入= 0) (写出= 0)(存储了 0%) 

增加:test/Test.class(读入= 7) (写出= 6)(压缩了 14%) 

4) jar cvfm test.jar manifest.mf test 

运行结果与 2) 相似,显示信息也相同,只是生成 JAR 包中的 META-INF/MANIFEST 内容不同,是包含了 manifest.mf 的内容 

5) jar tf test.jar 

在 test.jar 已经存在的情况下,可以查看 test.jar 中的内容,如对于 2) 和 3) 生成的 test.jar 分别应该此命令,结果如下; 

对于 2) 

META-INF/ 

META-INF/MANIFEST.MF 

test/ 

test/Test.class 

对于 3) 

test/ 

test/Test.class 

6) jar tvf test.jar 

除显示 5) 中显示的内容外,还包括包内文件的详细信息,如: 

0 Wed Jun 19 15:39:06 GMT 2002 META-INF/ 

86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF 

0 Wed Jun 19 15:33:04 GMT 2002 test/ 

7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class 

7) jar xf test.jar 

解开 test.jar 到当前目录,不显示任何信息,对于 2) 生成的 test.jar,解开后的目录结构如下: 

  == 

  |-- META-INF 

  |  `-- MANIFEST 

  `-- test 

    `--Test.class 

8) jar xvf test.jar 

运行结果与 7) 相同,对于解压过程有详细信息显示,如: 

创建:META-INF/ 

展开:META-INF/MANIFEST.MF 

创建:test/ 

展开:test/Test.class 

9) jar uf test.jar manifest.mf 

在 test.jar 中添加了文件 manifest.mf,此使用 jar tf 来查看 test.jar 可以发现 test.jar 中比原来多了一个 manifest。这里顺便提一下,如果使用 -m 参数并指定 manifest.mf 文件,那么 manifest.mf 是作为清单文件 MANIFEST 来使用的,它的内容会被添加到 MANIFEST 中;但是,如果作为一般文件添加到 JAR 文件包中,它跟一般文件无异。 

10) jar uvf test.jar manifest.mf 

与 9) 结果相同,同时有详细信息显示,如: 

增加:manifest.mf(读入= 17) (写出= 19)(压缩了 -11%) 

4. 关于 JAR 文件包的一些技巧 

1) 使用 unzip 来解压 JAR 文件 

在介绍 JAR 文件的时候就已经说过了,JAR 文件实际上就是 ZIP 文件,所以可以使用常见的一些解压 ZIP 文件的工具来解压 JAR 文件,如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等来解压是因为它们解压比较直观,方便。而使用 unzip,则是因为它解压时可以使用 -d 参数指定目标目录。 

在解压一个 JAR 文件的时候是不能使用 jar 的 -C 参数来指定解压的目标的,因为 -C 参数只在创建或者更新包的时候可用。那么需要将文件解压到某个指定目录下的时候就需要先将这具 JAR 文件拷贝到目标目录下,再进行解压,比较麻烦。如果使用 unzip,就不需要这么麻烦了,只需要指定一个 -d 参数即可。如: 

unzip test.jar -d dest/ 

2) 使用 WinZip 或者 WinRAR 等工具创建 JAR 文件 

上面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件,所以,只需要使用 WinZip、WinRAR 等工具创建所需要 ZIP 压缩包,再往这个 ZIP 压缩包中添加一个包含 MANIFEST 文件的 META-INF 目录即可。对于使用 jar 命令的 -m 参数指定清单文件的情况,只需要将这个 MANIFEST 按需要修改即可。 

3) 使用 jar 命令创建 ZIP 文件 

有些 Linux 下提供了 unzip 命令,但没有 zip 命令,所以需要可以对 ZIP 文件进行解压,即不能创建 ZIP 文件。如要创建一个 ZIP 文件,使用带 -M 参数的 jar 命令即可,因为 -M 参数表示制作 JAR 包的时候不添加 MANIFEST 清单,那么只需要在指定目标 JAR 文件的地方将 .jar 扩展名改为 .zip 扩展名,创建的就是一个不折不扣的 ZIP 文件了,如将上一节的第 3) 个例子略作改动: 

jar cvfM test.zip test


或者用 installanywhere 来制作安装 java 安装软件,。

他会自动的给 java 软件带上 java 运行环境(不用再为客户端装 jre 了),而且用一个小的 exe 文件来调用 jar 文件,这样上面的功能也就达到了。
来这里下:
http://goldengate.zerog.com/releases/enterprise507/

我还没找到 license,不过只是安装软件时 installanywhere 会提醒下注册,运行安装后的软件就再没出现注册提示.

Java初学者都应该搞懂的六个问题

 对于这个系列里的问题,每个学Java的人都应该搞懂。当然,如果只是学Java玩玩就无所谓了。如果你认为自己已经超越初学者了,却不很懂这些问题,请将你自己重归初学者行列。内容均来自于CSDN的经典老贴。

  问题一:我声明了什么!

 

String s = "Hello world!";

  许多人都做过这样的事情,但是,我们到底声明了什么?回答通常是:一个String,内容是"Hello world!"。这样模糊的回答通常是概念不清的根源。如果要准确的回答,一半的人大概会回答错误。
这个语句声明的是一个指向对象的引用,名为"s",可以指向类型为String的任何对象,目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象,我们只是声明了一个只能指向String对象的引用变量。所以,如果在刚才那句语句后面,如果再运行一句:

String string = s;

  我们是声明了另外一个只能指向String对象的引用,名为string,并没有第二个对象产生,string还是指向原来那个对象,也就是,和s指向同一个对象。

  问题二:"=="和equals方法究竟有什么区别?

  ==操作符专门用来比较变量的值是否相等。比较好理解的一点是:

int a=10;
int b=10;

  则a==b将是true。
  但不好理解的地方是:

String a=new String("foo");
String b=new String("foo");

  则a==b将返回false。

  根据前一帖说过,对象变量其实是一个引用,它们的值是指向对象所在的内存地址,而不是对象本身。a和b都使用了new操作符,意味着将在内存中产生两个内容为"foo"的字符串,既然是"两个",它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值,所以使用"=="操作符,结果会是false。诚然,a和b所指的对象,它们的内容都是"foo",应该是"相等",但是==操作符并不涉及到对象内容的比较。

  对象内容的比较,正是equals方法做的事。

  看一下Object对象的equals方法是如何实现的:

boolean equals(Object o){
return this==o;
}

  Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法,那你的类使用equals和使用==会得到同样的结果。同样也可以看出,Object的equals方法没有达到equals方法应该达到的目标:比较两个对象内容是否相等。因为答案应该由类的创建者决定,所以Object把这个任务留给了类的创建者。

  看一下一个极端的类:

Class Monster{
private String content;
...
boolean equals(Object another){ return true;}
}

  覆盖了equals方法。这个实现会导致无论Monster实例内容如何,它们之间的比较永远返回true。

  所以当你是用equals方法判断对象的内容是否相等,请不要想当然。因为可能你认为相等,而这个类的作者不这样认为,而类的equals方法的实现是由他掌握的。如果你需要使用equals方法,或者使用任何基于散列码的集合(HashSet,HashMap,HashTable),请察看一下java doc以确认这个类的equals逻辑是如何实现的。

 

  问题三:String到底变了没有?

  没有。因为String被设计成不可变(immutable)类,所以它的所有对象都是不可变对象。请看下列代码:

String s = "Hello";
s = s + " world!";

  s所指向的对象是否改变了呢?从本系列第一篇的结论很容易导出这个结论。我们来看看发生了什么事情。在这段代码中,s原先指向一个String对象,内容是"Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"Hello world!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。

  通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。

  同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做:

public class Demo {
private String s;
...
public Demo {
s = "Initial Value";
}
...
}

  而非

  s = new String("Initial Value");

  后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。

  上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。

  至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即StringBuffer。

  问题四:final关键字到底修饰了什么?

  final使得被修饰的变量"不变",但是由于对象型变量的本质是"引用",使得"不变"也有了两种含义:引用本身的不变,和引用指向的对象不变。

  引用本身的不变:

final StringBuffer a=new StringBuffer("immutable");
final StringBuffer b=new StringBuffer("not immutable");
a=b;//编译期错误

  引用指向的对象不变:

final StringBuffer a=new StringBuffer("immutable");
a.append(" broken!"); //编译通过

  可见,final只对引用的"值"(也即它所指向的那个对象的内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象的变化,final是不负责的。这很类似==操作符:==操作符只负责引用的"值"相等,至于这个地址所指向的对象内容是否相等,==操作符是不管的。

  理解final问题有很重要的含义。许多程序漏洞都基于此----final只能保证引用永远指向固定对象,不能保证那个对象的状态不变。在多线程的操作中,一个对象会被多个线程共享或修改,一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为final,意图使得它"永远不变"。其实那是徒劳的。

 

  问题五:到底要怎么样初始化!

  本问题讨论变量的初始化,所以先来看一下Java中有哪些种类的变量。

1. 类的属性,或者叫值域
2. 方法里的局部变量
3. 方法的参数

  对于第一种变量,Java虚拟机会自动进行初始化。如果给出了初始值,则初始化为该初始值。如果没有给出,则把它初始化为该类型变量的默认初始值。

int类型变量默认初始值为0
float类型变量默认初始值为0.0f
double类型变量默认初始值为0.0
boolean类型变量默认初始值为false
char类型变量默认初始值为0(ASCII码)
long类型变量默认初始值为0

  所有对象引用类型变量默认初始值为null,即不指向任何对象。注意数组本身也是对象,所以没有初始化的数组引用在自动初始化后其值也是null。

  对于两种不同的类属性,static属性与instance属性,初始化的时机是不同的。instance属性在创建实例的时候初始化,static属性在类加载,也就是第一次用到这个类的时候初始化,对于后来的实例的创建,不再次进行初始化。这个问题会在以后的系列中进行详细讨论。

  对于第二种变量,必须明确地进行初始化。如果再没有初始化之前就试图使用它,编译器会抗议。如果初始化的语句在try块中或if块中,也必须要让它在第一次使用前一定能够得到赋值。也就是说,把初始化语句放在只有if块的条件判断语句中编译器也会抗议,因为执行的时候可能不符合if后面的判断条件,如此一来初始化语句就不会被执行了,这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句,就可以通过编译,因为无论如何,总有至少一条初始化语句会被执行,不会发生使用前未被初始化的事情。对于try-catch也是一样,如果只有在try块里才有初始化语句,编译部通过。如果在catch或finally里也有,则可以通过编译。总之,要保证局部变量在使用之前一定被初始化了。所以,一个好的做法是在声明他们的时候就初始化他们,如果不知道要出事化成什么值好,就用上面的默认值吧!

  其实第三种变量和第二种本质上是一样的,都是方法中的局部变量。只不过作为参数,肯定是被初始化过的,传入的值就是初始值,所以不需要初始化。

  问题六:instanceof是什么东东?

  instanceof是Java的一个二元操作符,和==,>,<是同一类东东。由于它是由字母组成的,所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回boolean类型的数据。举个例子:

String s = "I AM an Object!";
boolean isObject = s instanceof Object;

  我们声明了一个String对象引用,指向一个String对象,然后用instancof来测试它所指向的对象是否是Object类的一个实例,显然,这是真的,所以返回true,也就是isObject的值为True。

  instanceof有一些用处。比如我们写了一个处理账单的系统,其中有这样三个类:

public class Bill {//省略细节}
public class PhoneBill extends Bill {//省略细节}
public class GasBill extends Bill {//省略细节}

  在处理程序里有一个方法,接受一个Bill类型的对象,计算金额。假设两种账单计算方法不同,而传入的Bill对象可能是两种中的任何一种,所以要用instanceof来判断:

public double calculate(Bill bill) {
if (bill instanceof PhoneBill) {
//计算电话账单
}
if (bill instanceof GasBill) {
//计算燃气账单
}
...
}

  这样就可以用一个方法处理两种子类。

  然而,这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现,这是面向对象变成应有的做法,避免回到结构化编程模式。只要提供两个名字和返回值都相同,接受参数类型不同的方法就可以了:

public double calculate(PhoneBill bill) {
//计算电话账单
}

public double calculate(GasBill bill) {
//计算燃气账单
}

  所以,使用instanceof在绝大多数情况下并不是推荐的做法,应当好好利用多态。

浅析java回调机制

public class Test{
   public static void main(String[] args){
     FooBar foo=new FooBar();
     foo.setCallBack(new ICallBack(){
        public void postExec(){System.out.println("method executed.");}
     });
   }
}


aaaaaa
public interface ICallBack(){
  void postExec();
}


bbbbbb
public class FooBar..{
  private ICallBack callBack;
  public void setCallBack(ICallBack callBack){
    this.callBack=callBack;
  }
  public void doSth(){
     ....
     callBack.postExec();
  }
  ..
}

JAVA的CALLBACK通过接口来实现。  
  例:  
  1.class   A,class   B  
  2.class   A实现接口ICallBack  
  3.class   B拥有一个参数为ICallBack接口类型的函数setCallBack(ICallBack   o)  
  4.class   A运行时调用class   B中setCallBack函数,以自身传入参数  
  5.class   B已取得A,就可以随时回调A所实现的ICallBack接口中的方法  

闰年的判断方法

在公历(格里历)纪年中,有闰日的年份叫闰年,一般年份365天,闰年为366天。由于地球绕太阳运行周期为365天5小时48分46秒(合365.24219天)即一回归年,公历把一年定为365天。所余下的时间约为四年累计一天,加在二月里,所以平常年份每年365天,二月为28天,闰年为366天,二月为29天。因此,每400年中有97个闰年,闰年在2月末增加一天,闰年366天。 闰年的计算方法:公元纪年的年数可以被四整除,即为闰年;被100整除而不能被400整除为平年;被100整除也可被400整除的为闰年。如2000年是闰年,而1900年不是。
 

var isLeapYear=function(str){
  if(str.isInt()){  //isInt()为自定义String扩展方法;
   var curYear=parseInt(str, 10);
   if(curYear % 400 == 0 || (curYear % 100 !=0 && curYear % 4 == 0)) return true;
   else return false;
  }
  else return false;
 }

javascript中replace()用法详解

在javascript中,String的函数replace()简直太让人喜爱了。它灵活而强大的字符替换处理能力,让我不禁想向大家介绍它。

replace()最简单的算是能力就是简单的字符替换。示例代码如下:

 

<script language="javascript">
var strM = "javascript is a good script language";
//在此我想将字母a替换成字母A
alert(strM.replace("a","A"));
</script>

 

  我想大家运行后可以看到结果,它只替换了首字母。但如果加上正则表达式结果就不一样了!呵呵,没错。replace()支持正则表达式,它可以按照正则表达式的规则匹配字符或字符串,然后给予替换!

 

<script language="javascript">
var strM = "javascript is a good script language";
//在此我想将字母a替换成字母A
alert(strM.replace(/a/,"A"));
</script>

 

  呵呵,您一定发现了。这样还是只替换了第一个字母a。如果您熟悉正则,那这就难不住您。稍加修改就OK了。

<script language="javascript">
var strM = "javascript is a good script language";
//在此将字母a全部替换成字母A
alert(strM.replace(/a/g,"A"));
</script>

  还可以这样,看看效果!

 

<script language="javascript">
var strM = "javascript is a good script language";
alert(strM.replace(/(javascript)\s*(is)/g,"$1 $2 fun. it $2"));
</script>

  我这儿举的例子都是很简单的应用,replace()在此点上与您使用正则表达式的能力成正比。您正则表达式越强,呵呵,那您就会越疯狂的爱上它。

 

  当然,我这儿推荐replace()的原因并不因为它能与正则表达式合作,而在于它还能与函数进行合作,发挥出强大的功能。

  先看看简单例子:将所有单词首字母换成大写。

<script language="javascript">
var strM = "javascript is a good script language";
function change(word)
{
 return word.indexOf(0).toUpperCase()+word.substring(1);
}
alert(strM.replace(/\b\w+\b/g,change));
</script>

 

  由上可知,当正则表达式有"g"标志时,代表将处理整个字符串,即函数change的变换将应用于所有匹配的对象。而该函数有三个或更多参数,具体个数视正则表达式而定。

  有了函数与正则表达式的配合,replace()处理字符串的功能空前强大起来了!

  最后还举个例子,将字符串所有单词倒序,用replace()处理是如此简单。

<script language="javascript">
var strM = "javascript is a good script language";
function change(word)
{
 var result = word.match(/(\w)/g);
if ( result )
{
 var str = "";
  for ( var i=result.length-1; i>=0; i-- )
 {
   str += result;
 }
 return str;
}
else
{
  return "null";
}
}
alert(strM.replace(/\b(\w)+\b/g,change));
</script>

判断JavaScript对象是否可用的正确方法

判断对象存在的方法

很快你就会注意到,JavaScript的部分功能在部分浏览器中无效。如果你要使用一些脚本的高级特性,你首先要检查浏览器是否支持要使用的对象,本文具体说明判断的正确方法。

 

通过判断浏览器的版本:不!

 

如果你想知道浏览器是否支持代码中使用的那些对象,记住,永远都不要通过浏览器的版本来判断。我确定你知道,有些浏览器支持你的代码,而有些浏览器不支持你的代码,可是你考虑过其他的浏览器么?那些不知名的小浏览器?

 

就算你可以检测出90%的用户所使用的浏览器及版本,还是有一些不出名的浏览器不能正确运行你的代码,结果要么是一大堆异常信息,要么是某些脚本没有被正确的执行。不管是哪种情况,你都是在使用漏洞百出的代码欺骗最终浏览网站的用户。

 

个案研究:mouseovers

 

一个古老的个案可以证实上述的说法。虽然这种情况现在已经不存在,但是同样原理的例子还是存在的。

 

一个公认的事实就是IE 3不支持document.images这个数组,但这个数组对mouseover脚本又是极为重要。所以我们就应该禁止mouseover脚本在IE 3浏览器中执行。解决方案之一就是对浏览器进行判断,当判断出用户使用的浏览器是IE 3的时候,就不执行这个函数。

 

但是,在大多数操作系统中,Netscape 2浏览器同样不支持document.images数组。如果你仅仅判断浏览器是不是IE 3,那么使用Netscape 2的用户就会看到一大堆异常信息。

 

那为什么不连同Netscape 2一起检测呢?因为就算这样做也是无事于补。

 

运行在OS/2上的Netscape 2是和Netscape 3完全兼容的,而且可以很好的处理mouseover效果。尽管如此,大家为什么还会经常看不到这个效果呢?因为web开发者使用了浏览器检测的手段,在 mouseover脚本中屏蔽了Netscape 2浏览器。因此开发者们,在没有充足理由的情况下,剥夺了用户拥有良好互动体验的权利。合适的对象检测方法可以避免这种情况的发生。

 

最后,越来越多的浏览器允许用户把浏览器的认证字符串修改为自己喜欢的内容,这样就存在很大的可能性,检测不出用户真实使用的浏览器以及版本,自然就不能保证无故障的运行代码了。由此,web开发者再次剥夺了用户额外互动效果的权利。更糟的是,这样的代码通常写的很烂。

 

既然浏览器的版本不可靠,那么是否JavaScript的版本更加可信一些呢?

 

通过判断JavaScript的版本:不!

 

在最初规划的时候,Netscape完全意识到未来的浏览器会支持比现在多得多的对象,而web开发者必须能够把新老浏览器区分开来。

 

起初的计划是让开发者对浏览器的版本进行判断。比如某某浏览器只能支持JavaScript 1.x等。在script标签中增加version属性,这样如果浏览器不支持相应版本的JavaScript,自然就不会执行这段脚本。

 

但是,当Microsoft涉足浏览器市场后,这个想法就无法进行下去了。尽管早在Netscape 4和IE 4的时候就都支持JavaScript 1.2,可是就算再有想象力的人也不会相信他们支持的是相同的JavaScript 1.2。因为这个版本号已经过时了,而且肯定和对象检测不相干。

 

所以不要使用JavaScript的版本号来做什么,他们没什么实际的作用。

 

正确的方法:对象判断

 

相反,我们只需通过简单的方法来判断浏览器是否支持要使用的对象(或者是方法、数组或者属性)。我们还是使用mouseover这个例子。这段脚本依赖于document.images这个数组,所以最重要的事情当然是判断浏览器是否支持他,下面是具体的做法:

if (document.images)
{
do something with the images array
}

 

现在你有了一个完全的保障,运行这段代码的浏览器肯定支持这段脚本。条件语句判断document.image这个数组是否存在,如果返回true,那么这段脚本将会被执行,反之如果这个数组不存在,将会返回false,而且这段脚本肯定不会被执行。

 

还有一个常用的检测是针对window.focus的。这是一个方法(一条你告诉JavaScript要去做什么的命令)。如果我们要使用这个方法,我们必须首先检测浏览器是否支持这个方法。

 

检测函数是否存在的正确方法如下,牢记千万不要在函数后面加括号:

if (window.focus)

 

上面这段代码的含义是:"浏览器是否支持window.focus这个函数",而下面这段代码的含义不同:

if (window.focus())

 

这段代码是对focus的结果进行判断,而且已经假设浏览器是支持focus方法的,而如果不支持,这时候就会报异常了。加了括号以后实际上执行了函数,而这并不是我们想要的状况。所以检测的时候不要加括号,而只有在检测通过后才加上括号执行这个函数。比如下面这个例子:

if (window.focus) window.focus()

 

重点

 

以上讨论的所有重点就是:在JavaScript中,如果你要使用document.images,首先判断是否支持document.images。如果你要使用window.focus方法,首先判断是否浏览器是否支持这个方法。

如果你总是在使用对象前进行检测,你的脚本将不会产生类似问题的异常,付出的代码只是有些功能在部分浏览器中被屏蔽掉了而已。

领悟JavaScript中的面向对象

JavaScript 是面向对象的。但是不少人对这一点理解得并不全面。

在 JavaScript 中,对象分为两种。一种可以称为"普通对象",就是我们所普遍理解的那些:数字、日期、用户自定义的对象(如:{})等等。

还有一种,称为"方法对象",就是我们通常定义的 function。你可能觉得奇怪:方法就是方法,怎么成了对象了?但是在 JavaScript 中,方法的确是被当成对象来处理的。下面是一个简单的例子:

 

JavaScript代码
function func() {alert('Hello!');}
alert(func.toString());
在这个例子中,func 虽然是作为一个方法定义的,但它自身却包含一个 toString 方法,说明 func 在这里是被当成一个对象来处理的。更准确的说,func 是一个"方法对象"。下面是例子的继续:


JavaScript代码
func.name = "I am func.";
alert(func.name);
我们可以任意的为 func 设置属性,这更加证明了 func 就是一个对象。那么方法对象和普通对象的区别在哪里呢?首先方法对象当然是可以执行的,在它后面加上一对括号,就是执行这个方法对象了。

 

JavaScript代码
func();
所以,方法对象具有二重性。一方面它可以被执行,另一方面它完全可以被当成一个普通对象来使用。这意味着什么呢?这意味着方法对象是可以完全独立于其他对象存在的。这一点我们可以同 Java 比较一下。在 Java 中,方法必须在某一个类中定义,而不能单独存在。而 JavaScript 中就不需要。

方法对象独立于其他方法,就意味着它能够被任意的引用和传递。下面是一个例子:


JavaScript代码
function invoke(f) {
f();
}
invoke(func);
将一个方法对象 func 传递给另一个方法对象 invoke,让后者在适当的时候执行 func。这就是所谓的"回调"了。另外,方法对象的这种特殊性,也使得 this 关键字不容易把握。这方面相关文章不少,这里不赘述了。

除了可以被执行以外,方法对象还有一个特殊的功用,就是它可以通过 new 关键字来创建普通对象。

话说每一个方法对象被创建时,都会自动的拥有一个叫 prototype 的属性。这个属性并无什么特别之处,它和其他的属性一样可以访问,可以赋值。不过当我们用 new 关键字来创建一个对象的时候,prototype 就起作用了:它的值(也是一个对象)所包含的所有属性,都会被复制到新创建的那个对象上去。下面是一个例子:


JavaScript代码
func.prototype.name="prototype of func";
var f = new func();
alert(f.name);
执行的过程中会弹出两个对话框,后一个对话框表示 f 这个新建的对象从 func.prototype 那里拷贝了 name 属性。而前一个对话框则表示 func 被作为方法执行了一遍。你可能会问了,为什么这个时候要还把 func 执行一遍呢?其实这个时候执行 func,就是起"构造函数"的作用。为了形象的说明,我们重新来一遍:


JavaScript代码
function func() {
this.name="name has been changed."
}
func.prototype.name="prototype of func";
var f = new func();
alert(f.name);
你就会发现 f 的 name 属性不再是"prototype of func",而是被替换成了"name has been changed"。这就是 func 这个对象方法所起到的"构造函数"的作用。所以,在 JavaScript 中,用 new 关键字创建对象是执行了下面三个步骤的:


创建一个新的普通对象;
将方法对象的 prototype 属性的所有属性复制到新的普通对象中去。
以新的普通对象作为上下文来执行方法对象。
对于"new func()"这样的语句,可以描述为"从 func 创建一个新对象"。总之,prototype 这个属性的唯一特殊之处,就是在创建新对象的时候了。


那么我们就可以利用这一点。比如有两个方法对象 A 和 B,既然从 A 创建的新对象包含了所有 A.prototype 的属性,那么我将它赋给 B.prototype,那么从 B 创建的新对象不也有同样的属性了?写成代码就是这样:


XML/HTML代码
A.prototype.hello = function(){alert('Hello!');}
B.prototype = new A();
new B().hello();
这就是 JavaScript 的所谓"继承"了,其实质就是属性的拷贝,这里利用了 prototype 来实现。如果不用 prototype,那就用循环了,效果是一样的。所谓"多重继承",自然就是到处拷贝了。

JavaScript 中面向对象的原理,就是上面这些了。自始至终我都没提到"类"的概念,因为 JavaScript 本来就没有"类"这个东西。面向对象可以没有类吗?当然可以。先有类,然后再有对象,这本来就不合理,因为类本来是从对象中归纳出来的,先有对象再有类,这才合理。像下面这样的:


XML/HTML代码
var o = {}; // 我发现了一个东西。
o.eat = function(){return "I am eating."} // 我发现它会吃;
o.sleep = function(){return "ZZZzzz..."} // 我发现它会睡;
o.talk = function(){return "Hi!"} // 我发现它会说话;
o.think = function(){return "Hmmm..."} // 我发现它还会思考。

var Human = new Function(); // 我决定给它起名叫"人"。
Human.prototype = o; // 这个东西就代表了所有"人"的概念。

var h = new Human(); // 当我发现其他同它一样的东西,
alert(h.talk()) // 我就知道它也是"人"了!

解决XP IIS 禁止访问连接的用户过多的问题

多刚接触ASP的朋友都是在XP系统下进行测试的,而XP自带的IIS对连接数进行了一定的限制,当多人访问网站时老是会提示IIS禁止访问,连接的用户过多,重启IIS后问题即可暂时解决,一但访问的人数再多时又会出现同样的错误提示,下面介绍一种方法从根本上解决Windows XP中IIS禁止访问连接的用户过多,使得我们的Windows XP能够像Windows 2000/2003/2008一样无限制人数的使用IIS。

     1、去微软的网站上下载MetaEdit工具。
     http://download.microsoft.com/download/iis50/Utility/5.0/NT45/EN-US/MtaEdt22.exe

     2、双击下载好的MtaEdt22.exe,按向导提示完成MetaEdit安装,在安装过程中可能会出现相关提示,不用管它,按YES即可。

     3、在MetaEdit中设置客户端连接限制的参数。
     安装MetaEdit完毕后,在开始菜单的程序组Administrative Tools下点击MetaEdit 2.2运行,在窗口的左边将树展开至LM\W3SVC,直接在W3SVC文件夹上单击,选择右边列表中Name为MaxConnections的项,双击后,在最后Data的文本框中默认的是10,这就是Windows XP专业版IIS默认设置的最大客户端连接数了,现在你可以改变这个默认值了,我把它改为10000,注意:在Win2000 上的IIS客户端连接数最大为2000000000。相关设置的截图如下所示:

javascript 兼容 IE6、IE7、FF 的“加入收藏”

window.external.addFavorite(sURL, sTitle);
说明:
addFavorite 的第一个字母 a 不是大写!纵然微软参考上是大写,但"事实胜于雄辩"。

Firefox 的"加入收藏"代码:

方法一、
<a href="http://blog.csdn.net/feng_sundy/" title="feng_sundy的专栏" rel="sidebar">加入收藏</a>
关键在于 rel="sidebar";href 属性值作为收藏网址;title 作为收藏名称。

方法二、
window.sidebar.addPanel(sTitle, sURL, "");
第一个参数是收藏名称;第二个参数是收藏网址;第三个是自定义 Tab 所需的 URL,为零长度字符串即可。注意参数顺序与 addFavorite 不同。我们推荐第二种方法。

不论哪一种方法,加入收藏夹后,单击收藏的项目都是在侧边栏(sidebar)中打开网页,要在主窗口中打开只有两种办法:法一是右键打开;法二是右键改其属性。这不能不说是 Firefox 收藏夹的遗憾。

兼容 IE6、IE7、FF 的"加入收藏"完整代码:
<?xml version="1.0" encoding="gb2312"?>
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
  <title>兼容 IE6、IE7、FF 的"加入收藏"</title>
  </head>
<body>
<script type="text/javascript" language="javascript">
  <!--
  function AddFavorite(sURL, sTitle)
  {
  try
  {
  window.external.addFavorite(sURL, sTitle);
  }
  catch (e)
  {
  try
  {
  window.sidebar.addPanel(sTitle, sURL, "");
  }
  catch (e)
  {
  alert("加入收藏失败,有劳您手动添加。");
  }
  }
  }
  -->
  </script>
<p>
  <a href="#" onclick="javascript:AddFavorite('http://www.cftea.com/', '千一网络 - 网页技术 永无止境');return false">加入收藏</a>
  </p>
</body>
</html>

Java高清晰高品质 图片压缩

在jdk1.6以下的版本环境下,压缩部分图片会很慢,经过我测试,如果图片的DPI越高,速度越慢,一般WEB使用图片DPI都是72,速度很快。大家可以试下。我测试了几张DPI为300,印刷品质的图片,大概要35秒左右,当然还和机器内存有关。

在jdk1.6环境下,速度能令人满意,从之前的35秒减少到了1秒多一点点。提升了这么多,jdk1.6改进实在是大。

 

经过我调试发现,慢的部分主要是在g2.drawImage(image, 0, 0,imageWidth, imageHeight, Color.white,null);,这一句。

主要的压缩代码是public static void ImageScale(String path,String fileName,String toFileName) 这个方法。

以下是我的代码,大家可以参考改进。

  1. package sundy.img;
  2. /**
  3.  * ImageCompress 提供用户将大图片按比例压缩为小图片,支持JPG
  4.  * Please refer to: <BR>
  5.  * http://blog.csdn.net/feng_sundy/archive/2008/08/05/2769572.aspx
  6.  * <P>
  7.  * @author feng_sunddy <sundysea@hotmail.com>
  8.  * @version 1.0
  9.  * @see java.awt.image.BufferedImage
  10. **/
  11. import java.awt.BorderLayout;
  12. import java.awt.Button;
  13. import java.awt.TextField;
  14. import java.awt.Color;
  15. import java.awt.Dimension;
  16. import java.awt.FileDialog;
  17. import java.awt.Font;
  18. import java.awt.Frame;
  19. import java.awt.Graphics;
  20. import java.awt.Graphics2D;
  21. import java.awt.Image;
  22. import java.awt.Insets;
  23. import java.awt.Label;
  24. import java.awt.MediaTracker;
  25. import java.awt.Panel;
  26. import java.awt.Toolkit;
  27. import java.awt.event.ActionEvent;
  28. import java.awt.event.ActionListener;
  29. import java.awt.event.WindowAdapter;
  30. import java.awt.event.WindowEvent;
  31. import java.awt.image.BufferedImage;
  32. import java.awt.image.ConvolveOp;
  33. import java.awt.image.Kernel;
  34. import java.io.File;
  35. import java.io.FileNotFoundException;
  36. import java.io.FileOutputStream;
  37. import java.io.IOException;
  38. import com.sun.image.codec.jpeg.JPEGCodec;
  39. import com.sun.image.codec.jpeg.JPEGImageEncoder;
  40. public class ImageCompress extends Frame {
  41.     private static final long serialVersionUID = 48L;
  42.     
  43.     public static void main(String[] args){
  44.         String fileName = "F:/share/bigimages/b-4.jpg";
  45.         String gui = "";
  46.     if (args.length > 0) fileName = args[0];
  47.     if (args.length > 1) gui = "gui";
  48.     if (gui.equals("gui")){
  49.       new ImageCompress(fileName);
  50.     }else{
  51.             long c = System.currentTimeMillis();
  52.             ImageCompress.ImageScale(getFilePath(fileName), getFileFullName(fileName), getFileName(fileName) + "-s." + getFileExt(fileName).toLowerCase());
  53.             System.out.println("elapse time:" + (System.currentTimeMillis() - c)/1000.0f + "s");
  54.       }
  55.     }
  56.     
  57.     private static final String version = "ImageCompress v1.0";
  58.     
  59.   public ImageCompress(String fileName) {
  60.     super(version);
  61.     file = fileName;
  62.     createUI();
  63.     loadImage(fileName);
  64.     setVisible(true);
  65.   }
  66.   /**
  67.    * A Hashtable member variable holds the image processing
  68.    * operations, keyed by their names.
  69.   **/
  70.   
  71.     private Panel mControlPanel;
  72.     
  73.     private BufferedImage mBufferedImage;
  74.     
  75.     private Label labelWidth = new Label("width:");    
  76.     private TextField textWidth = new TextField(7);
  77.   
  78.     private Label labelHeight = new Label("height:");    
  79.     private TextField textHeight = new TextField(7);
  80.     
  81.     private String file;
  82.   /**
  83.    * createUI() creates the user controls and lays out the window.
  84.    * It also creates the event handlers (as inner classes) for
  85.    * the user controls.
  86.   **/
  87.   private void createUI() {
  88.     setFont(new Font("Serif", Font.PLAIN, 12));
  89.     // Use a BorderLayout. The image will occupy most of the window,
  90.     //   with the user controls at the bottom.
  91.     setLayout(new BorderLayout());
  92.   
  93.     // Use a Label to display status messages to the user.
  94.     final Label statusLabel = new Label("Welcome to " + version + ".");
  95.     
  96.     textWidth.setText("160");
  97.     textHeight.setText("160");
  98.     // Create a Button for loading a new image.
  99.     Button loadButton = new Button("Load...");
  100.     // Add a listener for the button. It pops up a file dialog
  101.     //   and loads the selected image file.
  102.     loadButton.addActionListener(new ActionListener() {
  103.       public void actionPerformed(ActionEvent ae) {
  104.         FileDialog fd = new FileDialog(ImageCompress.this);
  105.         fd.setVisible(true);
  106.         if (fd.getFile() == nullreturn;
  107.         String path = fd.getDirectory() + fd.getFile();
  108.         file = path;
  109.         loadImage(path);
  110.       }
  111.     });
  112.     
  113.     Button buttonResize = new Button("Resize");
  114.     buttonResize.addActionListener(new ActionListener(){
  115.         public void actionPerformed(ActionEvent ae){
  116.             resizeImage(file);
  117.             
  118.         }
  119.     });
  120.     // Add the user controls at the bottom of the window.
  121.     mControlPanel = new Panel();
  122.     mControlPanel.add(loadButton);
  123.     mControlPanel.add(labelWidth);
  124.     mControlPanel.add(textWidth);
  125.     mControlPanel.add(labelHeight);
  126.     mControlPanel.add(textHeight);
  127.     mControlPanel.add(buttonResize);
  128.     //mControlPanel.add(processChoice);
  129.     mControlPanel.add(statusLabel);
  130.     add(mControlPanel, BorderLayout.SOUTH);
  131.     // Terminate the application if the user closes the window.
  132.     addWindowListener(new WindowAdapter() {
  133.       public void windowClosing(WindowEvent e) {
  134.         dispose();
  135.         System.exit(0);
  136.       }
  137.     });
  138.   }
  139.   
  140.   private void resizeImage(String fileName){
  141.     try{
  142.         Image image = javax.imageio.ImageIO.read(new File(file));
  143.         int imageWidth = image.getWidth(null);
  144.         int imageHeight = image.getHeight(null);
  145.         
  146.         float scale = getRatio(imageWidth,imageHeight,Integer.parseInt(textWidth.getText()),Integer.parseInt(textWidth.getText()));
  147.         imageWidth = (int)(scale*imageWidth);
  148.         imageHeight = (int)(scale*imageHeight);
  149.         
  150.         image = image.getScaledInstance(imageWidth, imageHeight, Image.SCALE_AREA_AVERAGING);
  151.         // Make a BufferedImage from the Image.
  152.         mBufferedImage = new BufferedImage(imageWidth, imageHeight,BufferedImage.TYPE_INT_RGB);
  153.         Graphics2D g2 = mBufferedImage.createGraphics();
  154.             
  155.         //Map readeringHint = new HashMap();
  156.             //readeringHint.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
  157.         //readeringHint.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  158.         //readeringHint.put(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
  159.         //readeringHint.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
  160.         //readeringHint.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);//VALUE_INTERPOLATION_BICUBIC
  161.         //readeringHint.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  162.         //g.setRenderingHints(readeringHint);
  163.             
  164.         g2.drawImage(image, 00,imageWidth, imageHeight, Color.white,null);
  165.     
  166.             float[] kernelData2 = { 
  167.                     -0.125f, -0.125f, -0.125f,
  168.             -0.125f,2, -0.125f,
  169.             -0.125f,-0.125f, -0.125f };
  170.         Kernel kernel = new Kernel(33, kernelData2);
  171.         ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
  172.         mBufferedImage = cOp.filter(mBufferedImage, null);
  173.         repaint();
  174.         //file = ImageCompress.getFilePath(file) + ImageCompress.getFileName(file) + "-s." + ImageCompress.getFileExt(file).toLowerCase(); 
  175.         //FileOutputStream out = new FileOutputStream(file);
  176.         //JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage);
  177.         //param.setQuality(0.9f, true);
  178.         //encoder.setJPEGEncodeParam(param);
  179.         //JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
  180.         //encoder.encode(mBufferedImage);
  181.         //out.close();      
  182.       }catch (IOException e){
  183.       }
  184.   }
  185.   
  186.   private void loadImage(String fileName) {
  187.     // Use a MediaTracker to fully load the image.
  188.     Image image = Toolkit.getDefaultToolkit().getImage(fileName);
  189.     MediaTracker mt = new MediaTracker(this);
  190.     mt.addImage(image, 0);
  191.     try { mt.waitForID(0); }
  192.     catch (InterruptedException ie) { return; }
  193.     if (mt.isErrorID(0)) return;
  194.     // Make a BufferedImage from the Image.
  195.     mBufferedImage = new BufferedImage(
  196.         image.getWidth(null), image.getHeight(null),
  197.         BufferedImage.TYPE_INT_RGB);
  198.     Graphics2D g2 = mBufferedImage.createGraphics();
  199.     g2.drawImage(image, nullnull);
  200.     adjustToImageSize();
  201.     center();
  202.     validate();
  203.     repaint();
  204.     setTitle(version + ": " + fileName);
  205.   }
  206.   
  207.   private void adjustToImageSize() {
  208.     if (!isDisplayable()) addNotify(); // Do this to get valid Insets.
  209.     Insets insets = getInsets();
  210.     int imageWidth = mBufferedImage.getWidth(); 
  211.     int imageHeight = mBufferedImage.getHeight();
  212.     imageWidth = 600;
  213.     imageHeight = 550;
  214.     int w = imageWidth + insets.left + insets.right;
  215.     int h = imageHeight + insets.top + insets.bottom;
  216.     h += mControlPanel.getPreferredSize().height;
  217.     setSize(w, h);
  218.   }
  219.   
  220.   /**
  221.    * Center this window in the user's desktop.
  222.   **/
  223.   private void center() {
  224.     Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
  225.     Dimension d = getSize();
  226.     int x = (screen.width - d.width) / 2;
  227.     int y = (screen.height - d.height) / 2;
  228.     setLocation(x, y);
  229.   }
  230.   
  231.   /**
  232.    * All paint() has to do is show the current image.
  233.   **/
  234.   public void paint(Graphics g) {
  235.     if (mBufferedImage == nullreturn;
  236.     Insets insets = getInsets();
  237.     g.drawImage(mBufferedImage, insets.left, insets.top, null);
  238.   }
  239.   
  240.   public static void ImageScale(String path,String fileName,String toFileName){
  241.     try {
  242.         Image image = javax.imageio.ImageIO.read(new File(path + fileName));
  243.         int imageWidth = image.getWidth(null);
  244.         int imageHeight = image.getHeight(null);
  245.         float scale = getRatio(imageWidth,imageHeight,130,130);
  246.         imageWidth = (int)(scale*imageWidth);
  247.         imageHeight = (int)(scale*imageHeight);
  248.         
  249.         image = image.getScaledInstance(imageWidth, imageHeight, Image.SCALE_AREA_AVERAGING);
  250.         // Make a BufferedImage from the Image.
  251.         BufferedImage mBufferedImage = new BufferedImage(imageWidth, imageHeight,BufferedImage.TYPE_INT_RGB);
  252.         Graphics2D g2 = mBufferedImage.createGraphics();
  253.             
  254.         //Map readeringHint = new HashMap();
  255.             //readeringHint.put(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
  256.         //readeringHint.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  257.         //readeringHint.put(RenderingHints.KEY_COLOR_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
  258.         //readeringHint.put(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
  259.         //readeringHint.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);//VALUE_INTERPOLATION_BICUBIC
  260.         //readeringHint.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
  261.         //g.setRenderingHints(readeringHint);
  262.             
  263.         g2.drawImage(image, 00,imageWidth, imageHeight, Color.white,null);
  264.         g2.dispose();
  265.         
  266.             float[] kernelData2 = { 
  267.                     -0.125f, -0.125f, -0.125f,
  268.           -0.125f,2, -0.125f,
  269.           -0.125f,-0.125f, -0.125f };
  270.         Kernel kernel = new Kernel(33, kernelData2);
  271.         ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
  272.         mBufferedImage = cOp.filter(mBufferedImage, null);
  273.         FileOutputStream out = new FileOutputStream(path + toFileName);
  274.       //JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bufferedImage);
  275.       //param.setQuality(0.9f, true);
  276.       //encoder.setJPEGEncodeParam(param);
  277.         JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
  278.         encoder.encode(mBufferedImage);
  279.         out.close();
  280.     }catch (FileNotFoundException fnf){
  281.     }catch (IOException ioe){
  282.     }finally{
  283.     
  284.     }
  285.   }
  286.   
  287.   public static float getRatio(int width,int height,int maxWidth,int maxHeight){
  288.     float Ratio = 1.0f;
  289.     float widthRatio ;
  290.     float heightRatio ;
  291.     widthRatio = (float)maxWidth/width;
  292.     heightRatio = (float)maxHeight/height;
  293.     if(widthRatio<1.0 || heightRatio<1.0){
  294.       Ratio = widthRatio<=heightRatio?widthRatio:heightRatio;
  295.     }
  296.     return Ratio;
  297.   }
  298.   
  299.   public static String getFileExt(String filePath) {
  300.     String tmp = filePath.substring(filePath.lastIndexOf(".") + 1);
  301.     return tmp.toUpperCase();
  302.   }
  303.   public static String getFileName(String filePath) {
  304.     int pos = -1;
  305.     int endPos = -1;
  306.     if (!filePath.equals("")) {
  307.       if (filePath.lastIndexOf("/") != -1) {
  308.         pos = filePath.lastIndexOf("/") + 1;
  309.       } else if (filePath.lastIndexOf("\\") != -1) {
  310.         pos = filePath.lastIndexOf("\\") + 1;
  311.       }
  312.       if (pos == -1)
  313.         pos = 0;
  314.       filePath = filePath.substring(pos);
  315.       endPos = filePath.lastIndexOf(".");
  316.       if (endPos == -1) {
  317.         return filePath;
  318.       } else {
  319.         return filePath.substring(0, endPos);
  320.       }
  321.     } else {
  322.       return "";
  323.     }
  324.   }
  325.   public static String getFileFullName(String filePath) {
  326.     int pos = -1;
  327.     if (!filePath.equals("")) {
  328.       if (filePath.lastIndexOf("/") != -1) {
  329.         pos = filePath.lastIndexOf("/") + 1;
  330.       } else if (filePath.lastIndexOf("\\") != -1) {
  331.         pos = filePath.lastIndexOf("\\") + 1;
  332.       }
  333.       if (pos == -1)
  334.         pos = 0;
  335.       return filePath.substring(pos);
  336.     } else {
  337.       return "";
  338.     }
  339.   }
  340.   
  341.   public static String getFilePath(String filePath) {
  342.     int pos = -1;
  343.     if (!filePath.equals("")) {
  344.       if (filePath.lastIndexOf("/") != -1) {
  345.         pos = filePath.lastIndexOf("/") + 1;
  346.       } else if (filePath.lastIndexOf("\\") != -1) {
  347.         pos = filePath.lastIndexOf("\\") + 1;
  348.       }
  349.       if (pos != -1) {
  350.         return filePath.substring(0, pos);
  351.       } else {
  352.         return "";
  353.       }
  354.     } else {
  355.       return "";
  356.     }
  357.   }
  358. }

java API 写文本文件比较 FileOutputStream, BufferedOutputStream, FileWriter

对于java.io包中的FileOutputStream,BufferedOutputStream和FileWriter三个不同类写入到文本文件性能,
测试代码和结果如下:
环境: 机器ibm thinkpad 61i,
配置:2.0G双核CPU,2G内存,操作系统xp sp2,java api1.5.

  1. import java.io.BufferedOutputStream;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.FileWriter;
  5. public class TestTxtWriter {
  6.     public TestTxtWriter() {
  7.     }
  8.     public static void main(String[] args) {
  9.         FileOutputStream out = null;
  10.         FileOutputStream outSTr = null;
  11.         BufferedOutputStream Buff = null;
  12.         FileWriter fw = null;
  13.         int count = 10000000;// 写文件行数   
  14.         try {
  15.             out = new FileOutputStream(new File("D:/FileOutputStream.txt"));
  16.             long begin = System.currentTimeMillis();
  17.             for (int i = 0; i < count; i++) {
  18.                 out.write("测试FileOutputStream,BufferedOutputStream和FileWriter,对文件写操作\r\n".getBytes());
  19.             }
  20.             out.close();
  21.             long end = System.currentTimeMillis();
  22.             System.out.println("FileOutputStream执行耗时:" + (end - begin) + " 豪秒");
  23.             outSTr = new FileOutputStream(new File("D:/BufferedOutputStream.txt"));
  24.             Buff = new BufferedOutputStream(outSTr);
  25.             long begin0 = System.currentTimeMillis();
  26.             for (int i = 0; i < count; i++) {
  27.                 Buff.write("测试FileOutputStream,BufferedOutputStream和FileWriter,对文件写操作\r\n"  .getBytes());
  28.             }
  29.             Buff.flush();
  30.             Buff.close();
  31.             long end0 = System.currentTimeMillis();
  32.             System.out.println("BufferedOutputStream执行耗时:" + (end0 - begin0) + " 豪秒");
  33.             fw = new FileWriter("D:/FileWriter.txt");
  34.             long begin3 = System.currentTimeMillis();
  35.             for (int i = 0; i < count; i++) {
  36.                 fw.write("测试FileOutputStream,BufferedOutputStream和FileWriter,对文件写操作\r\n");
  37.             }
  38.             fw.close();
  39.             long end3 = System.currentTimeMillis();
  40.             System.out.println("FileWriter执行耗时:" + (end3 - begin3) + " 豪秒");
  41.         } catch (Exception e) {
  42.             e.printStackTrace();
  43.         } finally {
  44.             try {
  45.                 fw.close();
  46.                 Buff.close();
  47.                 outSTr.close();
  48.                 out.close();
  49.             } catch (Exception e) {
  50.                 e.printStackTrace();
  51.             }
  52.         }
  53.     }
  54. }
 

以下结果经过多次执行,取常出现的数据,由于只是简单比较,不做详细统计。

1.当count=1 000的,即写文件1 000行的时候,写出的文件大小为66.4KB:
FileOutputStream执行耗时:31 豪秒
BufferedOutputStream执行耗时:16 豪秒
FileWriter执行耗时:0 豪秒

2.当count=10 000的,即写文件10 000行的时候,写出的文件大小为664KB:
FileOutputStream执行耗时:78 豪秒
BufferedOutputStream执行耗时:32 豪秒
FileWriter执行耗时:15 豪秒

3.当count=100 000的,即写文件100 000行的时候,写出的文件大小为6.7MB:
FileOutputStream执行耗时:453 豪秒
BufferedOutputStream执行耗时:172 豪秒
FileWriter执行耗时:156 豪秒

4.当count=1 000 000的,即写文件1 000 000行的时候,写出的文件大小为64.8MB:
FileOutputStream执行耗时:4500 豪秒
BufferedOutputStream执行耗时:2422 豪秒
FileWriter执行耗时:2500 豪秒

5.当count=10 000 000的,即写文件10 000 000行的时候,写出的文件大小为648MB:
FileOutputStream执行耗时:52453 豪秒
BufferedOutputStream执行耗时:25921 豪秒
FileWriter执行耗时:36094 豪秒

FileOutputStream执行耗时:51547 豪秒
BufferedOutputStream执行耗时:35203 豪秒
FileWriter执行耗时:31609 豪秒

FileOutputStream执行耗时:50078 豪秒
BufferedOutputStream执行耗时:33515 豪秒
FileWriter执行耗时:29516 豪秒

由以上数据可以看到,如果不用缓冲流BufferedOutputStream,FileOutputStream写文件的鲁棒性是很不好的。当写 10 000 000行的文件的时候,FileOutputStream比FileWriter要慢10 000-21 000毫秒(10-21秒)。

不要小看这几秒的时间。当操作的数据量很大的时候,这点性能的差距就会很大了。在操作数据库,通过java导出生成数亿条记录文件的时候,等待的时间要10分钟以上,性能相差大了。

JavaScript验证正则表达式大全

匹配中文字符的正则表达式: [u4e00-u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了

匹配双字节字符(包括汉字在内):[^x00-xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

匹配空白行的正则表达式:ns*r
评注:可以用来删除空白行

匹配HTML标记的正则表达式:< (S*?)[^>]*>.*?|< .*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力

匹配首尾空白字符的正则表达式:^s*|s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式

匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
评注:表单验证时很实用

匹配网址URL的正则表达式:[a-zA-z]+://[^s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求

匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用

匹配国内电话号码:d{3}-d{8}|d{4}-d{7}
评注:匹配形式如 0511-4405222 或 021-87888822

匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始

匹配中国邮政编码:[1-9]d{5}(?!d)
评注:中国邮政编码为6位数字

匹配身份证:d{15}|d{18}
评注:中国的身份证为15位或18位

匹配ip地址:d+.d+.d+.d+
评注:提取ip地址时有用


匹配特定数字:
^[1-9]d*$    //匹配正整数
^-[1-9]d*$   //匹配负整数
^-?[1-9]d*$   //匹配整数
^[1-9]d*|0$  //匹配非负整数(正整数 + 0)
^-[1-9]d*|0$   //匹配非正整数(负整数 + 0)
^[1-9]d*.d*|0.d*[1-9]d*$   //匹配正浮点数
^-([1-9]d*.d*|0.d*[1-9]d*)$  //匹配负浮点数
^-?([1-9]d*.d*|0.d*[1-9]d*|0?.0+|0)$  //匹配浮点数
^[1-9]d*.d*|0.d*[1-9]d*|0?.0+|0$   //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]d*.d*|0.d*[1-9]d*))|0?.0+|0$  //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正

匹配特定字符串:
^[A-Za-z]+$  //匹配由26个英文字母组成的字符串
^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串
^[a-z]+$  //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串
^w+$  //匹配由数字、26个英文字母或者下划线组成的字符串

在使用RegularExpressionValidator验证控件时的验证功能及其验证表达式介绍如下:
只能输入数字:"^[0-9]*$"
只能输入n位的数字:"^d{n}$"
只能输入至少n位数字:"^d{n,}$"
只能输入m-n位的数字:"^d{m,n}$"
只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"
只能输入有两位小数的正实数:"^[0-9]+(.[0-9]{2})?$"
只能输入有1-3位小数的正实数:"^[0-9]+(.[0-9]{1,3})?$"
只能输入非零的正整数:"^+?[1-9][0-9]*$"
只能输入非零的负整数:"^-[1-9][0-9]*$"
只能输入长度为3的字符:"^.{3}$"
只能输入由26个英文字母组成的字符串:"^[A-Za-z]+$"
只能输入由26个大写英文字母组成的字符串:"^[A-Z]+$"
只能输入由26个小写英文字母组成的字符串:"^[a-z]+$"
只能输入由数字和26个英文字母组成的字符串:"^[A-Za-z0-9]+$"
只能输入由数字、26个英文字母或者下划线组成的字符串:"^w+$"
验证用户密码:"^[a-zA-Z]w{5,17}$"正确格式为:以字母开头,长度在6-18之间,


只能包含字符、数字和下划线。
验证是否含有^%&',;=?$"等字符:"[^%&',;=?$x22]+"
只能输入汉字:"^[u4e00-u9fa5],{0,}$"
验证Email地址:"^w+[-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*$"
验证InternetURL:"^http://([w-]+.)+[w-]+(/[w-./?%&=]*)?$"
验证电话号码:"^((d{3,4})|d{3,4}-)?d{7,8}$"


正确格式为:"XXXX-XXXXXXX","XXXX-XXXXXXXX","XXX-XXXXXXX",


"XXX-XXXXXXXX","XXXXXXX","XXXXXXXX"。
验证身份证号(15位或18位数字):"^d{15}|d{}18$"
验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"-"09"和"1""12"
验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"


正确格式为:"01""09"和"1""31"。


匹配中文字符的正则表达式: [u4e00-u9fa5]
匹配双字节字符(包括汉字在内):[^x00-xff]
匹配空行的正则表达式:n[s| ]*r
匹配HTML标记的正则表达式:/< (.*)>.*|< (.*) />/
匹配首尾空格的正则表达式:(^s*)|(s*$)
匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
匹配网址URL的正则表达式:http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?

(1)应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
String.prototype.len=function(){return this.replace([^x00-xff]/g,"aa").length;}

(2)应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现
String.prototype.trim = function()
{
return this.replace(/(^s*)|(s*$)/g, "");
}
(3)应用:利用正则表达式分解和转换IP地址
function IP2V(ip) //IP地址转换成对应数值
{
re=/(d+).(d+).(d+).(d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}
(4)应用:从URL地址中提取文件名的javascript程序
s="http://www.9499.net/page1.htm";
s=s.replace(/(.*/){0,}([^.]+).*/ig,"$2") ; //Page1.htm
(5)应用:利用正则表达式限制网页表单里的文本框输入内容
用正则表达式限制只能输入中文:onkeyup="value="/blog/value.replace(/["^u4E00-u9FA5]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))"
用正则表达式限制只能输入全角字符: onkeyup="value="/blog/value.replace(/["^uFF00-uFFFF]/g,'') " onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))"
用正则表达式限制只能输入数字:onkeyup="value="/blog/value.replace(/["^d]/g,'') "onbeforepaste= "clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"
用正则表达式限制只能输入数字和英文:onkeyup="value="/blog/value.replace(/[W]/g,"'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''