Archive for the 'JavaBasic' Category

You are currently browsing the archives of Enabling Technology .

Swing thread articles

 

http://www.yesky.com/418/1743418_5.shtml

http://java.chinaitlab.com/line/10270.html

http://fanqiang.chinaunix.net/program/java/2005-07-04/3363.shtml

http://www.21tx.com/dev/2002/02/22/10107.html

http://www.ddvip.com/program/java/index2/79.htm

http://www.ddvip.com/program/java/index2/78.htm

http://www.21tx.com/dev/2005/04/07/14818.html

http://www.jspcn.net/htmlnews/11049310422031206.html

http://www.matrix.org.cn/resource/article/0/132.html

Posted by micas on Jun 13th 2008 | Filed in JavaBasic | Comments (2)

Implementation for running OS commands by using Java [Chinese]

enabling-tech.com原创】

Java 语言本身提供了执行外部程序的机制,那就是java.lang.Runtime。改类自Java诞生就已经从在,这个可以从见JDK帮助文档的Since得到。随着Java的发展,该类也多次修订。http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Runtime.html

改类提供了6个重载的方法(截至目前1.5版本),我们把它拷过来,用作参考:

Process exec(String command)
Executes the specified string command in a separate process.

Process exec(String[] cmdarray)
Executes the specified command and arguments in a separate process.

Process exec(String[] cmdarray, String[] envp)
Executes the specified command and arguments in a separate process with the specified environment.

Process exec(String[] cmdarray, String[] envp, File dir)
Executes the specified command and arguments in a separate process with the specified environment and working directory.

Process exec(String command, String[] envp)
Executes the specified string command in a separate process with the specified environment.

Process exec(String command, String[] envp, File dir)
Executes the specified string command in a separate process with the specified environment and working directory

按照文档上说,这行exec,就会产生一个与操作系统相关的process,Java用Process与之相联系,就是在Process里面有个这个实际的Process的引用。类Process的说明如下:

The ProcessBuilder.start() and Runtime.exec methods create a native process and return an instance of a subclass of Process that can be used to control the process and obtain information about it.

就是说执行了exec,剩下的(输入,输出,等待结束,结束返回值等等)就交给Process具体的实现类来处理:

The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.

网络上有很多介绍的文章,但是如果你看了还是不是很明白的话,其实最重要的还是回到JDK的帮助文档里来,在类Process的文档剩下的部分写的很明白:

The methods that create processes may not work well for special processes on certain native platforms, such as native windowing processes, daemon processes, Win16/DOS processes on Microsoft Windows, or shell scripts. The created subprocess does not have its own terminal or console. All its standard io (i.e. stdin, stdout, stderr) operations will be redirected to the parent process through three streams (getOutputStream(), getInputStream(), getErrorStream()). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, and even deadlock.

The subprocess is not killed when there are no more references to the Process object, but rather the subprocess continues executing asynchronously.

There is no requirement that a process represented by a Process object execute asynchronously or concurrently with respect to the Java process that owns the Process object.

简单的说,所有的标准IO操作都会转给父进程,父进程需要用那三种流给子进程。更糟的是标准输入输出流的缓冲啊,就是buffer,有些操作系统给的是有限的(废话),那么不能及时写输入和读输出给子进程就或许导致子进程被block或者甚至死锁!

明白了上边的几点,我们来看一段例程,就比较清楚了:

直接使用参考文献1中的例程:

public class BadExecJavac
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec(”javac”);
int exitVal = proc.exitValue();
System.out.println(”Process exitValue: ” + exitVal);
}
catch (Throwable t)
{
t.printStackTrace();
}
}
}

执行结果如下:

java.lang.IllegalThreadStateException: process has not exited
at java.lang.ProcessImpl.exitValue(Native Method)
at com.test.tools.test.book.Test.main(Test.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)

什么原因呢? 查查文档,原来是说子进程还未结束,如果call exitValue()的话,就会报错。

老方法,查查文档,Process有个waitFor() 方法:

waitFor
public abstract int waitFor()
                     throws InterruptedException
causes the current thread to wait, if necessary, until the process represented by this Process object has terminated. This method returns immediately if the subprocess has already terminated. If the subprocess has not yet terminated, the calling thread will be blocked until the subprocess exits.
Returns:
the exit value of the process. By convention, 0 indicates normal termination.
Throws:
InterruptedException - if the current thread is interrupted by another thread while it is waiting, then the wait is ended and an InterruptedException is thrown.

好,我们立即改进我们的程序,使用waitFor():

public class Test

{

public static void main(String args[])

{

try

{

Runtime rt = Runtime.getRuntime();

Process proc = rt.exec(”javac”);

int exitVal = proc.waitFor();

System.out.println(”Process exitValue: ” + exitVal);

}

catch (Throwable t)

{

t.printStackTrace();

}

}

}

编译,运行。。。结果。。。结果。。。好像死在那里了#¥@%@@

好惨。。。立刻反省一下哪里错了?原来前文有提:我们没有处理输入,输出流×可能会×导致死锁! Javac执行如上的话,会把结果输入到stderr流中去的,结果父进程没有处理(所有的外部流都导给父进程,见文档),子进程等父进程处理,父进程等子进程结束(waitFor()),典型的死锁情节。下面,我们的程序需要加上流的处理的部分!

import java.io.BufferedReader;

import java.io.InputStream;

import java.io.InputStreamReader;

public class Test

{

public static void main(String args[])

{

try

{

Runtime rt = Runtime.getRuntime();

Process proc = rt.exec(”javac”);
//prepare to receive input err stream directed to This Process to drain.

InputStream stderr = proc.getErrorStream(); 得到错误流

InputStreamReader isr = new InputStreamReader(stderr);

BufferedReader br = new BufferedReader(isr);

String line = null;

System.out.println(”<ERROR>”);

while ((line = br.readLine()) != null)

{

System.out.println(line);

}

System.out.println(”</ERROR>”);

int exitVal = proc.waitFor();

System.out.println(”Process exitValue: ” + exitVal);

}

catch (Throwable t)

{

t.printStackTrace();

}

}

}

运行结果如下:

<ERROR>

用法:javac <选项> <源文件>

其中,可能的选项包括:

-g                         生成所有调试信息

-g:none                    不生成任何调试信息

-g:{lines,vars,source}     只生成某些调试信息

-nowarn                    不生成任何警告

-verbose                   输出有关编译器正在执行的操作的消息

-deprecation               输出使用已过时的 API 的源位置

-classpath <路径>            指定查找用户类文件的位置

-cp <路径>                   指定查找用户类文件的位置

-sourcepath <路径>           指定查找输入源文件的位置

-bootclasspath <路径>        覆盖引导类文件的位置

-extdirs <目录>              覆盖安装的扩展目录的位置

-endorseddirs <目录>         覆盖签名的标准路径的位置

-d <目录>                    指定存放生成的类文件的位置

-encoding <编码>             指定源文件使用的字符编码

-source <版本>               提供与指定版本的源兼容性

-target <版本>               生成特定 VM 版本的类文件

-version                   版本信息

-help                      输出标准选项的提要

-X                         输出非标准选项的提要

-J<标志>                     直接将 <标志> 传递给运行时系统

</ERROR>

Process exitValue: 2

Process finished with exit code 0

因为我在IDE里运行的,所以你会看到退出码是0,就是这个java类运行是正常。但是对于javac在例程中运行code是2.不同系统不同意义,这里代表文件没有找到。一般来说,0代表正常,非0都代表错误。

这段程序对这个例子来说足够了,但是缺乏灵活和完美!最要命的是这个程序还没有处理标准输入和输出流。

在开始完美化之前,先说说一个常见的错误。或许你已经迫不及待的编写和运行如下程序,结果发现是有问题的:

public class Test

{

public static void main(String args[])

{

try

{

Runtime rt = Runtime.getRuntime();

     Process proc = rt.exec(”dir”);

InputStream stdin = proc.getInputStream();

InputStreamReader isr = new InputStreamReader(stdin);

BufferedReader br = new BufferedReader(isr);

String line = null;

System.out.println(”<OUTPUT>”);

while ((line = br.readLine()) != null)

{

System.out.println(line);

}

System.out.println(”</OUTPUT>”);

int exitVal = proc.waitFor();

System.out.println(”Process exitValue: ” + exitVal);

}

catch (Throwable t)

{

t.printStackTrace();

}

}

}

为什么不行呢?这是因为dir这个命令需要windows 命令解释器,而不是一个单独存在的命令!也就是说该程序无法找到dir.

现在就让我们开始振奋人心的编程吧!采用一个专门的类处理外部程序需要输出的流,对于我们来说就是输入流。采用线程执行,所以可以异步的处理多个流。

/**

*  gobbler

1. 雄火鸡

2. 狼吞虎咽的人

*/

class StreamGobbler extends Thread

{

InputStream is;

String type;

StreamGobbler(InputStream is, String type)

{

this.is = is;

this.type = type;

}

public void run()

{

try

{

InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);

String line = null;

while ((line = br.readLine()) != null)

{

System.out.println(type + “>” + line);

}

}

catch (IOException ioe)

{

ioe.printStackTrace();

}

}

}

class GoodWindowsExec

{

public static void main(String args[])

{

if (args.length < 1)

{

System.out.println(”USAGE: java GoodWindowsExec <cmd>”);

System.exit(1);

}

try

{

String osName = System.getProperty(”os.name”);

String[] cmd = new String[3];

if (osName.equals(”Windows NT”))

{

cmd[0] = “cmd.exe”;

cmd[1] = “/C”;

cmd[2] = args[0];

}

else if (osName.equals(”Windows 95″))

{

cmd[0] = “command.com”;

cmd[1] = “/C”;

cmd[2] = args[0];

}

Runtime rt = Runtime.getRuntime();

System.out.println(”Execing ” + cmd[0] + ” ” + cmd[1]

+ ” ” + cmd[2]);

Process proc = rt.exec(cmd);

// any error message?

StreamGobbler errorGobbler = new

                    StreamGobbler(proc.getErrorStream(), “ERROR”);

            // any output?

StreamGobbler outputGobbler = new

                    StreamGobbler(proc.getInputStream(), “OUTPUT”);

            // kick them off

errorGobbler.start();

            outputGobbler.start();

// 还是惹不起那些进程,我等。

int exitVal = proc.waitFor();

System.out.println(”ExitValue: ” + exitVal);

}

catch (Throwable t)

{

t.printStackTrace();

}

}

}

用这个方式执行:

列目录,java GoodWindowsExec “dir *.java” 。

打开word文档,java GoodWindowsExec “yourdoc.doc”。其他就不赘述了。

另外,要记住,exec不是个命令解释器,它的作用只是运行命令。千万不要认为exec() method 好像一个shell interpreter。如果你那么认为,就会犯下面的错误:

class BadWinRedirect

{

public static void main(String args[])

{

try

{

Runtime rt = Runtime.getRuntime();

Process proc = rt.exec(”java jecho ‘Hello World’ > test.txt”);

// any error message?

StreamGobbler errorGobbler = new

StreamGobbler(proc.getErrorStream(), “ERROR”);

// any output?

StreamGobbler outputGobbler = new

StreamGobbler(proc.getInputStream(), “OUTPUT”);

// kick them off

errorGobbler.start();

outputGobbler.start();

// any error???

int exitVal = proc.waitFor();

System.out.println(”ExitValue: ” + exitVal);

}

catch (Throwable t)

{

t.printStackTrace();

}

}

}

该程序本意是想执行jecho ‘Hello World‘,然后把执行结果存入test.txt。Sorry,错了。你必须用编程的方法来实现。还记得我们前面说过子进程的输出流么,把子进程的输出流===》得到,然后存入test.txt就可以实现了。

有点晕?呵呵。我们里一下思路。该例程运行程序(java jecho ‘Hello World’),产生个子进程,子进程产生输出流。子进程如前所述没有地方释放,需要父进程排泄。所以,对父进程来说,就是得到proc.getInputStream(), 就是把子进程要输出的东西得到。

这样还需要改进一下我们(吃流者)这个类。SteamBobbler.:) 如下:

import java.io.BufferedReader;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStream;

import java.io.PrintWriter;

class StreamGobbler extends Thread

{

InputStream is;

String type;

OutputStream os;

StreamGobbler(InputStream is, String type)

{

this(is, type, null);

}

StreamGobbler(InputStream is, String type, OutputStream redirect)

{

this.is = is;

this.type = type;

this.os = redirect;

}

public void run()

{

try

{

       PrintWriter pw = null;

if (os != null)

            {

                pw = new PrintWriter(os);

            }

InputStreamReader isr = new InputStreamReader(is);

BufferedReader br = new BufferedReader(isr);

String line = null;

while ((line = br.readLine()) != null)

{

if (pw != null)

{

          pw.println(line);

}

System.out.println(type + “>” + line);

}

if (pw != null)

{

              pw.flush();

}

}

catch (IOException ioe)

{

ioe.printStackTrace();

}

}

}

class GoodWinRedirect

{

public static void main(String args[])

{

if (args.length < 1)

{

System.out.println(”USAGE java GoodWinRedirect <outputfile>”);

System.exit(1);

}

try

{

FileOutputStream fos = new FileOutputStream(args[0]);

Runtime rt = Runtime.getRuntime();

Process proc = rt.exec(”java jecho ‘Hello World’”);
// any error message?

StreamGobbler errorGobbler = new

StreamGobbler(proc.getErrorStream(), “ERROR”);

// any output?

StreamGobbler outputGobbler = new

StreamGobbler(proc.getInputStream(), “OUTPUT”, fos);

// kick them off

errorGobbler.start();

outputGobbler.start();

// any error???

int exitVal = proc.waitFor();

System.out.println(”ExitValue: ” + exitVal);

fos.flush();

fos.close();

}

catch (Throwable t)

{

t.printStackTrace();

}

}

}

OK,大功告成,基本上成功。

小结如下:

  1. You cannot obtain an exit status from an external process until it has exited
  2. You must immediately handle the input, output, and error streams from your spawned external process
  3. You must use Runtime.exec() to execute programs
  4. You cannot use Runtime.exec() like a command line

本文完。下期谈谈如何使用目录,环境变量等高级话题。

参考文档:

  1. http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html

Posted by micas on Jun 13th 2008 | Filed in JavaBasic, Enabling-tech | Comments (0)

纯java 的javascript引擎:rhino 【转】

关键字: 企业应用   纯java 的javascript引擎 rhino js引擎 java脚本引擎    

前段时间,在浏览javaeye论坛,看见有人征集如何在java中运行数学表达式。
结果方案五花八门:
1.jakarta commons JEXL.
2.Beanshell
3.Java Math Expression Parser jep
4.parse combinator jparsec
5.jdk 6.0的 script
6.利用SQL
7.自己写语法分析
如果自己写语法分析,没有个2000行估计搞不定。有人用sql来运行数学表达式,比较另类。
不过由于前段时间较深入的学习了一些java的javascript引擎,我给出的方案就是用javascript来计算了。
java中比较著名的js引擎当属mozilla开源的rhino,不过jdk6已经把它收归帐下,成了正规军。

  1. public class MathEval   
  2. {   
  3.     public static void main(String[] args)   
  4.     {   
  5.         Context cx = Context.enter();   
  6.         try  
  7.         {   
  8.             Scriptable scope = cx.initStandardObjects();   
  9.             String str = “9*(1+2)”;   
  10.             Object result = cx.evaluateString(scope, str, null1null);   
  11.             double res = Context.toNumber(result);   
  12.             System.out.println(res);   
  13.         }   
  14.         finally  
  15.         {   
  16.             Context.exit();   
  17.         }   
  18.     }   
  19. }  

下面总结一下前段时间学习rhino的心得(给自己的程序添加脚本功能,其实是很酷的):

一:环境配置及运行js脚本:
在 http://www.mozilla.org/rhino/ 下载rhino:
把js.jar加入系统CLASSPATH中
可以以交互模式调用js解释器:
java org.mozilla.javascript.tools.shell.Main
然后您应该会看到解释器的版本号,后面跟着提示符 js>
用法如下:
比如:有一个js文件:
D:\eclipse-workshop\rhinoExample\src\isPrime.js
内容如下:

js 代码

  1. function isPrime (num)   
  2. {   
  3.     if (num <= 1) {   
  4.         print(“Please enter a positive integer >= 2.”)   
  5.         return false  
  6.     }   
  7.        
  8.     var prime = true  
  9.     var sqrRoot = Math.round(Math.sqrt(num))   
  10.        
  11.     for (var n = 2; prime & n <= sqrRoot; ++n) {   
  12.         prime = (num % n != 0)   
  13.     }   
  14.        
  15.     return prime   
  16. }  

如何运行呢:
1:在命令行下键入:
java org.mozilla.javascript.tools.shell.Main
2:在js〉下键入:
load(”D:/eclipse-workshop/rhinoExample/src/isPrime.js”);
注意:是“/”而不是“\”
3:键入:
isPrime(77);
可看见返回结果为false。
键入:
isPrime(71);返回true

再给个例子,脚本如下:

  1. person = {   
  2.   name:“Mike Squillace”,   
  3.   age:37,   
  4.   position:“software engineer”,   
  5.   getFirstName:function () {return this.name.split(“ ”)[0]}   
  6. }   
  7. person.getFirstName()  

js产生swing的例子:
load(”D:/eclipse-workshop/rhinoExample/src/SwingApplication.js”);
怎么样?看见效果没?是不是很强悍?其中SwingApplication.js是rhnio自带的例子。


Rhino还有一个js脚本的调试器:
Rhino JavaScript Debugger:
java org.mozilla.javascript.tools.debugger.Main [options] [filename.js] [script-arguments]

只须运行java org.mozilla.javascript.tools.debugger.Main,就可以看到调试器的界面了。
为了加快js文件运行的速度,可以把它编译为class文件:
compile:
java org.mozilla.javascript.tools.jsc.Main D:/eclipse-workshop/rhinoExample/src/FirstCompile.js
编译产生FirstCompile.class文件
在D:/eclipse-workshop/rhinoExample/src/下运行该class文件:
java FirstCompile

二:在实际应用中不可避免的需要遇到java代码如何和javascript脚本相互访问的问题:
这是一个最简单的例子:(liveConnect.js是rhnio自带的例子):
load(”D:/eclipse-workshop/rhinoExample/src/liveConnect.js”);

在给个复杂点的例子, 没有什么逻辑,纯技术展示,呵呵:
JSFunction.java:

java 代码

  1. package co.test;   
  2.   
  3. import org.mozilla.javascript.Function;   
  4.   
  5. public class JSFunction  //extends ScriptableObject   
  6. {   
  7.  private String name;    
  8.     
  9.  private Function handle;   
  10.     
  11.  public void setHandler(Function func)   
  12.  {   
  13.   this.handle = func;   
  14.  }   
  15.     
  16.  public Function getHandler()   
  17.  {   
  18.   return this.handle;   
  19.  }   
  20.   
  21.     
  22.  public JSFunction(String s)   
  23.  {   
  24.   this.name = s;   
  25.  }    
  26.     
  27.  public static void print(String s)   
  28.  {   
  29.   System.out.println(s);   
  30.  }   
  31.   
  32.  public String getName() {   
  33.   return name;   
  34.  }   
  35.  public void setName(String name) {   
  36.   this.name = name;   
  37.  }   
  38.   
  39. }   
  40.   

JSExploration.java:

java 代码

  1. package co.test;   
  2.   
  3. import java.io.FileReader;   
  4. import java.io.LineNumberReader;   
  5.   
  6. import org.mozilla.javascript.Context;   
  7. import org.mozilla.javascript.Function;   
  8. import org.mozilla.javascript.Scriptable;   
  9.   
  10. public class JSExploration   
  11. {   
  12.     private Context cx;   
  13.   
  14.     private Scriptable scope;   
  15.   
  16.     public JSExploration()   
  17.     {   
  18.         this.cx = Context.enter();   
  19.         this.scope = cx.initStandardObjects();   
  20.     }   
  21.   
  22.     public Object runJavaScript(String filename)   
  23.     {   
  24.         String jsContent = this.getJsContent(filename);   
  25.         Object result = cx.evaluateString(scope, jsContent, filename, 1null);   
  26.         return result;   
  27.     }   
  28.   
  29.     private String getJsContent(String filename)   
  30.     {   
  31.         LineNumberReader reader;   
  32.         try  
  33.         {   
  34.             reader = new LineNumberReader(new FileReader(filename));   
  35.             String s = null;   
  36.             StringBuffer sb = new StringBuffer();   
  37.             while ((s = reader.readLine()) != null)   
  38.             {   
  39.                 sb.append(s).append(“\n”);   
  40.             }   
  41.             return sb.toString();   
  42.         }   
  43.         catch (Exception e)   
  44.         {   
  45.             // TODO Auto-generated catch block   
  46.             e.printStackTrace();   
  47.             return null;   
  48.         }   
  49.     }   
  50.   
  51.   
  52.     public Scriptable getScope()   
  53.     {   
  54.         return scope;   
  55.     }   
  56.   
  57.     public static void main(String[] args)   
  58.     {   
  59.         String filename = System.getProperty(“user.dir”) + “/jsmap.js”;   
  60.         JSExploration jsExploration = new JSExploration();   
  61.         Object result = jsExploration.runJavaScript(filename);   
  62.         Scriptable scope = jsExploration.getScope();   
  63.         Scriptable obj = (Scriptable) scope.get(“obj”, scope);   
  64.         System.out.println(“obj.a == ” + obj.get(“a”, obj));   
  65.         Scriptable b = (Scriptable) obj.get(“b”, obj);   
  66.         System.out.println(“b[0] == ” + b.get(0, b));   
  67.         Boolean flag = (Boolean) scope.get(“flag”, scope);   
  68.         System.out.println(flag);   
  69.   
  70.         Scriptable myobj = (Scriptable) scope.get(“obj”, scope);   
  71.         Boolean myflag = (Boolean) scope.get(“flag”, scope);   
  72.         System.out.println(myflag);   
  73.   
  74.         Scriptable jsFunction = (Scriptable) scope.get(“jsFunction”, scope);   
  75.         Function fc = (Function) jsFunction.get(“handler”, jsFunction);   
  76.         Object isPrime = fc.call(Context.getCurrentContext(), jsFunction, fc, new Object[] { “this is my test” });   
  77.     }   
  78. }   
  79.   

js脚本:jsmap.js

js 代码

  1. var swingNames = JavaImporter();   
  2.   
  3. swingNames.importPackage(Packages.java.lang);   
  4. swingNames.importPackage(Packages.co.test);   
  5.   
  6. obj = {a:1, b:[’x',’y']}   
  7. next = isPrime   
  8. flag = isPrime(5)   
  9. with (swingNames) {   
  10.  System.out.println(“in javascript”);   
  11.  JSFunction.print(“in JSFunction”);   
  12.   jsFunction = new JSFunction(“lichunlei”);   
  13.  var name = jsFunction.getName();   
  14.  System.out.println(“get name from java source: ” + name);   
  15.  jsFunction.setHandler(log);    
  16. }    
  17.   
  18. java.lang.System.out.println(“not use swingNames”);   
  19. function isPrime (num)   
  20. {   
  21.  java.lang.System.out.println(“in isPrime(num)”);   
  22.     if (num <= 1) {   
  23.         java.lang.System.out.println(“Please enter a positive integer >= 2.”)   
  24.         return false  
  25.     }   
  26.        
  27.     var prime = true  
  28.     var sqrRoot = Math.round(Math.sqrt(num))   
  29.        
  30.     for (var n = 2; prime & n <= sqrRoot; ++n) {   
  31.         prime = (num % n != 0)   
  32.     }   
  33.        
  34.     return prime   
  35. }   
  36.   
  37. function log(msg)   
  38. {   
  39.  java.lang.System.out.println(“in function log: ” + msg);   
  40. }   
  41.   
  42.     

Posted by micas on Jul 8th 2007 | Filed in J2EE, JavaBasic, Enabling-tech | Comments (0)

SortUtil:

package org.rut.util.algorithm;

import org.rut.util.algorithm.support.BubbleSort;
import org.rut.util.algorithm.support.HeapSort;
import org.rut.util.algorithm.support.ImprovedMergeSort;
import org.rut.util.algorithm.support.ImprovedQuickSort;
import org.rut.util.algorithm.support.InsertSort;
import org.rut.util.algorithm.support.MergeSort;
import org.rut.util.algorithm.support.QuickSort;
import org.rut.util.algorithm.support.SelectionSort;
import org.rut.util.algorithm.support.ShellSort;

/**
 * @author treeroot
 * @since 2006-2-2
 * @version 1.0
 */
public class SortUtil {
    public final static int INSERT = 1;
    public final static int BUBBLE = 2;
    public final static int SELECTION = 3;
    public final static int SHELL = 4;
    public final static int QUICK = 5;
    public final static int IMPROVED_QUICK = 6;
    public final static int MERGE = 7;
    public final static int IMPROVED_MERGE = 8;
    public final static int HEAP = 9;

    public static void sort(int[] data) {
        sort(data, IMPROVED_QUICK);
    }
    private static String[] name={
            “insert”, “bubble”, “selection”, “shell”, “quick”, “improved_quick”, “merge”, “improved_merge”, “heap”
    };
    
    private static Sort[] impl=new Sort[]{
            new InsertSort(),
            new BubbleSort(),
            new SelectionSort(),
            new ShellSort(),
            new QuickSort(),
            new ImprovedQuickSort(),
            new MergeSort(),
            new ImprovedMergeSort(),
            new HeapSort()
    };

    public static String toString(int algorithm){
        return name[algorithm-1];
    }
    
    public static void sort(int[] data, int algorithm) {
        impl[algorithm-1].sort(data);
    }

    public static interface Sort {
        public void sort(int[] data);
    }

    public static void swap(int[] data, int i, int j) {
        int temp = data[i];
        data[i] = data[j];
        data[j] = temp;
    }
}

Posted by micas on Jun 28th 2007 | Filed in JavaBasic | Comments (0)

堆排序:

package org.rut.util.algorithm.support;

import org.rut.util.algorithm.SortUtil;

/**
 * @author treeroot
 * @since 2006-2-2
 * @version 1.0
 */
public class HeapSort implements SortUtil.Sort{

    /* (non-Javadoc)
     * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
     */
    public void sort(int[] data) {
        MaxHeap h=new MaxHeap();
        h.init(data);
        for(int i=0;i<data.length;i++)
            h.remove();
        System.arraycopy(h.queue,1,data,0,data.length);
    }

     private static class MaxHeap{        
       
        void init(int[] data){
            this.queue=new int[data.length+1];
            for(int i=0;i<data.length;i++){
                queue[++size]=data[i];
                fixUp(size);
            }
        }
        
        private int size=0;

        private int[] queue;
               
        public int get() {
            return queue[1];
        }

        public void remove() {
            SortUtil.swap(queue,1,size–);
            fixDown(1);
        }
        //fixdown
        private void fixDown(int k) {
            int j;
            while ((j = k << 1) <= size) {
                if (j < size && queue[j]<queue[j+1])
                    j++;
                if (queue[k]>queue[j]) //不用交换
                    break;
                SortUtil.swap(queue,j,k);
                k = j;
            }
        }
        private void fixUp(int k) {
            while (k > 1) {
                int j = k >> 1;
                if (queue[j]>queue[k])
                    break;
                SortUtil.swap(queue,j,k);
                k = j;
            }
        }

    }

}

Posted by micas on Jun 28th 2007 | Filed in JavaBasic | Comments (0)

归并排序:

package org.rut.util.algorithm.support;

import org.rut.util.algorithm.SortUtil;

/**
 * @author treeroot
 * @since 2006-2-2
 * @version 1.0
 */
public class MergeSort implements SortUtil.Sort{

    /* (non-Javadoc)
     * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
     */
    public void sort(int[] data) {
        int[] temp=new int[data.length];
        mergeSort(data,temp,0,data.length-1);
    }
   
    private void mergeSort(int[] data,int[] temp,int l,int r){
        int mid=(l+r)/2;
        if(l==r) return ;
        mergeSort(data,temp,l,mid);
        mergeSort(data,temp,mid+1,r);
        for(int i=l;i<=r;i++){
            temp[i]=data[i];
        }
        int i1=l;
        int i2=mid+1;
        for(int cur=l;cur<=r;cur++){
            if(i1==mid+1)
                data[cur]=temp[i2++];
            else if(i2>r)
                data[cur]=temp[i1++];
            else if(temp[i1]<temp[i2])
                data[cur]=temp[i1++];
            else
                data[cur]=temp[i2++];           
        }
    }

}
改进后的归并排序:

package org.rut.util.algorithm.support;

import org.rut.util.algorithm.SortUtil;

/**
 * @author treeroot
 * @since 2006-2-2
 * @version 1.0
 */
public class ImprovedMergeSort implements SortUtil.Sort {

    private static final int THRESHOLD = 10;

    /*
     * (non-Javadoc)
     *
     * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
     */
    public void sort(int[] data) {
        int[] temp=new int[data.length];
        mergeSort(data,temp,0,data.length-1);
    }

    private void mergeSort(int[] data, int[] temp, int l, int r) {
        int i, j, k;
        int mid = (l + r) / 2;
        if (l == r)
            return;
        if ((mid - l) >= THRESHOLD)
            mergeSort(data, temp, l, mid);
        else
            insertSort(data, l, mid - l + 1);
        if ((r - mid) > THRESHOLD)
            mergeSort(data, temp, mid + 1, r);
        else
            insertSort(data, mid + 1, r - mid);

        for (i = l; i <= mid; i++) {
            temp[i] = data[i];
        }
        for (j = 1; j <= r - mid; j++) {
            temp[r - j + 1] = data[j + mid];
        }
        int a = temp[l];
        int b = temp[r];
        for (i = l, j = r, k = l; k <= r; k++) {
            if (a < b) {
                data[k] = temp[i++];
                a = temp[i];
            } else {
                data[k] = temp[j–];
                b = temp[j];
            }
        }
    }

    /**
     * @param data
     * @param l
     * @param i
     */
    private void insertSort(int[] data, int start, int len) {
        for(int i=start+1;i<start+len;i++){
            for(int j=i;(j>start) && data[j]<data[j-1];j–){
                SortUtil.swap(data,j,j-1);
            }
        }
    }
}

Posted by micas on Jun 28th 2007 | Filed in JavaBasic | Comments (0)

快速排序:

package org.rut.util.algorithm.support;

import org.rut.util.algorithm.SortUtil;

/**
 * @author treeroot
 * @since 2006-2-2
 * @version 1.0
 */
public class QuickSort implements SortUtil.Sort{

    /* (non-Javadoc)
     * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
     */
    public void sort(int[] data) {
        quickSort(data,0,data.length-1);       
    }
    private void quickSort(int[] data,int i,int j){
        int pivotIndex=(i+j)/2;
        //swap
        SortUtil.swap(data,pivotIndex,j);
       
        int k=partition(data,i-1,j,data[j]);
        SortUtil.swap(data,k,j);
        if((k-i)>1) quickSort(data,i,k-1);
        if((j-k)>1) quickSort(data,k+1,j);
       
    }
    /**
     * @param data
     * @param i
     * @param j
     * @return
     */
    private int partition(int[] data, int l, int r,int pivot) {
        do{
           while(data[++l]<pivot);
           while((r!=0)&&data[–r]>pivot);
           SortUtil.swap(data,l,r);
        }
        while(l<r);
        SortUtil.swap(data,l,r);       
        return l;
    }

}
改进后的快速排序:

package org.rut.util.algorithm.support;

import org.rut.util.algorithm.SortUtil;

/**
 * @author treeroot
 * @since 2006-2-2
 * @version 1.0
 */
public class ImprovedQuickSort implements SortUtil.Sort {

    private static int MAX_STACK_SIZE=4096;
    private static int THRESHOLD=10;
    /* (non-Javadoc)
     * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
     */
    public void sort(int[] data) {
        int[] stack=new int[MAX_STACK_SIZE];
       
        int top=-1;
        int pivot;
        int pivotIndex,l,r;
       
        stack[++top]=0;
        stack[++top]=data.length-1;
       
        while(top>0){
            int j=stack[top–];
            int i=stack[top–];
           
            pivotIndex=(i+j)/2;
            pivot=data[pivotIndex];
           
            SortUtil.swap(data,pivotIndex,j);
           
            //partition
            l=i-1;
            r=j;
            do{
                while(data[++l]<pivot);
                while((r!=0)&&(data[–r]>pivot));
                SortUtil.swap(data,l,r);
            }
            while(l<r);
            SortUtil.swap(data,l,r);
            SortUtil.swap(data,l,j);
           
            if((l-i)>THRESHOLD){
                stack[++top]=i;
                stack[++top]=l-1;
            }
            if((j-l)>THRESHOLD){
                stack[++top]=l+1;
                stack[++top]=j;
            }
           
        }
        //new InsertSort().sort(data);
        insertSort(data);
    }
    /**
     * @param data
     */
    private void insertSort(int[] data) {
        int temp;
        for(int i=1;i<data.length;i++){
            for(int j=i;(j>0)&&(data[j]<data[j-1]);j–){
                SortUtil.swap(data,j,j-1);
            }
        }      
    }

}

Posted by micas on Jun 28th 2007 | Filed in JavaBasic | Comments (0)

对 Object 类中方法的一些简单认识

说到toString()方法,就不得不先看看Object类.
Object 类是一个超级类,是一切类的父类;看看sun的JDK就知道,其实他的方法并不多,但都非常实用.
我始终对Object有一丝神秘感,昨天朋友问起Clone()仍有很多困惑;
所以今天决定,来揭开Object的面纱.下面就是我通过翻阅资料和阅读JDK后,对Object的一些理解,如有错误请指出:
package java.lang;
public class Object { }
在JDK1.4中它有11个方法,主要的方法有 clone(), equals(), getClass(), notfiy(), toString(), wait() …….
我在这里只重点说说clone(), equals(),  toString()
1.clone()
所有具有clone功能的类都有一个特性,那就是它直接或间接地实现了Cloneable接口。否则,我们在尝试调用clone()方法时,将会触发CloneNotSupportedException异常。
protected native Object clone() throws CloneNotSupportedException;(在JDK中)
可以看出它是一个protected方法,所以我们不能简单地调用它,
native : 关键字native,表明这个方法使用java以外的语言实现。所修辞的方法不包括实现.   (参考:http://blog.csdn.net/mingjava/archive/2004/11/14/180946.aspx)
在这里我就不具体讲clone() 是如何实现Cloneable接口,如何覆盖; 这说说clone的作用和用法;
对于 object  x,
x.clone() != x
x.clone().getClass() == x.getClass()
x.clone().equals(x)
x.clone().getClass() == x.getClass()
以上返回的值都为true
2 equals()
其原型为:
public boolean equals(Object obj) {
      return (this == obj);
 }
Object 中定义的 equals(Object) 是比较的引用,与 “==” 作用相同。
3. toString()其原型为:
public String toString() {
   return getClass().getName() + “@” + Integer.toHexString(hashCode());
}
toString() 方法是最为常见的,在很多类中都对他进行覆盖:
先看两个例子
例一:    
class Example{
    private String s = “abc”;
    public Example(String str) {
    this.s = str + this.s ;
 }
 public static void main(String[] args){
     Example ex = new Example(”123″);
     System.out.println(ex);
     System.out.println(ex.s);
 }
 public String toString() {
     this.s = “cba” +this.s;
     return s;
}
输出结果:
cba123abc
cba123abc
例二.
class Example{
    private String s = “abc”;
    public Example(String str) {
    this.s = str + this.s ;
 }
 public static void main(String[] args){
     Example ex = new Example(”123″);
     System.out.println(ex);
     System.out.println(ex.s);
 }
 public String toString2() {
     this.s = “cba” + this.s;
     return s;
}
输出结果:
Example@1858610
123abc
例一:和例二;只修改了tostring的方法名,但执行却有很大的不同 ;
例一中: tostring()被覆盖,在执行new Example(”123″);的时候,先调用构造方法(暂不执行)再加载执行父类中的方法tostring()(这里被覆盖,则运行本类中的方法代码),最后执行构造方法;这里涉及到执行的顺序,不着讨论;  然后在执行到 System.out.println(ex); 时,实际是打印方法tostring()返回的string值;
在例二中:tostring()并没有被覆盖,toString2() 是类中普通的方法, 所以new Example(”123″);时,不会加载执行toString2() ,所以s值为”123abc”;而System.out.println(ex);打印出来的结果,是原型中看到的 类名 + @ + 十六进制数字表示的该对象的散列码
方法tostring()使用还很多,我们在编写类的时候,都最好能有自己的tostring,把原型覆盖掉; 

Posted by micas on Jun 28th 2007 | Filed in JavaBasic | Comments (0)

java io读取文件到String

 public static String loadAFileToStringDE1(File f) throws IOException { 
        long beginTime = System.currentTimeMillis();
        InputStream is = null;
        String ret = null;
        try {
            is = new BufferedInputStream( new FileInputStream(f) );
            long contentLength = f.length();
            ByteArrayOutputStream outstream = new ByteArrayOutputStream( contentLength > 0 ? (int) contentLength : 1024);
            byte[] buffer = new byte[4096];
            int len;
            while ((len = is.read(buffer)) > 0) {
                outstream.write(buffer, 0, len);
            }           
            outstream.close();
            ret = outstream.toString();
            //byte[] ba = outstream.toByteArray();
            //ret = new String(ba);
        } finally {
            if(is!=null) {try{is.close();} catch(Exception e){} }
        }
        long endTime = System.currentTimeMillis();
        System.out.println(”方法1用时”+ (endTime-beginTime) + “ms”);
        return ret;       
    }
   

    public static String loadAFileToStringDE2(File f) throws IOException { 
        long beginTime = System.currentTimeMillis();
        InputStream is = null;
        String ret = null;
        try {
            is =  new FileInputStream(f) ;
            long contentLength = f.length();
            byte[] ba = new byte[(int)contentLength];
            is.read(ba);
            ret = new String(ba);
        } finally {
            if(is!=null) {try{is.close();} catch(Exception e){} }
        }
        long endTime = System.currentTimeMillis();
        System.out.println(”方法2用时”+ (endTime-beginTime) + “ms”);
        return ret;       
    }   
   

    public static String loadAFileToStringDE3(File f) throws IOException {
        long beginTime = System.currentTimeMillis();
        BufferedReader br = null;
        String ret = null;
        try {
            br =  new BufferedReader(new FileReader(f));
            String line = null;
            StringBuffer sb = new StringBuffer((int)f.length());
            while( (line = br.readLine() ) != null ) {
                sb.append(line).append(LINE_BREAK);
            }
            ret = sb.toString();
        } finally {
            if(br!=null) {try{br.close();} catch(Exception e){} }
        }
        long endTime = System.currentTimeMillis();
        System.out.println(”方法3用时”+ (endTime-beginTime) + “ms”);
        return ret;       
    }

3个方法去读取一个大于50M的文件,当不设置jvm参数时都OutofMemery,当设置-Xmx128M时。只有方法3 可以通过,设置到-Xmx256M时也只有方法3可以通过,干脆设置512M,都可以了,运行时间如果正常的话一般都在4~5S
 

Posted by micas on Jun 28th 2007 | Filed in JavaBasic | Comments (0)

使用JNI的步骤

1. 写Java类,其中定义了native方法

public class WitWrapper {

    static {
        System.loadLibrary(
witengine);
    }

    /**
     * 
@param args
     
*/
    
public static void main(String[] args) {
        
new WitWrapper().run();
    }

    private void run() {
        solve(
C:\\temp\\witlib\\problem.txt);
    }

    public native static int solve(String filename);
}

2. 在命令行下用javah生成.h文件,内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
<jni.h>
/* Header for class XXX_WitWrapper */

#ifndef _Included_XXX_witwrapper_WitWrapper
#define _Included_XXX_witwrapper_WitWrapper
#ifdef __cplusplus
extern C {
#endif
/*
 * Class:     XXX_WitWrapper
 * Method:    solve
 * Signature: (Ljava/lang/String;)I
 
*/
JNIEXPORT jint JNICALL Java_XXX_WitWrapper_solve
  (JNIEnv 
*, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

3. 复制.h文件到一个vc++6.0的dll工程里,用vs2005得到的dll会依赖msvcr80d.dll等其他dll,不建议。把$jdk_dir$/include里的jni.h和$jdk_dir$/include/win32里的jni_md.h也添加到这个工程里。

4. 按.h文件实现.c文件对应的方法,如下例,注意jstring类型要转换成char *类型,否则即使英文也会有乱码:

/**************************************************************************** 
 *
 * Sample WIT API Program.
 * Runs implosion on the Diner problem.
 *
 ***************************************************************************
*/
#include 
<stdlib.h>
#include 
wit.h
#include 
jni.h

/****************************************************************************/
/* Main Program                                                             */
/****************************************************************************/
JNIEXPORT jint JNICALL Java_XXX_WitWrapper_solve
  (JNIEnv 
* env, jclass jc, jstring file)
{
  WitRun 
* theWitRun;
  
const char *str = (*env)->GetStringUTFChars(env, file, 0);//把jstring转换为char *,否则会有错
  printf(str);

   /* Initialize WIT */
   witNewRun( 
&theWitRun );
   witInitialize ( theWitRun );

   witReadData (theWitRun, str);
   /*************************************************************************
    *
    * Finished entering data
    *
    ***********************************************************************
*/

   witOptImplode( theWitRun );
   witWriteExecSched( theWitRun, execsched.txt, WitBSV );
   witWriteShipSched( theWitRun, 
shipsched.txt, WitBSV );

   witDeleteRun( theWitRun );

   exit (0);

/* main */
5. 编译生成.dll文件,把它和其他依赖的文件放在path环境变量包含的一个目录下,在java里就可以调用了。注意调用这个dll的java类名(包括所在包)不能改,否则会出现UnsatisfiedLinkException,如果一定要改名,只能重新生成一遍dll了。

Posted by micas on Jun 27th 2007 | Filed in JavaBasic | Comments (0)

Next »