﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-花-文章分类-Java</title><link>http://www.blogjava.net/hua/category/10660.html</link><description>即使世界明天毁灭，我也要在今天种下我的葡萄树。 </description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 06:41:17 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 06:41:17 GMT</pubDate><ttl>60</ttl><item><title>Java 中文问题的根源分析及解决 </title><link>http://www.blogjava.net/hua/articles/56558.html</link><dc:creator>花</dc:creator><author>花</author><pubDate>Tue, 04 Jul 2006 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/hua/articles/56558.html</guid><wfw:comment>http://www.blogjava.net/hua/comments/56558.html</wfw:comment><comments>http://www.blogjava.net/hua/articles/56558.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hua/comments/commentRss/56558.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hua/services/trackbacks/56558.html</trackback:ping><description><![CDATA[
		<span class="javascript" id="text55406" style="FONT-SIZE: 12px">
				<font face="Courier New" color="#000000" size="3">在基于 Java 语言的编程中，我们经常碰到汉字的处理及显示的问题。一大堆看不懂的乱码肯定不是我们愿意看到的显示效果，怎样才能够让那些汉字正确显示呢？Java 语言默认的编码方式是UNICODE ，而我们中国人通常使用的文件和数据库都是基于 GB2312 或者 BIG5 等方式编码的，怎样才能够恰当地选择汉字编码方式并正确地处理汉字的编码呢？本文将从汉字编码的常识入手，结合 Java 编程实例，分析以上两个问题并提出解决它们的方案。 <br /><br />现在 Java 编程语言已经广泛应用于互联网世界，早在 Sun 公司开发 Java 语言的时候，就已经考虑到对非英文字符的支持了。Sun 公司公布的 Java 运行环境（JRE）本身就分英文版和国际版，但只有国际版才支持非英文字符。不过在 Java 编程语言的应用中，对中文字符的支持并非如同 Java Soft 的标准规范中所宣称的那样完美，因为中文字符集不只一个，而且不同的操作系统对中文字符的支持也不尽相同，所以会有许多和汉字编码处理有关的问题在我们进行应用开发中困扰着我们。有很多关于这些问题的解答，但都比较琐碎，并不能够满足大家迫切解决问题的愿望，关于 Java 中文问题的系统研究并不多，本文从汉字编码常识出发，分析 Java 中文问题，希望对大家解决这个问题有所帮助。 <br /><br />汉字编码的常识 <br /><br />我们知道，英文字符一般是以一个字节来表示的，最常用的编码方法是 ASCII 。但一个字节最多只能区分256个字符，而汉字成千上万，所以现在都以双字节来表示汉字，为了能够与英文字符分开，每个字节的最高位一定为1，这样双字节最多可以表示64K格字符。我们经常碰到的编码方式有 GB2312、BIG5、UNICODE 等。关于具体编码方式的详细资料，有兴趣的读者可以查阅相关资料。我肤浅谈一下和我们关系密切的 GB2312 和 UNICODE。GB2312 码，中华人民共和国国家标准汉字信息交换用编码，是一个由中华人民共和国国家标准总局发布的关于简化汉字的编码，通行于中国大陆地区及新加坡，简称国标码。两个字节中，第一个字节（高字节）的值为区号值加32（20H），第二个字节（低字节）的值为位号值加32（20H），用这两个值来表示一个汉字的编码。UNICODE 码是微软提出的解决多国字符问题的多字节等长编码，它对英文字符采取前面加“0”字节的策略实现等长兼容。如 “A” 的 ASCII 码为0x41，UNICODE 就为0x00，0x41。利用特殊的工具各种编码之间可以互相转换。 <br /><br />Java 中文问题的初步认识 <br /><br />我们基于 Java 编程语言进行应用开发时，不可避免地要处理中文。Java 编程语言默认的编码方式是 UNICODE，而我们通常使用的数据库及文件都是基于 GB2312 编码的，我们经常碰到这样的情况：浏览基于 JSP 技术的网站看到的是乱码，文件打开后看到的也是乱码，被 Java 修改过的数据库的内容在别的场合应用时无法继续正确地提供信息。 <br /><br />String sEnglish = “apple”; <br /><br />String sChinese = “苹果”; <br /><br />String s = “苹果 apple ”; <br /><br />sEnglish 的长度是5，sChinese的长度是4，而 s 默认的长度是14。对于 sEnglish来说， Java 中的各个类都支持得非常好，肯定能够正确显示。但对于 sChinese 和 s 来说，虽然 Java Soft 声明 Java 的基本类已经考虑到对多国字符的支持（默认 UNICODE 编码），但是如果操作系统的默认编码不是 UNICODE ，而是国标码等。从 Java 源代码到得到正确的结果，要经过 “Java 源代码-&gt; Java 字节码-&gt; ;虚拟机-&gt;操作系统-&gt;显示设备”的过程。在上述过程中的每一步骤，我们都必须正确地处理汉字的编码，才能够使最终的显示结果正确。 <br /><br />“ Java 源代码-&gt; Java 字节码”，标准的 Java 编译器 javac 使用的字符集是系统默认的字符集，比如在中文 Windows 操作系统上就是 GBK ,而在 Linux 操作系统上就是ISO-8859-1，所以大家会发现在 Linux 操作系统上编译的类中源文件中的中文字符都出了问题，解决的办法就是在编译的时候添加 encoding 参数，这样才能够与平台无关。用法是 <br /><br />javac –encoding GBK。 <br /><br />“ Java 字节码-&gt;虚拟机-&gt;操作系统”， Java 运行环境 （JRE） 分英文版和国际版，但只有国际版才支持非英文字符。 Java 开发工具包 （JDK） 肯定支持多国字符，但并非所有的计算机用户都安装了 JDK 。很多操作系统及应用软件为了能够更好的支持 Java ，都内嵌了 JRE 的国际版本，为自己支持多国字符提供了方便。 <br /><br />“操作系统-&gt;显示设备”，对于汉字来说，操作系统必须支持并能够显示它。英文操作系统如果不搭配特殊的应用软件的话，是肯定不能够显示中文的。 <br /><br />还有一个问题，就是在 Java 编程过程中，对中文字符进行正确的编码转换。例如，向网页输出中文字符串的时候，不论你是用 <br /><br />out.println(string); // string 是含中文的字符串 <br /><br />还是用 <br /><br />，都必须作 UNICODE 到 GBK 的转换，或者手动，或者自动。在 JSP 1.0中，可以定义输出字符集，从而实现内码的自动转换。用法是 <br /><br /><br />但是在一些 JSP 版本中并没有提供对输出字符集的支持，（例如 JSP 0.92），这就需要手动编码输出了，方法非常多。最常用的方法是 <br /><br />String s1 = request.getParameter(“keyword”); <br /><br />String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”); <br /><br />getBytes 方法用于将中文字符以“ISO-8859-1”编码方式转化成字节数组，而“GBK” 是目标编码方式。我们从以ISO-8859-1方式编码的数据库中读出中文字符串 s1 ，经过上述转换过程，在支持 GBK 字符集的操作系统和应用软件中就能够正确显示中文字符串 s2 。 <br /><br />Java 中文问题的表层分析及处理 <br /><br />背景 <br /><br />开发环境 <br />JDK1.15 <br />Vcafe2.0 <br />JPadPro <br /><br />服务器端 <br />NT IIS <br />Sybase System <br />Jconnect（JDBC） <br /><br />客户端 <br />IE5.0 <br />Pwin98 <br /><br /><br />.CLASS 文件存放在服务器端，由客户端的浏览器运行 APPLET ， APPLET 只起调入 FRAME 类等主程序的作用。界面包括 Textfield ，TextArea，List，Choice 等。 <br /><br />I. 取中文 <br /><br />用 JDBC 执行 SELECT 语句从服务器端读取数据（中文）后，将数据用 APPEND 方法加到 TextArea（TA） ，不能正确显示。但加到 List 中时，大部分汉字却可正确显示。 <br /><br />将数据按“ISO-8859-1” 编码方式转化为字节数组，再按系统缺省编码方式 （Default Character Encoding） 转化为 STRING ，即可在 TA 和 List 中正确显示。 <br /><br />程序段如下： <br /><br />dbstr2 = results.getString(1); <br /><br />//After reading the result from DB server，converting it to string. <br /><br />dbbyte1 = dbstr2.getBytes(“iso-8859-1”); <br /><br />dbstr1 = new String(dbbyte1); <br /><br />在转换字符串时不采用系统默认编码方式，而直接采用“ GBK” 或者 “GB2312” ,在 A 和 B 两种情况下，从数据库取数据都没有问题。 <br /><br />II. 写中文到数据库 <br /><br />处理方式与“取中文”相逆，先将 SQL 语句按系统缺省编码方式转化为字节数组，再按“ISO-8859-1”编码方式转化为 STRING ，最后送去执行，则中文信息可正确写入数据库。 <br /><br />程序段如下： <br /><br />sqlstmt = tf_input.getText(); <br /><br />//Before sending statement to DB server，converting it to sql statement. <br /><br />dbbyte1 = sqlstmt.getBytes(); <br /><br />sqlstmt = newString(dbbyte1,”iso-8859-1”); <br /><br />_stmt = _con.createStatement(); <br /><br />_stmt.executeUpdate(sqlstmt); <br /><br />…… <br /><br />问题：如果客户机上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 时（称为 A 情况），上述程序代码可正确执行。但是如果客户机只有浏览器，而没有 JDK 和 CLASSPATH 时（称为 B 情况），则汉字无法正确转换。 <br /><br />我们的分析： <br /><br />1.经过测试，在 A 情况下，程序运行时系统的缺省编码方式为 GBK 或者 GB2312 。在 B 情况下，程序启动时浏览器的 JAVA 控制台中出现如下错误信息： <br /><br />Can't find resource for sun.awt.windows.awtLocalization_zh_CN <br /><br />然后系统的缺省编码方式为“8859-1”。 <br /><br />2.如果在转换字符串时不采用系统缺省编码方式，而是直接采用 “GBK” 或“GB2312”，则在 A 情况下程序仍然可正常运行，在 B 情况下，系统出现错误： <br /><br />UnsupportedEncodingException。 <br /><br />3.在客户机上，把 JDK 的 CLASSES.ZIP 解压后，放在另一个目录中， CLASSPATH 只包含该目录。然后一边逐步删除该目录中的 .CLASS 文件，另一边运行测试程序，最后发现在一千多个 CLASS 文件中，只有一个是必不可少的，该文件是： <br /><br />sun.io.CharToByteDoubleByte.class。 <br /><br />将该文件拷到服务器端和其它的类放在一起，并在程序的开头 IMPORT 它，在 B 情况下程序仍然无法正常运行。 <br /><br />4.在 A 情况下，如果在 CLASSPTH 中去掉 sun.io.CharToByteDoubleByte.class ，则程序运行时测得默认编码方式为“8859-1”，否则为 “GBK” 或 “GB2312” 。 <br /><br />如果 JDK 的版本为1.2以上的话，在 B 情况下遇到的问题得到了很好的解决，测试的步骤同上，有兴趣的读者可以尝试一下。<br />在简体中文 MS Windows 98 + JDK 1.3 下，可以用 System.getProperties() 得到 Java 运行环境的一些基本属性，类 PoorChinese 可以帮助我们得到这些属性。 <br /><br />类 PoorChinese 的源代码： <br /><br />public class PoorChinese { <br /><br />public static void main(String[] args) { <br /><br />System.getProperties().list(System.out); <br /><br />} <br /><br />} <br /><br />执行 java PoorChinese 后，我们会得到: <br /><br />系统变量 file.encoding 的值为 GBK ，user.language 的值为 zh ， user.region 的值为 CN ，这些系统变量的值决定了系统默认的编码方式是 GBK 。 <br /><br />在上述系统中，下面的代码将 GB2312 文件转换成 Big5 文件，它们能够帮助我们理解 Java 中汉字编码的转化: <br /><br /><br />import java.io.*; <br /><br />import java.util.*; <br /><br /><br />public class gb2big5 { <br /><br /><br />static int iCharNum=0; <br /><br /><br />public static void main(String[] args) { <br /><br />System.out.println("Input GB2312 file, output Big5 file."); <br /><br />if (args.length!=2) { <br /><br />System.err.println("Usage: jview gb2big5 gbfile big5file"); <br /><br />System.exit(1); <br /><br />} <br /><br />String inputString = readInput(args[0]); <br /><br />writeOutput(inputString,args[1]); <br /><br />System.out.println("Number of Characters in file: "+iCharNum+"."); <br /><br />} <br /><br /><br />static void writeOutput(String str, String strOutFile) { <br /><br />try { <br /><br />FileOutputStream fos = new FileOutputStream(strOutFile); <br /><br />Writer out = new OutputStreamWriter(fos, "Big5"); <br /><br />out.write(str); <br /><br />out.close(); <br /><br />} <br /><br />catch (IOException e) { <br /><br />e.printStackTrace(); <br /><br />e.printStackTrace(); <br /><br />} <br /><br />} <br /><br /><br />static String readInput(String strInFile) { <br /><br />StringBuffer buffer = new StringBuffer(); <br /><br />try { <br /><br />FileInputStream fis = new FileInputStream(strInFile); <br /><br />InputStreamReader isr = new InputStreamReader(fis, "GB2312"); <br /><br />Reader in = new BufferedReader(isr); <br /><br />int ch; <br /><br />while ((ch = in.read()) &gt; -1) { <br /><br />iCharNum += 1; <br /><br />buffer.append((char)ch); <br /><br />} <br /><br />in.close(); <br /><br />return buffer.toString(); <br /><br />} <br /><br />catch (IOException e) { <br /><br />e.printStackTrace(); <br /><br />return null; <br /><br />} <br /><br />} <br /><br />} <br /><br /><br />编码转化的过程如下： <br /><br />ByteToCharGB2312 CharToByteBig5 <br /><br />GB2312------------------&gt;Unicode-------------&gt;Big5 <br /><br />执行 java gb2big5 gb.txt big5.txt ，如果 gb.txt 的内容是“今天星期三”，则得到的文件 big5.txt 中的字符能够正确显示；而如果 gb.txt 的内容是“情人节快乐”，则得到的文件 big5.txt 中对应于“节”和“乐”的字符都是符号“？”（0x3F），可见 sun.io.ByteToCharGB2312 和 sun.io.CharToByteBig5 这两个基本类并没有编好。 <br /><br />正如上例一样， Java 的基本类也可能存在问题。由于国际化的工作并不是在国内完成的，所以在这些基本类发布之前，没有经过严格的测试，所以对中文字符的支持并不像 Java Soft 所声称的那样完美。前不久，我的一位技术上的朋友发信给我说，他终于找到了 Java Servlet 中文问题的根源。两周以来，他一直为 Java Servlet 的中文问题所困扰，因为每面对一个含有中文字符的字符串都必须进行强制转换才能够得到正确的结果（这好象是大家公认的唯一的解决办法）。后来，他确实不想如此继续安分下去了，因为这样的事情确实不应该是高级程序员所要做的工作，他就找出 Servlet 解码的源代码进行分析，因为他怀疑问题就出在解码这部分。经过四个小时的奋斗，他终于找到了问题的根源所在。原来他的怀疑是正确的， Servlet 的解码部分完全没有考虑双字节，直接把 %XX 当作一个字符。（原来 Java Soft 也会犯这幺低级的错误！） <br /><br />如果你对这个问题有兴趣或者遇到了同样的烦恼的话，你可以按照他的步骤对 Servlet.jar 进行修改： <br /><br />找到源代码 HttpUtils 中的 static private String parseName ，在返回前将 sb（StringBuffer） 复制成 byte bs[] ，然后 return new String(bs,”GB2312”)。作上述修改后就需要自己解码了： <br /><br />HashTable form=HttpUtils .parseQueryString(request.getQueryString())或者 <br /><br />form=HttpUtils.parsePostData(……) <br /><br />千万别忘了编译后放到 Servlet.jar 里面。 <br /><br />五、 关于 Java 中文问题的总结 <br /><br />Java 编程语言成长于网络世界，这就要求 Java 对多国字符有很好的支持。 Java 编程语言适应了计算的网络化的需求，为它能够在网络世界迅速成长奠定了坚实的基础。 Java 的缔造者 （Java Soft） 已经考虑到 Java 编程语言对多国字符的支持，只是现在的解决方案有很多缺陷在里面，需要我们付诸一些补偿性的措施。而世界标准化组织也在努力把人类所有的文字统一在一种编码之中，其中一种方案是 ISO10646 ，它用四个字节来表示一个字符。当然，在这种方案未被采用之前，还是希望 Java Soft 能够严格地测试它的产品，为用户带来更多的方便。 <br /><br />附一个用于从数据库和网络中取出中文乱码的处理函数，入参是有问题的字符串，出参是问题已经解决了的字符串。 <br /><br />String parseChinese(String in) <br /><br />{ <br /><br />String s = null; <br /><br />byte temp []; <br /><br />if (in == null) <br /><br />{ <br /><br />System.out.println("Warn:Chinese null founded!"); <br /><br />return new String(""); <br /><br />} <br /><br />try <br /><br />{ <br /><br />temp=in.getBytes("iso-8859-1"); <br /><br />temp=in.getBytes("iso-8859-1"); <br /><br />s = new String(temp); <br /><br />} <br /><br />{ <br /><br />System.out.println("Warn:Chinese null founded!"); <br /><br />return new String(""); <br /><br />} <br /><br />try <br /><br />{ <br /><br />temp=in.getBytes("iso-8859-1"); <br /><br />s = new String(temp); <br /><br />} <br /><br />catch(UnsupportedEncodingException e) <br /><br />{ <br /><br />System.out.println (e.toString()); <br /><br />} <br /><br />return s; <br /><br />}</font>
		</span>
<img src ="http://www.blogjava.net/hua/aggbug/56558.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hua/" target="_blank">花</a> 2006-07-04 16:46 <a href="http://www.blogjava.net/hua/articles/56558.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA 在图像处理中的应用</title><link>http://www.blogjava.net/hua/articles/56464.html</link><dc:creator>花</dc:creator><author>花</author><pubDate>Tue, 04 Jul 2006 01:41:00 GMT</pubDate><guid>http://www.blogjava.net/hua/articles/56464.html</guid><wfw:comment>http://www.blogjava.net/hua/comments/56464.html</wfw:comment><comments>http://www.blogjava.net/hua/articles/56464.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hua/comments/commentRss/56464.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hua/services/trackbacks/56464.html</trackback:ping><description><![CDATA[
		<font face="Courier New">相信大家平时碰到过一些在JAVA中对图像进行处理的需求，比如需要对上传的图片加上自己的签名或图标，或者生成和解析动态的GIF图片，以及处理PSD文件图像信息。本文就JAVA在图像处理中一些基本应用进行了介绍。希望通过能够对大家在以后的图像处理中有些帮助。<br />一、对一个现有的图片进行文字和图标的合成<br />                      <br />我们先从下面的这段简单的代码开始<br />import java.awt.*; <br />import javax.imageio.ImageIO;<br />import com.sun.image.codec.jpeg.*;<br />/** <br />* @author Anders.Hu<br />* 2005-01-12<br />*/<br />public class Test {<br />public static void main(String[] args) {<br /> try {<br />   //读取模板图片内容<br />   BufferedImage image = ImageIO.read(new FileInputStream("c:\\1.jpg"));<br />   Graphics2D g = image.createGraphics();//得到图形上下文<br />   g.setColor(Color.BLACK); //设置画笔颜色<br />   //设置字体<br />   g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 15));//写入签名<br />   g.drawString("很好吃诶，要不要也来一口？",43, image.getHeight() - 10);<br />   g.dispose();<br />   FileOutputStream out = new FileOutputStream("c:\\2.jpg");<br />   JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);<br />   encoder.encode(image);<br />   out.close();<br />   } catch(Exception e) {<br />    e.printStackTrace();<br />   }<br />}<br />} <br /><br />相信大家看到这里已经知道了大致的操作过程，我想我还是在这里把基本的原理简单说明一下便于对后续内容的阐述：首先我们通过javax.imageio.ImageIO的read方法读取图像在BufferedImage中，然后我们可以通过BufferedImage的createGraphics方法取得图像的上下文便于对图像的处理，如加上自己喜爱的文字或图片等，最后调用JPEGCodec的encode方法进行JPEG编码,然后就是保存到文件中了。<br />这就是我运行上面代码的结果<br /><br />需要提出的是JPEGCodec是非标准类，如果程序是运行JDK1.4以上版本的话,可以采取以下代码进行JPEG编码ImageIO.write(image, "JPEG", out);<br />可能在你的实际需求还要加入一些图标的修饰，要做到这一步，我们只需要在上面的代码中利用Graphics2D的drawImage方法做到。下面是加入图标的代码<br />public static void main(String[] args) {<br /> try {<br />    BufferedImage image = ImageIO.read(new FileInputStream("c:\\1.jpg"));<br />    //读取图标<br />    BufferedImage image_biao = ImageIO.read(new FileInputStream("c:\\i.jpg"));<br />    Graphics2D g = image.createGraphics();<br />    g.setColor(Color.YELLOW);<br />    g.setFont(new Font("宋体", Font.LAYOUT_LEFT_TO_RIGHT, 25));<br />    g.drawString("很好吃诶，要不要也来一口？",43, image.getHeight() - 80);<br />    //写入图标<br />    g.drawImage(image_biao, 20,image.getHeight() - 80, image_biao.getWidth(null),<br />      image_biao.getHeight(null), null);<br />    g.dispose();<br />    FileOutputStream out = new FileOutputStream("c:\\3.jpg");<br />    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);<br />    encoder.encode(image);<br />    out.close();<br />   } catch(Exception e) {<br />    e.printStackTrace();<br />   }<br />} <br /><br />代码运行的结果如下<br /><br />二、生成和解析动态的GIF图片<br />有了以上对图象的基本处理之后，我们再来看看对动态GIF图片的处理。<br />GIF是一种由CompuServe创建的压缩和传送图像文件的格式。<br />GIF图像是基于颜色列表的（存储的数据是该点的颜色对应于颜色列表的索引值），最多只支持8位（256色）。GIF文件内部分成许多存储块，用来存储多幅图像（Frame）或者是决定图像表现行为的控制块，用以实现动画和交互式应用。因此我们要生成和分析GIF图像的话，就需要对GIF文件格式进行分析，这里我们采用网上的一个开源代码进行处理。<br />先在http://www.fmsware.com/stuff/gif.zip 下载处理GIF图片的代码，解压之后可以发现有AnimatedGifEncoder.java, GifDecoder.java, LZWEncoder.java,NeuQuant.java这4个JAVA文件，在这些文件的开头都已经有了简单的说明。其中AnimatedGifEncoder.是用来生成GIF文件的类，而GifDecoder则是用来解析GIF动态图像Frame信息的类。LZWEncoder是LZW压缩算法类，NeuQuant是用来生成颜色列表的类。<br />把它们加入到我们的项目文件中，然后我们就来利用AnimatedGifEncoder来写一段合成动态GIF文件的代码。<br />import java.io.FileInputStream;<br />import javax.imageio.ImageIO;<br />import open.AnimatedGifEncoder; <br />/** <br />* @author Anders.Hu<br />* 2005-01-13<br />*/<br />public class TestMakeGIF {<br />public static void main(String[] args) {<br /> try {<br />  //指定Frame的文件<br />  String imgFileName[] = new String[]{"c:\\1.jpg","c:\\2.jpg", "c:\\3.jpg"}; <br />  String outputFileName = "c:\\test.gif";<br />  AnimatedGifEncoder e = new AnimatedGifEncoder();<br />  e.start(outputFileName);//开始处理<br />  e.setDelay(500); //设置延迟时间<br />  for (int i = 0; i &lt; imgFileName.length; i++) {<br />   e.addFrame(ImageIO.read(new FileInputStream(imgFileName[i])));//加入Frame<br />  }<br />  e.finish();<br /> } catch (Exception e) {<br />  e.printStackTrace();<br />}<br />}<br /><br /><br />代码运行的结果如下<br /><br />是不是觉得有了这个AnimatedGifEncoder类，合成GIF文件挺方便的，现在我们再来看看GifDecoder的使用。<br />public class TestGifDecoder {<br />public static void main(String[] args) {<br /> try {<br />  String inputFileName = "c:\\test.gif";<br />  GifDecoder decoder = new GifDecoder();<br />  decoder.read(inputFileName);<br />  int n = decoder.getFrameCount();//得到frame的个数<br />  for (int i = 0; i &lt; n; i++) {<br />   BufferedImage frame = decoder.getFrame(i); //得到frame<br />   int delay = decoder.getDelay(i);//得到延迟时间<br />   //生成JPG文件<br />   String outFilePath = "c:\\test_"+i+".jpg";<br />   FileOutputStream out = new FileOutputStream(outFilePath);<br />   ImageIO.write(frame,"jpeg",out);<br />  }<br /> } catch (Exception e) {<br />  e.printStackTrace();<br /> }<br />}<br />} <br /><br />代码运行完毕之后，就可以生成了相应的4个jpg文件。<br />对于以上的代码有下面几点需要补充：<br />1． 我测试过使用BMP文件的情况，但是没有通过代码的测试，可能是在把BMP图像转为256色图像时出现了错误。所以在使用之前还需要用其他工具把BMP文件转为JPG格式。<br />2． 在合成GIF文件的AnimatedGifEncoder类中有下面几个值得关注的函数<br />2.1：setFrameRate（float）每秒种播放的帧数<br />2.2：setQuality(int quality) 设置在GIF规范中转换为256位图像时的质量参数这个值设置的越小，质量越高，但速度越慢，反之依然，不过超过20以后，速度不会有明显的提升，默认为10。<br />2.3：setSize(int x,int y) 设置GIF图像的大小，默认值为第一个加入的帧的图像的大小。<br />三、对PSD图像文件的分析<br />我们先用PS对模板图片加上一串字符，保存为TestPsd.psd，注意保存时不要合并图层。然后从http://www.fmsware.com/stuff/PSDReader.java 下载一个分析PSD代码的JAVA文件，并加入到我们的项目中。并运行下面的代码<br />import java.awt.Point;<br />import java.awt.image.BufferedImage;<br />import java.io.FileOutputStream;<br />import open.PSDReader;<br />import com.sun.image.codec.jpeg.*;<br />/**<br />* @author Ander.Hu<br />* 2005-10-13<br />*/<br />public class TestPsd {<br /> public static void main(String[] args) {<br />  try {<br />  PSDReader r = new PSDReader();<br />      r.read("c:\\testPsd.psd");<br />       int n = r.getFrameCount();<br />       for (int i = 0; i &lt; n; i++) {<br />          BufferedImage image = r.getLayer(i);<br />          Point offset = r.getLayerOffset(i);<br />          //生成JPG文件<br />    String outFilePath = "c:\\testPsd_"+i+".jpg";<br />    FileOutputStream out = new FileOutputStream(outFilePath);<br />    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);<br />    encoder.encode(image);<br />       }<br /> } catch(Exception e) {<br />  e.printStackTrace();<br /> }<br />}<br />} <br /><br />此时我们便可以发现3个解析后的JPG文件，因为包括背景图层在内有3个图层，故有3个JPG文件。 目前PSDReader 类只支持没有压缩过的或者使用RLE压缩的RGB文件，并且也不支持PS3.0以上的特殊功能。<br />总结<br />在JAVA对图像的处理过程中，通常基本步骤是通过读取图像信息到图像缓冲中－&gt;同时取得图形上下文－&gt;对图像进行相应的处理－&gt;生成图像文件。 </font>
<img src ="http://www.blogjava.net/hua/aggbug/56464.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hua/" target="_blank">花</a> 2006-07-04 09:41 <a href="http://www.blogjava.net/hua/articles/56464.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAR文件包及jar命令详解</title><link>http://www.blogjava.net/hua/articles/45855.html</link><dc:creator>花</dc:creator><author>花</author><pubDate>Fri, 12 May 2006 07:35:00 GMT</pubDate><guid>http://www.blogjava.net/hua/articles/45855.html</guid><wfw:comment>http://www.blogjava.net/hua/comments/45855.html</wfw:comment><comments>http://www.blogjava.net/hua/articles/45855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/hua/comments/commentRss/45855.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/hua/services/trackbacks/45855.html</trackback:ping><description><![CDATA[
		<font face="Courier New">常常在网上看到有人询问：如何把 java 程序编译成 .exe 文件。通常回答只有两种，一种是制作一个可执行的 JAR 文件包，然后就可以像.chm 文档一样双击运行了；而另一种是使用 JET 来进行 编译。但是 JET 是要用钱买的，而且据说 JET 也不是能把所有的 Java 程序都编译成执行文件，性能也要打些折扣。所以，使用制作可执行 JAR 文件包的方法就是最佳选择了，何况它还能保持 Java 的跨平台特性。 <br /><br />　　下面就来看看什么是 JAR 文件包吧： <br /><br />　　1. JAR 文件包 <br /><br />　　JAR 文件就是 Java Archive File，顾名思意，它的应用是与 Java 息息相关的，是 Java 的一种文档格式。JAR 文件非常类似 ZIP 文件——准确的说，它就是 ZIP 文件，所以叫它文件包。JAR 文件与 ZIP 文件唯一的区别就是在 JAR 文件的内容中，包含了一个 META-INF/MANIFEST.MF 文件，这个文件是在生成 JAR 文件的时候自动创建的。举个例子，如果我们具有如下目录结构的一些文件： <br /><br />　　== <br /><br />　　`-- test <br /><br />　　　 `-- Test.class <br /><br />　　把它压缩成 ZIP 文件 test.zip，则这个 ZIP 文件的内部目录结构为： <br /><br />　　test.zip <br /><br />　　`-- test <br /><br />　　　 `-- Test.class <br /><br />　　如果我们使用 JDK 的 jar 命令把它打成 JAR 文件包 test.jar，则这个 JAR 文件的内部目录结构为： <br /><br />　　test.jar <br /><br />　　|-- META-INF <br /><br />　　|　 `-- MANIFEST.MF <br /><br />　　`-- test <br /><br />　　　　`--Test.class <br /><br />　　2. 创建可执行的 JAR 文件包 <br /><br />　　制作一个可执行的 JAR 文件包来发布你的程序是 JAR 文件包最典型的用法。 <br /><br />　　Java 程序是由若干个 .class 文件组成的。这些 .class 文件必须根据它们所属的包不同而分级分目录存放；运行前需要把所有用到的包的根目录指定给 CLASSPATH 环境变量或者 java 命令的 -cp 参数；运行时还要到控制台下去使用 java 命令来运行，如果需要直接双击运行必须写 Windows 的批处理文件 (.bat) 或者 Linux 的 Shell 程序。因此，许多人说，Java 是一种方便开发者苦了用户的程序设计语言。 <br /><br />　　其实不然，如果开发者能够制作一个可执行的 JAR 文件包交给用户，那么用户使用起来就方便了。在 Windows 下安装 JRE (Java Runtime Environment) 的时候，安装文件会将 .jar 文件映射给 javaw.exe 打开。那么，对于一个可执行的 JAR 文件包，用户只需要双击它就可以运行程序了，和阅读 .chm 文档一样方便 (.chm 文档默认是由 hh.exe 打开的)。那么，现在的关键，就是如何来创建这个可执行的 JAR 文件包。 <br /><br />　　创建可执行的 JAR 文件包，需要使用带 cvfm 参数的 jar 命令，同样以上述 test 目录为例，命令如下： <br /><br />jar cvfm test.jar manifest.mf test <br /><br />　　这里 test.jar 和 manifest.mf 两个文件，分别是对应的参数 f 和 m，其重头戏在 manifest.mf。因为要创建可执行的 JAR 文件包，光靠指定一个 manifest.mf 文件是不够的，因为 MANIFEST 是 JAR 文件包的特征，可执行的 JAR 文件包和不可执行的 JAR 文件包都包含 MANIFEST。关键在于可执行 JAR 文件包的 MANIFEST，其内容包含了 Main-Class 一项。这在 MANIFEST 中书写格式如下： <br /><br />　　Main-Class: 可执行主类全名(包含包名) <br /><br />　　例如，假设上例中的 Test.class 是属于 test 包的，而且是可执行的类 (定义了 public static void main(String[]) 方法)，那么这个 manifest.mf 可以编辑如下： <br /><br />Main-Class: test.Test &lt;回车&gt; <br /><br />　　这个 manifest.mf 可以放在任何位置，也可以是其它的文件名，只需要有 Main-Class: test.Test 一行，且该行以一个回车符结束即可。创建了 manifest.mf 文件之后，我们的目录结构变为： <br /><br />　　== <br /><br />　　|-- test <br /><br />　　|　 `-- Test.class <br /><br />　　`-- manifest.mf <br /><br />　　这时候，需要到 test 目录的上级目录中去使用 jar 命令来创建 JAR 文件包。也就是在目录树中使用“==”表示的那个目录中，使用如下命令： <br /><br />jar cvfm test.jar manifest.mf test <br /><br />　　之后在“==”目录中创建了 test.jar，这个 test.jar 就是执行的 JAR 文件包。运行时只需要使用 java -jar test.jar 命令即可。 <br /><br />　　需要注意的是，创建的 JAR 文件包中需要包含完整的、与 Java 程序的包结构对应的目录结构，就像上例一样。而 Main-Class 指定的类，也必须是完整的、包含包路径的类名，如上例的 test.Test；而且在没有打成 JAR 文件包之前可以使用 java &lt;类名&gt; 来运行这个类，即在上例中 java test.Test 是可以正确运行的 (当然要在 CLASSPATH 正确的情况下)。 </font>
		<p>
				<span class="f14">
						<font face="Courier New">　　3. jar 命令详解 <br /><br />　　jar 是随 JDK 安装的，在 JDK 安装目录下的 bin 目录中，Windows 下文件名为 jar.exe，Linux 下文件名为 jar。它的运行需要用到 JDK 安装目录下 lib 目录中的 tools.jar 文件。不过我们除了安装 JDK 什么也不需要做，因为 SUN 已经帮我们做好了。我们甚至不需要将 tools.jar 放到 CLASSPATH 中。 <br /><br />　　使用不带任何的 jar 命令我们可以看到 jar 命令的用法如下： <br /><br />　　jar {ctxu}[vfm0M] [jar-文件] [manifest-文件] [-C 目录] 文件名 ... <br /><br />　　其中 {ctxu} 是 jar 命令的子命令，每次 jar 命令只能包含 ctxu 中的一个，它们分别表示： <br /><br />　　　-c　创建新的 JAR 文件包 <br /><br />　　　-t　列出 JAR 文件包的内容列表 <br /><br />　　　-x　展开 JAR 文件包的指定文件或者所有文件 <br /><br />　　　-u　更新已存在的 JAR 文件包 (添加文件到 JAR 文件包中) <br /><br />　　　　　[vfm0M] 中的选项可以任选，也可以不选，它们是 jar 命令的选项参数 <br /><br />　　　-v　生成详细报告并打印到标准输出 <br /><br />　　　-f　指定 JAR 文件名，通常这个参数是必须的 <br /><br />　　　-m　指定需要包含的 MANIFEST 清单文件 <br /><br />　　　-0　只存储，不压缩，这样产生的 JAR 文件包会比不用该参数产生的体积大，但速度更快 <br /><br />　　　-M　不产生所有项的清单（MANIFEST〕文件，此参数会忽略 -m 参数 <br /><br />　　　　　[jar-文件] 即需要生成、查看、更新或者解开的 JAR 文件包，它是 -f 参数的附属参数 <br /><br />　　　　　[manifest-文件] 即 MANIFEST 清单文件，它是 -m 参数的附属参数 <br /><br />　　　　　[-C 目录] 表示转到指定目录下去执行这个 jar 命令的操作。它相当于先使用 cd 命令转该目录下再执行不带 -C 参数的 jar 命令，它只能在创建和更新 JAR 文件包的时候可用。　　 <br /><br />　　文件名 ... 指定一个文件/目录列表，这些文件/目录就是要添加到 JAR 文件包中的文件/目录。如果指定了目录，那么 jar 命令打包的时候会自动把该目录中的所有文件和子目录打入包中。 <br /><br />　　下面举一些例子来说明 jar 命令的用法： <br /><br />　　1) jar cf test.jar test <br /><br />　　该命令没有执行过程的显示，执行结果是在当前目录生成了 test.jar 文件。如果当前目录已经存在 test.jar，那么该文件将被覆盖。 <br /><br />　　2) jar cvf test.jar test <br /><br />　　该命令与上例中的结果相同，但是由于 v 参数的作用，显示出了打包过程，如下： <br /><br />　　标明清单(manifest) <br /><br />　　增加：test/(读入= 0) (写出= 0)(存储了 0%) <br /><br />　　增加：test/Test.class(读入= 7) (写出= 6)(压缩了 14%) <br /><br />　　3) jar cvfM test.jar test <br /><br />　　该命令与 2) 结果类似，但在生成的 test.jar 中没有包含 META-INF/MANIFEST 文件，打包过程的信息也略有差别： <br /><br />　　增加：test/(读入= 0) (写出= 0)(存储了 0%) <br /><br />　　增加：test/Test.class(读入= 7) (写出= 6)(压缩了 14%) <br /><br />　　4) jar cvfm test.jar manifest.mf test <br /><br />　　运行结果与 2) 相似，显示信息也相同，只是生成 JAR 包中的 META-INF/MANIFEST 内容不同，是包含了 manifest.mf 的内容 <br /><br />　　5) jar tf test.jar <br /><br />　　在 test.jar 已经存在的情况下，可以查看 test.jar 中的内容，如对于 2) 和 3) 生成的 test.jar 分别应该此命令，结果如下； <br /><br />　　对于 2) <br /><br />　　META-INF/ <br /><br />　　META-INF/MANIFEST.MF <br /><br />　　test/ <br /><br />　　test/Test.class <br /><br />　　对于 3) <br /><br />　　test/ <br /><br />　　test/Test.class <br /><br />　　6) jar tvf test.jar <br /><br />　　除显示 5) 中显示的内容外，还包括包内文件的详细信息，如： <br /><br />　　0 Wed Jun 19 15:39:06 GMT 2002 META-INF/ <br /><br />　　86 Wed Jun 19 15:39:06 GMT 2002 META-INF/MANIFEST.MF <br /><br />　　0 Wed Jun 19 15:33:04 GMT 2002 test/ <br /><br />　　7 Wed Jun 19 15:33:04 GMT 2002 test/Test.class <br /><br />　　7) jar xf test.jar <br /><br />　　解开 test.jar 到当前目录，不显示任何信息，对于 2) 生成的 test.jar，解开后的目录结构如下： <br /><br />　　== <br /><br />　　|-- META-INF <br /><br />　　|　 `-- MANIFEST <br /><br />　　`-- test <br /><br />　　　　`--Test.class <br /><br />jar xvf test.jar <br /><br />　　运行结果与 7) 相同，对于解压过程有详细信息显示，如： <br /><br />　　创建：META-INF/ <br /><br />　　展开：META-INF/MANIFEST.MF <br /><br />　　创建：test/ <br /><br />　　展开：test/Test.class <br /><br />　　9) jar uf test.jar manifest.mf <br /><br />　　在 test.jar 中添加了文件 manifest.mf，此使用 jar tf 来查看 test.jar 可以发现 test.jar 中比原来多了一个 manifest。这里顺便提一下，如果使用 -m 参数并指定 manifest.mf 文件，那么 manifest.mf 是作为清单文件 MANIFEST 来使用的，它的内容会被添加到 MANIFEST 中；但是，如果作为一般文件添加到 JAR 文件包中，它跟一般文件无异。 <br /><br />　　10) jar uvf test.jar manifest.mf <br /><br />　　与 9) 结果相同，同时有详细信息显示，如： <br /><br />　　增加：manifest.mf(读入= 17) (写出= 19)(压缩了 -11%) <br /><br />　　4. 关于 JAR 文件包的一些技巧 <br /><br />　　1) 使用 unzip 来解压 JAR 文件 <br /><br />　　在介绍 JAR 文件的时候就已经说过了，JAR 文件实际上就是 ZIP 文件，所以可以使用常见的一些解压 ZIP 文件的工具来解压 JAR 文件，如 Windows 下的 WinZip、WinRAR 等和 Linux 下的 unzip 等。使用 WinZip 和 WinRAR 等来解压是因为它们解压比较直观，方便。而使用 unzip，则是因为它解压时可以使用 -d 参数指定目标目录。 <br /><br />　　在解压一个 JAR 文件的时候是不能使用 jar 的 -C 参数来指定解压的目标的，因为 -C 参数只在创建或者更新包的时候可用。那么需要将文件解压到某个指定目录下的时候就需要先将这具 JAR 文件拷贝到目标目录下，再进行解压，比较麻烦。如果使用 unzip，就不需要这么麻烦了，只需要指定一个 -d 参数即可。如： <br /><br />　　unzip test.jar -d dest/ <br /><br />　　2) 使用 WinZip 或者 WinRAR 等工具创建 JAR 文件 <br /><br />　　上面提到 JAR 文件就是包含了 META-INF/MANIFEST 的 ZIP 文件，所以，只需要使用 WinZip、WinRAR 等工具创建所需要 ZIP 压缩包，再往这个 ZIP 压缩包中添加一个包含 MANIFEST 文件的 META-INF 目录即可。对于使用 jar 命令的 -m 参数指定清单文件的情况，只需要将这个 MANIFEST 按需要修改即可。 <br /><br />　　3) 使用 jar 命令创建 ZIP 文件 <br /><br />　　有些 Linux 下提供了 unzip 命令，但没有 zip 命令，所以需要可以对 ZIP 文件进行解压，即不能创建 ZIP 文件。如要创建一个 ZIP 文件，使用带 -M 参数的 jar 命令即可，因为 -M 参数表示制作 JAR 包的时候不添加 MANIFEST 清单，那么只需要在指定目标 JAR 文件的地方将 .jar 扩展名改为 .zip 扩展名，创建的就是一个不折不扣的 ZIP 文件了，如将上一节的第 3) 个例子略作改动： <br /><br />　　jar cvfM test.zip test</font>
				</span>
		</p>
<img src ="http://www.blogjava.net/hua/aggbug/45855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/hua/" target="_blank">花</a> 2006-05-12 15:35 <a href="http://www.blogjava.net/hua/articles/45855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>