??xml version="1.0" encoding="utf-8" standalone="yes"?>
常常遇到数组排序的问?比如我有一个Personc?它的实例对象存储在ArrayList数组?现在要把ArrayList数组中的Person对象按照q龄排序. 1:Person.java文g:------------------------------- public int getAge() { public void setAge(int age) { public String getName() { public void setName(String name) { } public int compare(Object o1,Object o2) { } 3:ListSort.java------------------------------------ package com.infoearth; import java.util.ArrayList; public class ListSort { } Java异常的语法应该是很简单的Q一个tryQcatchQfinallyQ一个throwsQthrowQ两分钟可学完了。我怿许多人和我一P对于异常是这样处理的Q?BR>1.写程序时q~译器检查,一旦通不q就加tryQcatch; 查阅资料可以得知QJava最主要的异常类包括4U:Throwable、Error、Exception和RuntimeExceptionQ其中Throwable是所有异常类的父c,它承Objectcdƈ实现Serializable接口QError和Exception都是Throwable的子c;而RuntimeException是Exception的子cRException的子c非常多Q但是RuntimeException是一个特D的子类Q需要单独讨论?BR> 一般当E序员在某个Ҏ(gu)中抛Z个Exception异常Q或者其子类Q时Q需在方法头部声明此Ҏ(gu)抛出了一个异常,是用throws关键字来声明Q但是如果在Ҏ(gu)中抛Z个RuntimeException或者一个ErrorӞ则不需要声明此Ҏ(gu)抛出了异常,q是Z么呢Q?BR> 语法上的U束必然有其背后的道理;如果不去弄明白这些道理而是一味的依赖~辑器来帮忙Q则事倍功半。事实上QJava语言的这U语法含义是QJava~译器要求JavaE序必须捕获或声明所有非q行时的异常Q也是_Exception异常是需查异常,必须q序员对它严格的负责,如果在方法中抛出Q必d明,如果抛出的异常没有被catchQ则会出现语法错误,~译都不能通过。这是强制性的让程序员遵守Java的异常规则。这栯定的原因是当Exception异常出现Ӟq行的程序还有补救的余地Q通过异常处理代码Q可以让E序恢复q行Q如果不捕捉q种异常Q则白白费了补救程序的Z。而且Q这U异常应让程序员可见Q所以必dҎ(gu)头部声明此方法抛Z某种Exception异常?BR> 那么QError和RuntimeException都是不需查异常,在方法中抛出q两U异帔R不需要声明,在程序中不catch它们也不会造成语法错误。我的理解是Q当出现q样的异常时Q运行的E序已经没有补救的余CQ于是直接抛出异常让E序l束是比较合理的安排。如果在E序q行时出CError或者RuntimeExceptionQ那么程序员也无能ؓ力,所以它们可以对E序员透明Q也不需要特意声明让E序员来处理它们?BR> 现在我们知道Qtry和catch一般对Exception及其子类使用Qthrows也是。而对于Error和RuntimeException则不需要throwsQ不q还是可以catch的,但是catch到它们一般也是释放资源Q退出程序而已?BR> 对于catch到的异常的处理,最l常犯的错误是丢失异常Qcatch到旧的异常抛出新的异常,{到E序出错时就找不到旧异常的信息了。其实JDK1.4已经提供了这个问题的解决Ҏ(gu)Q就是用Exception的构造函数Ş成异帔RQ用旧异怽为参数构造新异常Q这样就可以在出错时一步步跟踪到所有出现过的异怺Q这两个构造函数就是: 2005-03-02 15:40 作? wxb_nudt
]]>
ArrayList中的数据排序--java对象排序
其实q种情况l常遇到.
下面l出源代?
public class Person{
String name;
int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
return age;
}
this.age = age;
}
return name;
}
this.name = name;
}
2:Mycomparator.java-------------------------------
//实现Comparator接口,也就是定义排序规?你几乎可以定义Q何规?BR>package com.infoearth;
import java.util.*;
public class Mycomparator implements Comparator{
Person p1=(Person)o1;
Person p2=(Person)o2;
if(p1.age<p2.age)
return 1;
else
return 0;
}
import java.util.Collections;
import java.util.Comparator;
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add(new Person("lcl",28));
list.add(new Person("fx",23));
list.add(new Person("wqx",29));
Comparator comp = new Mycomparator();
Collections.sort(list,comp);
for(int i = 0;i<list.size();i++){
Person p = (Person)list.get(i);
System.out.println(p.getName());
}
}
]]>
2.自己抛异常常常忘了在Ҏ(gu)声明时加throwsQ而且又不明白Z么有的异帔R要throwsQ而有的又不需?
3.从来不写自己的异常类Q?BR>4.catch到异怸知道怎么办,通通加一行printStackTrace拉倒;
如果属于以上q几U情늚Q我觉得有必要和我一赯Z下Java的异怋用方法?/FONT>
public Exception(String message, Throwable cause) {
super(message, cause);
}
public Exception(Throwable cause) {
super(cause);
}
想到这么多Q以后有了新体会再箋?/FONT>
]]>
one-time pad的算法有以下要求Q?BR>1、密钥必随Z?BR>2、密钥不能重复?BR>3、密钥和密文的长度是一L?BR>
one-time pad是最安全的加密算法,双方一旦安全交换了密钥Q之后交换信息的q程是l对安全的啦。这U算法一直在一些要求高度机密的场合使用Q据说美国和前苏联之间的热线?sh)话、前苏联的间谍都是用One-time pad的方式加密的。不超U计机工作多久Q也不管多少人,用什么方法和技术,h多大的计能力,都不可能破解?BR>
一ơ一密的一U实现方式,如下Q?BR>
public class OneTimePadUtil
{
public static byte[] xor(byte[] bytes, byte[] keyBytes)
{
if (keyBytes.length != bytes.length)
{
throw new IllegalArgumentException();
}
byte[] resultBytes = new byte[bytes.length];
for (int i = 0; i < resultBytes.length; ++i)
{
resultBytes[i] = (byte) (keyBytes[i] ^ bytes[i]);
}
return resultBytes;
}
}
使用例子Q?BR>
String plainText = "温少";
String keyText = "密码";
byte[] plainBytes = plainText.getBytes();
byte[] keyBytes = keyText.getBytes();
assert plainBytes.length == keyBytes.length;
//加密
byte[] cipherBytes = OneTimePadUtil.xor(plainBytes, keyBytes);
//解密
byte[] cipherPlainBytes = OneTimePadUtil.xor(cipherBytes, keyBytes);
q是最单的加密法Q但也是最安全的机密算法。前天和朋友讨论Cq个问题Q所以写了这文章?/FONT>
]]>import java.security.*;
import javax.crypto.*;
/**//**
* <p>Title: </p>
*
* <p>Description: </p>
*
* <p>Copyright: Copyright (c) 2005</p>
*
* <p>Company: </p>
*
* @author George Hill
* @version 1.0
*/
public class Test
{
// 加密使用的Key
private SecretKey key;
// 加密法QJCE可用DES,DESede和Blowfish
private static final String algorithm = "DES";
public Test() throws NoSuchAlgorithmException
{
KeyGenerator generator = KeyGenerator.getInstance(algorithm);
key = generator.generateKey();
}
/**//**
* 利用DES法加密
* @param s String 需要加密的字符?BR>
* @return String 加密后的字符?BR>
* @throws Exception
*/
public String encryptData(String s) throws Exception
{
Cipher c = Cipher.getInstance(algorithm);
c.init(Cipher.ENCRYPT_MODE, key);
return new String(c.doFinal(s.getBytes()));
}
/**//**
* 利用DES法解密
* @param s String 需要解密的字符?BR>
* @return String 解密后的字符?BR>
* @throws Exception
*/
public String decryptData(String s) throws Exception
{
Cipher c = Cipher.getInstance(algorithm);
c.init(Cipher.DECRYPT_MODE, key);
return new String(c.doFinal(s.getBytes()));
}
/**//**
* 试E序
* @param args String[]
* @throws Exception
*/
public static void main(String[] args) throws Exception
{
String s = "Hello";
Test test = new Test();
String encrypt = test.encryptData(s);
System.out.println(encrypt);
String decrypt = test.decryptData(encrypt);
System.out.println(decrypt);
}
}
]]>
一、目?nbsp;
对于代码Q首要要求是它必L,能够按照E序员的真实思想去运行;W二个的要求是代码必L晰易懂,使别的程序员能够Ҏ(gu)理解代码所q行的实际工作。在软g工程领域Q源E序的风格统一标志着可维护性、可L,是Y仉目的一个重要组成部分。而目前还没有成文的编码风格文档,以致于很多时候,E序员没有一个共同的标准可以遵守Q编码风格各异,E序可维护性差、可L也很差。通过建立代码~写规范QŞ成开发小l编码约定,提高E序的可靠性、可L、可修改性、可l护性、可l承性和一致性,可以保证E序代码的质量,l承软g开发成果,充分利用资源Q开发h员之间的工作成果可以׃n?/FONT>
本文在参考业界已有的~码风格的基上,描述了一个基?JBuilder 的项目风|力求一U统一的编E风|q从整体~码风格、代码文仉根{函数编写风根{变量风根{注释风格等几个斚wq行阐述。(q些规范q不是一定要l对遵守Q但是一定要让程序有良好的可L)
二、整体编码风?/FONT>
1、羃q?/FONT>
~进?个空gؓ单位。徏议在 Tools/Editor Options 中设|?Editor 面的Block ident?QTab Size ?。预处理语句、全局数据、标题、附加说明、函数说明、标L均顶g写。语句块?{"?}"配对寚wQƈ与其前一行对齐,语句块类的语句羃q徏议每?{"?}"单独占一行,便于匹对。JBuilder 中的默认方式是开始的"{"不是单独一行,更改成上q格式(?Project/Default Project Properties 中设|?Code Style 中选择 Braces ?Next lineQ?/FONT>
2、空?/FONT>
原则上变量、类、常量数据和函数在其cdQ修饰名UC间适当I格q据情况寚w。关键字原则上空一|如:if ( ... {。运符的空D定如下:"::"?->"?["?]"?++"?--"?~"?!"?+"?-"Q指正负P?&"Q引用){几个运符两边不加I格Q其中单目运符pL与操作数相连的一边)Q其它运符Q包括大多数二目q算W和三目q算W??:"两边均加一I格Q在作函数定义时q可据情况多I或不空格来寚wQ但在函数实现时可以不用?,"q算W只在其后空一|需寚w时也可不I或多空根{不论是否有括号Q对语句行后加的注释应用适当I格与语句隔开q尽可能寚w。个为此可以依照个Z惯决定遵循与否?/FONT>
3、对?/FONT>
原则上关pd切的行应寚wQ对齐包括类型、修饰、名U、参数等各部分对齐。另每一行的长度不应过屏幕太多Q必要时适当换行Q换行时可能在","处或q算W处Q换行后最好以q算W打_q且以下各行均以该语句首行羃q,但该语句仍以首行的羃qؓ准,卛_其下一行ؓ“{”应与首行对齐?/FONT>
变量定义最好通过dI格形成寚wQ同一cd的变量最好放在一赗如下例所C:
int Value;
int Result;
int Length;
DWORD Size;
DWORD BufSize;
个h认ؓ此项可以依照个h习惯军_遵@与否?/FONT>
4、空?/FONT>
不得存在无规则的IQ比如说q箋十个I。程序文件结构各部分之间IZ行,若不必要也可只空一行,各函数实C间一般空两行Q由于每个函数还要有函数说明注释Q故通常只需IZ行或不空Q但对于没有函数说明的情况至应再空一行。对自己写的函数Q徏议也加上?/------”做分隔。函数内部数据与代码之间应空臛_一行,代码中适当处应以空行空开Q徏议在代码中出现变量声明时Q在其前IZ行。类中四个“p”之间至空一行,在其中的数据与函C间也应空行?/FONT>
5、注?/FONT>
注释是Y件可L的具体体现。程序注释量一般占E序~码量的20%QY件工E要求不于20%。程序注释不能用抽象的语aQ类g"处理"?循环"q样的计机抽象语言Q要_表达出程序的处理说明。例如:"计算净需??计算W一道工序的加工工时"{。避免每行程序都使用注释Q可以在一D늨序的前面加一D|释,h明确的处理逻辑?/FONT>
注释必不可少Q但也不应过多,不要被动的ؓ写注释而写注释。以下是四种必要的注释:
A. 标题、附加说明?/FONT>
B. 函数、类{的说明。对几乎每个函数都应有适当的说明,通常加在函数实现之前Q在没有函数实现部分的情况下则加在函数原型前Q其内容主要是函数的功能、目的、算法等说明Q参数说明、返回D明等Q必要时q要有一些如特别的Yg要求{说明。公用函数、公用类的声明必ȝ注解说明其用方法和设计思\Q当焉择恰当的命名格式能够帮助你把事情解释得更清楚?/FONT>
C. 在代码不明晰或不可移植处必须有一定的说明?/FONT>
D. 及少量的其它注释Q如自定义变量的注释、代码书写时间等?/FONT>
注释有块注释和行注释两种Q分别是指:"/**/"?//"对A用块注释QD用行注释QB、C则视情况而定Q但应统一Q至在一个单元中BcL释Ş式应l一。具体对不同文g、结构的注释会在后面详细说明?/FONT>
6、代码长?/FONT>
对于每一个函数徏议尽可能控制其代码长度ؓ53行左叻I过53行的代码要重新考虑其拆分Z个或两个以上的函数。函数拆分规则应该一不破坏原有算法ؓ基础Q同时拆分出来的部分应该是可以重复利用的。对于在多个模块或者窗体中都要用到的重复性代码,完全可以v独立成ؓ一个具备公用性质的函敎ͼ攄于一个公用模块中?/FONT>
7、页?/FONT>
宽应该讄?0字符。源代码一般不会超q这个宽? q导致无法完整显C? 但这一讄也可以灵z调? 在Q何情况下, 长的语句应该在一个逗号或者一个操作符后折? 一条语句折行后, 应该比原来的语句再羃q?个字W?
8、行?/FONT>
一般的集成~程环境下,每屏大概只能昄不超q?0行的E序Q所以这个函数大概要5-6屏显C,在某些环境下?屏左x能显C完。这样一来,无论是读E序q是修改E序Q都会有困难。因此徏议把完成比较独立功能的程序块抽出Q单独成Z个函数。把完成相同或相q功能的E序块抽出,独立Z个子函数。可以发玎ͼ是上层的函数越单,是调用几个子函敎ͼ是底层的函数完成的是具体的工作。这是好E序的一个标志。这P我们可以在较上层函数里Ҏ(gu)控制整个E序的逻辑Q而在底层的函数里专注于某斚w的功能的实现了?/FONT>
三、代码文仉?/FONT>
所有的 Java(*.java) 文g都必遵守如下的样式规则Q?/FONT>
. 文g生成
对于规范?JAVA zc,量?JBuilder ?Object Gallery 工具来生成文件格式,避免用手工制作的头文?实现文g?BR>
. package/import
package 行要?import 行之前,import 中标准的包名要在本地的包名之前,而且按照字母序排列。如?import 行中包含了同一个包中的不同子目录,则应该用 * 来处理?
package hotlava.net.stats;
import java.io.*;
import java.util.Observable;
import hotlava.util.Application;
q里 java.io.* 使用来代替InputStream and OutputStream 的?/FONT>
. 文g头部注释
文g头部注释主要是表明该文g的一些信息,是程序的M说明Q可以增强程序的可读性和可维护性。文件头部注释一般位?package/imports 语句之后QClass 描述之前。要求至写出文件名、创、创建时间和内容描述。JBuilder ?Object Gallery 工具生成的代码中会在cR工E文件中{自动添加注释,我们也要d一些注释,其格式应该尽量约束如下:
/**
* Title: 定鼠标位置c?BR> * Description: 定鼠标当前在哪个作业栏位中q返回作业号
* @Copyright: Copyright (c) 2002
* @Company: HIT
* @author: rivershan
* @version: 1.0
* @time: 2002.10.30
*/
. Class
接下来的是类的注释,一般是用来解释cȝ?
/**
* A class representing a set of packet and byte counters
* It is observable to allow it to be watched, but only
* reports changes when the current set is complete
*/
接下来是cd义,包含了在不同的行?extends ?implements
public class CounterSet
extends Observable
implements Cloneable
.Class Fields
接下来是cȝ成员变量Q?
/**
* Packet counters
*/
protected int[] packets;
public 的成员变量必ȝ成文档(JavaDocQ。proceted、private?package 定义的成员变量如果名字含义明的话,可以没有注释?/FONT>
. 存取Ҏ(gu)
接下来是cd量的存取的方法。它只是单的用来类的变量赋D取值的话,可以单的写在一行上。(个h认ؓ量分行写)
/**
* Get the counters
* @return an array containing the statistical data. This array has been
* freshly allocated and can be modified by the caller.
*/
public int[] getPackets()
{
return copyArray(packets, offset);
}
public int[] getBytes()
{
return copyArray(bytes, offset);
}
public int[] getPackets()
{
return packets;
}
public void setPackets(int[] packets)
{
this.packets = packets;
}
其它的方法不要写在一行上
. 构造函?
接下来是构造函敎ͼ它应该用递增的方式写Q比如:参数多的写在后面Q?
讉Kcd("public","private" {?)和Q?static","final"?synchronized"应该在一行中Qƈ且方法和参数另写一行,q样可以使方法和参数更易诅R?
public
CounterSet(int size)
{
this.size = size;
}
. 克隆Ҏ(gu)
如果q个cL可以被克隆的Q那么下一步就?clone Ҏ(gu)Q?
public
Object clone()
{
try
{
CounterSet obj = (CounterSet)super.clone();
obj.packets = (int[])packets.clone();
obj.size = size;
return obj;
}
catch(CloneNotSupportedException e)
{
throw new InternalError("Unexpected CloneNotSUpportedException: "
+ e.getMessage());
}
}
. cL?
下面开始写cȝҎ(gu)Q?
/**
* Set the packet counters
* (such as when restoring from a database)
*/
protected final
void setArray(int[] r1, int[] r2, int[] r3, int[] r4)
throws IllegalArgumentException
{
//
// Ensure the arrays are of equal size
//
if (r1.length != r2.length || r1.length != r3.length || r1.length != r4.length)
throw new IllegalArgumentException("Arrays must be of the same size";
System.arraycopy(r1, 0, r3, 0, r1.length);
System.arraycopy(r2, 0, r4, 0, r1.length);
}
. toString Ҏ(gu)
无论如何Q每一个类都应该定?toString Ҏ(gu)Q?
public
String toString()
{
String retval = "CounterSet: ";
for (int i = 0; i < data.length(); i++)
{
retval += data.bytes.toString();
retval += data.packets.toString();
}
return retval;
}
. main Ҏ(gu)
如果main(String[]) Ҏ(gu)已经定义? 那么它应该写在类的底?
四、函数编写风?/FONT>
. 函数的命?/FONT>
通常Q函数的命名也是以能表达函数的动作意义ؓ原则的,一般是由动词打_然后跟上表示动作对象的名词,各单词的首字母应该大写。另外,q有一些函数命名的通用规则。如取数Q则用Get打头Q然后跟上要取的对象的名字;讄敎ͼ则用Set打头Q然后跟上要讄对象的名字;而对象中Z响应消息q行动作的函敎ͼ可以命名为On打头Q然后是相应的消息的名称Q进行主动动作的函数Q可以命名ؓDo打头Q然后是相应的动作名U。类似的规则q有很多Q需要程序员多读优秀的程序,逐渐U篏l验Q才能作出好的函数命名?/FONT>
. 函数注释
pȝ自动生成的函敎ͼ如鼠标动作响应函数等Q不必太多的注释和解释;
对于自行~写的函敎ͼ若是pȝ关键函数Q则必须在函数实现部分的上方标明该函数的信息Q格式如下:
/**
* 函数名:
* ~写者:
* 参考资料:
* ?nbsp; 能:
* 输入参数Q?BR>* 输出参数Q?BR>* ?nbsp; 注:
*/
希望量遵@以上格式?/FONT>
五、符号风?/FONT>
. M要求
对于各种W号的定义,都有一个共通点Q就是应该用有实际意义的英文单词或英文单词的羃写,不要使用单但没有意义的字Ԍ可能不使用阿拉伯数字,更切忌用中文拼音的首字母。如q样的名U是不提倡的QValue1,Value2,Value3,Value4 …?/FONT>
例如Q?BR>file(文g),code(~号),data(数据),pagepoint(面指针), faxcode(传真? ,address(地址),bank(开户银?,…?/FONT>
. 变量名称
变量命名由(前缀+修饰语)构成。现在比较流行的是一套由微Y的一个匈牙利软g工程师首先用,q且在微软推q开来,现在被称之ؓ匈牙利命名法的命名规则。匈牙利命名法规定,使用表示标识W所对应的变量类型的英文写~写作ؓ标识W的前缀Q后面在使用表示变量意义的英文单词或~写q行命名。下面是匈牙利命名法中的一些命名方式:
Q?Q生存期修饰Q用l(local)表示局域变量,p(public)表示全局变量Qs(send)表示参数变量
Q?Q类型修饎ͼ用s(AnsiString)表示字符?c(char)表示字符,n(number)数?i(intger)表示整数,d(double)表示双精?f(float)点?b(bool)布尔?d(date)表示日期?
例如Q?BR>li_length表示整Ş的局域变?是用来标识长度的.ls_code表示字符型的局域变?用来标识代码.
. 控g名称
控g命名由(前缀+修饰语)构成。前~即ؓ控g的名U?/FONT>
按钮变量 Button+Xxxxxxx 例如QButtonSave,ButtonExit,ButtonPrint{?BR>题标变量 Label+Xxxxxxxx 例如QLabelName,LabelSex{?BR>数据表变?Table+Xxxxxx 例如QTableFile,TableCount{?BR>查询变量 Query+Xxxxxx 例如QQueryFile,QueryCeneter{?BR>数据源变?DataSource+Xxx 例如QDataSourceFile,DataSourceCenter{?BR>。。。。。。。。。。。。。。。?BR>(注:对于与表有关的控件“修饰语”部分最好直接用表名?
. Package 的命?
Package 的名字应该都是由一个小写单词组成?
. Class 的命?
Class 的名字必ȝ一个或C能表达该cȝ意思的大写字母开头而其它字母都写的单词或~写l成Q这栯使这?Class 的名U能更容易被理解?/FONT>
. Class 变量的命?
变量的名字必ȝ一个小写字母开头。后面的单词用大写字母开头。对于类的成员变量,在对其标识符命名Ӟ要加上代表memberQ成员)的前~m_。例如一个标识符为m_dwFlagQ则它表C的变量是一个类型ؓ双字的成员变量,它是代表一个标志?/FONT>
. Static Final 变量的命?
Static Final 变量的名字应该都大写Qƈ且指出完整含义?
. 参数的命?
参数的名字必d变量的命名规范一致?
. 数组的命?
数组应该L用下面的方式来命名:
byte[] buffer;
而不是:
byte buffer[];
. Ҏ(gu)的参?BR>
使用有意义的参数命名Q如果可能的话,使用和要赋值的字段一L名字Q?
SetCounter(int size)
{
this.size = size;
}
. 秘的数
首先要说什么是秘的数。我们在E序里经怼用到一些量Q它是有特定的含义的。例如,现在我们写一个薪金统计程序,公司员工?0人,我们在程序里׃?0q个数去q行各种各样的运。在q里Q?0是"秘的数"。ؓ什么称它ؓ秘呢?因ؓ别的E序员在E序里看?0q个敎ͼ不知道它的含义,只能靠猜了?/FONT>
在程序里出现"秘的数"会降低程序的可读性,应该量避免。避免的Ҏ(gu)是把秘的数定义Z个常量。注意这个常量的命名应该能表达该数的意义Qƈ且应该全部大写,以与对应于变量的标识W区别开来。例如上?0q个敎ͼ我们可以定义Z个名为NUMOFEMPLOYEES的常量来代替。这P别的E序员在ȝ序的时候就可以Ҏ(gu)理解了?/FONT>
六、程序编写风?/FONT>
. exit()
exit 除了?main 中可以被调用外,其他的地方不应该调用。因样做不给M代码代码Z来截获退出。一个类似后台服务地E序不应该因为某一个库模块军_了要退出就退出?
. 异常
x的错误应该抛Z个RuntimeException或者派生的异常?
层的main()函数应该截获所有的异常Qƈ且打华ͼ或者记录在日志中)在屏q上?
. 垃圾攉
JAVA使用成熟的后台垃圾收集技术来代替引用计数。但是这样会D一个问题:你必d使用完对象的实例以后q行清场工作。比如一个prel的程序员可能q么写:
...
{
FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, "IDE Project File";
}
...
除非输出一Z用域关闭,非引用计数的E序语言Q比如JAVAQ是不能自动完成变量的清场工作的。必象下面一样写Q?
FileOutputStream fos = new FileOutputStream(projectFile);
project.save(fos, "IDE Project File";
fos.close();
. Clone
下面是一U有用的Ҏ(gu)Q?
implements Cloneable
public
Object clone()
{
try
{
ThisClass obj = (ThisClass)super.clone();
obj.field1 = (int[])field1.clone();
obj.field2 = field2;
return obj;
}
catch(CloneNotSupportedException e)
{
throw new InternalError("Unexpected CloneNotSUpportedException: " + e.getMessage());
}
}
. final c?
l对不要因ؓ性能的原因将cd义ؓ final 的(除非E序的框架要求)
如果一个类q没有准备好被承,最好在cL档中注明Q而不要将她定义ؓ final 的。这是因为没有h可以保证会不会由于什么原因需要承她?BR>
. 讉Kcȝ成员变量
大部分的cL员变量应该定义ؓ protected 的来防止l承cM用他们?
注意Q要?int[] packets"Q而不?int packets[]"Q后一U永q也不要用?
public void setPackets(int[] packets)
{
this.packets = packets;
}
CounterSet(int size)
{
this.size = size;
}
. byte 数组转换?characters
Z?byte 数组转换?charactersQ你可以q么做:
"Hello world!".getBytes();
. Utility c?
Utility c(仅仅提供Ҏ(gu)的类Q应该被x为抽象的来防止被l承或被初始化?
. 初始?BR>
下面的代码是一U很好的初始化数l的Ҏ(gu)Q?
objectArguments = new Object[]
{
arguments
};
. 枚Dcd
JAVA Ҏ(gu)丄支持不好Q但是下面的代码是一U很有用的模板:
class Colour
{
public static final Colour BLACK = new Colour(0, 0, 0);
public static final Colour RED = new Colour(0xFF, 0, 0);
public static final Colour GREEN = new Colour(0, 0xFF, 0);
public static final Colour BLUE = new Colour(0, 0, 0xFF);
public static final Colour WHITE = new Colour(0xFF, 0xFF, 0xFF);
}
q种技术实CRED, GREEN, BLUE {可以象其他语言的枚丄型一样用的帔R?他们可以?'==' 操作W来比较?
但是q样使用有一个缺P如果一个用Lq样的方法来创徏颜色 BLACK
那么q就是另外一个对象,'=='操作W就会生错误。她?equal() Ҏ(gu)仍然有效。由于这个原因,q个技术的~陷最好注明在文档中,或者只在自q包中使用?/FONT>
. 混合使用 AWT ?Swing lg
如果要将 AWT lg?Swing lg混合h使用的话Q请心使用。实际上Q尽量不要将他们混合h使用?
. 滚动?AWT lg
AWT lgl对不要?JscrollPane cL实现滚动。滚?AWT lg的时候一定要?AWT ScrollPane lg来实现?/FONT>
. 避免?InternalFrame lg中?AWT lg
量不要q么做,要不然会出现不可预料的后果?
. Z-Order 问题
AWT lgL昄?Swing lg之上。当使用包含 AWT lg?POP-UP 菜单的时候要心Q尽量不要这样用?
八、性能
在写代码的时候,从头臛_都应该考虑性能问题。这不是说时间都应该费在优化代码上Q而是我们时刻应该提醒自己要注意代码的效率。比如:如果没有旉来实C个高效的法Q那么我们应该在文档中记录下来,以便在以后有I的时候再来实现她?
不是所有的人都同意在写代码的时候应该优化性能q个观点的,他们认ؓ性能优化的问题应该在目的后期再去考虑Q也是在程序的轮廓已经实现了以后?
. 不必要的对象构?
不要在@环中构造和释放对象
. 使用 StringBuffer 对象
在处?String 的时候要量使用 StringBuffer c,StringBuffer cL构成 String cȝ基础。String cd StringBuffer cd装了hQ(以花Ҏ(gu)多时间ؓ代h(hun)Qؓ开发h员提供了一个安全的接口。当我们在构造字W串的时候,我们应该?StringBuffer 来实现大部分的工作,当工作完成后?StringBuffer 对象再{换ؓ需要的 String 对象。比如:如果有一个字W串必须不断地在其后d许多字符来完成构造,那么我们应该使用 StringBuffer 对象和她?append() Ҏ(gu)。如果我们用 String 对象代替 StringBuffer 对象的话Q会p许多不必要的创徏和释攑֯象的 CPU 旉?
. 避免太多的?synchronized 关键?
避免不必要的使用关键?synchronizedQ应该在必要的时候再使用她,q是一个避免死锁的好方法?/FONT>
rivershan 原创?002.11.5
![]() ![]() ![]() |
作者:UB 旉Q?002-06-14 10:51:10 JSP/Servlet中的汉字编码问?1) [作?不详d旉:?001-9-6?:12:47?gt; ? |上MJSP/Servlet中DBCS字W编码问题有许多优秀的文章和讨论Q本文对它们作一些整理,q结合IBMWebSphereApplicationServer?.5QWASQ的解决Ҏ(gu)作一些说明,希望它不是多余的? 内容Q 问题的v源 GB2312-80QGBKQGB18030-2000汉字字W集及Encoding? 中文转码??'、ؕ码的由来? JSP/Servlet汉字编码问题及在WAS中的解军_法? l束? 1.问题的h? 每个国Ӟ或区域)都规定了计算Z息交换用的字W编码集Q如国的扩展ASCII?中国的GB2312-80Q日本的JIS等Q作国家/区域内信息处理的基础Q有着l一~码的重要作用。字W编码集按长度分为SBCSQ单字节字符集)QDBCSQ双字节字符集)两大cR早期的软gQ尤其是操作pȝQ,Z解决本地字符信息的计机处理Q出C各种本地化版本(L10NQ,Z区分Q引q了LANG,Codepage等概念。但是由于各个本地字W集代码范围重叠Q相互间信息交换困难QY件各个本地化版本独立l护成本较高。因此有必要本地化工作中的共性抽取出来,作一致处理,特别的本地化处理内定w低到最。这也就是所谓的国际化(I18NQ。各U语a信息被进一步规范ؓLocale信息。处理的底层字符集变成了几乎包含了所有字形的Unicode。 现在大部分h国际化特征的软g核心字符处理都是以Unicodeؓ基础的,在Y件运行时Ҏ(gu)当时的Locale/Lang/Codepage设|确定相应的本地字符~码讄Qƈ依此处理本地字符。在处理q程中需要实现Unicode和本地字符集的怺转换Q甚或以Unicodeؓ中间的两个不同本地字W集的相互{换。这U方式在|络环境下被q一步g伸,M|络两端的字W信息也需要根据字W集的设|{换成可接受的内容。 Java语a内部是用Unicode表C字W的Q遵守UnicodeV2.0。Java程序无论是?往文gpȝ以字W流?写文Ӟq是往URL连接写HTML信息,或从URL连接读取参数|都会有字W编码的转换。这样做虽然增加了编E的复杂度,Ҏ(gu)引vhQ但却是W合国际化的思想的。 从理Z来说Q这些根据字W集讄而进行的字符转换不应该生太多问题。而事实是׃应用E序的实际运行环境不同,Unicode和各个本地字符集的补充、完善,以及pȝ或应用程序实现的不规范,转码时出现的问题时时困扰着E序员和用户。 2.GB2312-80QGBKQGB18030-2000汉字字W集及Encoding? 其实解决JAVA程序中的汉字编码问题的Ҏ(gu)往往很简单,但理解其背后的原因,定位问题Q还需要了解现有的汉字~码和编码{换。 GB2312-80是在国内计机汉字信息技术发展初始阶D制定的Q其中包含了大部分常用的一、二U汉字,和9区的符受该字符集是几乎所有的中文pȝ和国际化的Y仉支持的中文字W集Q这也是最基本的中文字W集。其~码范围是高?xa1Q?xfeQ低位也是0xa1-0xfeQ汉字从?xb0a1开始,l束于0xf7feQ GBK是GB2312-80的扩展Q是向上兼容的。它包含了20902个汉字Q其~码范围是0x8140-0xfefeQ剔除高位0x80的字位。其所有字W都可以一对一映射到Unicode?.0Q也是说JAVA实际上提供了GBK字W集的支持。这是现阶段Windows和其它一些中文操作系l的~省字符集,但ƈ不是所有的国际化Y仉支持该字W集Q感觉是他们q不完全知道GBK是怎么回事。值得注意的是它不是国家标准,而只是规范。随着GB18030-2000国标的发布,它将在不久的来完成它的历史使命。 GB18030-2000(GBK2K)在GBK的基础上进一步扩展了汉字Q增加了藏、蒙{少数民族的字Ş。GBK2K从Ҏ(gu)上解决了字位不够Q字形不的问题。它有几个特点,? 它ƈ没有定所有的字ŞQ只是规定了~码范围Q留待以后扩充。 ~码是变长的Q其二字节部分与GBK兼容;四字节部分是扩充的字形、字位,其编码范围是首字节0x81-0xfe、二字节0x30-0x39、三字节?x81-0xfe、四字节0x30-0x39。 它的推广是分阶段的,首先要求实现的是能够完全映射到Unicode?.0标准的所有字形。 它是国家标准Q是强制性的? 现在q没有Q何一个操作系l或软g实现了GBK2K的支持Q这是现阶段和将来汉化的工作内容。 Unicode的介绍......免了吧。 JAVA支持的encoding中与中文~程相关的有Q?有几个在JDK文档中未列出)ASCII?-bit,同ascii7? ISO8859-1?-bit,同?859_1,ISO-8859-1,ISO_8859-1,latin1...? GB2312-80同gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381,?383,Cp1383,ISO2022CN,ISO2022CN_GB......? GBK?注意大小?,同MS936? UTF8UTF-8? GB18030?现在只有IBMJDK1.3.?有支?,同Cp1392,1392? JAVA语a采用Unicode处理字符.但从另一个角度来_在javaE序中也可以采用非Unicode的{码,重要的是保证E序入口和出口的汉字信息不失真。如完全采用ISO-8859-1来处理汉字也能达到正的l果。网l上行的许多解x法,都属于这U类型。ؓ了不致引h淆,本文不对q种Ҏ(gu)作讨论。 3.中文转码??'、ؕ码的由来? 两个方向转换都有可能得到错误的结果:? Unicode-->Byte,如果目标代码集不存在对应的代码,则得到的l果?x3f.? 如: "\u00d6\u00ec\u00e9\u0046\u00bb\u00f9".getBytes("GBK")的l果是"?ìéF?ù",Hex值是3fa8aca8a6463fa8b4.? 仔细看一下上面的l果Q你会发现\u00ec被{换ؓ0xa8ac,\u00e9被{换ؓ\xa8a6...它的实际有效位变长了!这是因为GB2312W号Z的一些符可映射C些公qW号~码Q由于这些符号出现在ISO-8859-1或其它一些SBCS字符集中Q故它们在Unicode中编码比较靠前,有一些其有效位只?位,和汉字的~码重叠(其实q种映射只是~码的映,在显C时仔细不是一L。Unicode中的符h单字节宽Q汉字中的符h双字节宽)?在Unicode\u00a0--\u00ff之间这LW号?0个。了解这个特征非帔R要!由此׃隄解ؓ什么JAVA~程中,汉字~码的错误结果中常常会出C些ؕ?其实是符号字W?,而不全是'?'字符,就比如上面的例子? Byte-->Unicode,如果Byte标识的字W在源代码集不存在,则得到的l果?xfffd.? 如: Byteba[>?{(byte)0x81,(byte)0x40,(byte)0xb0,(byte)0xa1};newString(ba,"gb2312");? l果???,hex值是"\ufffd\u554a".?x8140是GBK字符Q按GB2312转换表没有对应的|取\ufffd.?h意:在显CuniCodeӞ因ؓ没有对应的本地字W,所以也适用上一U情况,昄Z??".) 实际~程中,JSP/Servlet程序得到错误的汉字信息Q往往是这两个q程的叠加,有时甚至是两个过E叠加后反复作用的结?? 4.JSP/Servlet汉字编码问题及在WAS中的解军_法 4.1常见的encoding问题的现象 |上常出现的JSP/Servletencoding问题一般都表现在browser或应用E序端,?? 览器中看到的Jsp/Servlet页面中的汉字怎么都成了?’?? 览器中看到的Servlet页面中的汉字怎么都成了ؕ码?? JAVA应用程序界面中的汉字怎么都成了方块?? Jsp/Servlet页面无法显CGBK汉字。 JSP页面中内嵌?%...%>,<%=...%>{Tag包含的JAVAcode中的中文成了ؕ码,但页面的其它汉字是对的。 Jsp/Servlet不能接~form提交的汉字。 JSP/Servlet数据库d无法获得正确的内宏V? 隐藏在这些问题后面的是各U错误的字符转换和处理(除第3个外Q是因ؓJavafont设|错误引LQ。解决类似的字符encoding问题,需要了解Jsp/Servlet的q行q程Q检查可能出现问题的各个炏V 4.2JSP/Servletweb编E时的encoding问? q行于Java应用服务器的JSP/ServletؓBrowser提供HTML内容,其过E如下图所C:? ? ![]() 其中有字W编码{换的地方? JSP编译。Java应用服务器根据JVM的file.encodingD取JSP源文gQ编译生成JAVA源文gQ再Ҏ(gu)file.encoding值写回文件系l。如果当前系l语a支持GBKQ那么这时候不会出现encoding问题。如果是英文的系l,如LANG是en_US的Linux,AIX或SolarisQ则要将JVM的file.encoding值置成GBK。系l语a如果是GB2312Q则Ҏ(gu)需要,定要不要设|file.encodingQ将file.encoding设为GBK可以解x在的GBK字Wؕ码问题 Java需要被~译为.class才能在JVM中执行Q这个过E存在与a.同样的file.encoding问题。从q里开始servlet和jsp的q行qgQ只不过Servlet的~译不是自动q行的。对于JSPE序,对产生的JAVA中间文件的~译是自动进行的(在程序中直接调用sun.tools.javac.Mainc?.因此如果在q一步出现问题的?也要检查encoding和OS的语a环境Q或者将内嵌在JSPJAVACode中的静态汉字{为Unicode,要么静态文本输Z要放在JAVAcode中。对于Servlet,javac编译时手工指定-encoding参数就可以了。 Servlet需要将HTML页面内容{换ؓbrowser可接受的encoding内容发送出厅R依赖于各JAVAAppServer的实现方式Q有的将查询Browser的accept-charset和accept-language参数或以其它猜的方式确定encoding|有的则不。因此采用固定encoding也许是最好的解决Ҏ(gu)。对于中文网,可在JSP或Servlet中讄contentType="text/html;charset=GB2312"Q如果页面中有GBK字符Q则讄为contentType="text/html;charset=GBK"Q由于IE和Netscape对GBK的支持程度不一P作这U设|时需要测试一下? 因ؓ16位JAVAchar在网l传送时?位会被丢弃,也ؓ了确保Servlet面中的汉字Q包括内嵌的和servletq行q程中得到的Q是期望的内码,可以用PrintWriterout=res.getWriter()取代ServletOutputStreamout=res.getOutputStream().PrinterWriter将Ҏ(gu)contentType中指定的charset作{换(ContentType需在此之前指定Q?;也可以用OutputStreamWriter装ServletOutputStream类q用write(String)输出汉字字符丌Ӏ? 对于JSPQJAVAApplicationServer应当能够确保在q个阶段嵌入的汉字正确传送出厅R q是解释URL字Wencoding问题。如果通过get/post方式从browser返回的参数g包含汉字信息Qservlet将无法得到正确的倹{SUN的J2SDK中QHttpUtils.parseName在解析参数时根本没有考虑browser的语言讄Q而是得到的值按byte方式解析。这是网上讨论得最多的encoding问题。因是设计缺P只能以bin方式重新解析得到的字符Ԍ或者以hackHttpUtils类的方式解冟뀂参考文章2均有介l,不过最好将其中的中文encodingGB2312、CP1381都改ؓGBKQ否则遇到GBK汉字时Q还是会有问题。 ServletAPI?.3提供一个新的函数HttpServeletRequest.setCharacterEncoding用于在调用request.getParameter(“param_name?前指定应用E序希望的encodingQ这有助于d解决q个问题? 4.3IBMWebsphereApplicationServer中的解x法 WebSphereApplicationServer对标准的ServletAPI?.x作了扩展,提供较好的多语言支持。运行在中文的操作系l中Q可以不作Q何设|就可以很好地处理汉字。下面的说明只是对WAS是运行在英文的系l中Q或者需要有GBK支持时有效。 上述c,d情况QWAS都要查询Browser的语言讄Q在~省状况下,zh,zh-cn等均被映射为JAVAencodingCP1381Q注意:CP1381只是等同于GB2312的一个codepageQ没有GBK支持)。这样做我想是因为无法确认Browser运行的操作pȝ是支持GB2312,还是GBKQ所以取其小。但是实际的应用pȝq是要求面中出现GBK汉字,最著名的是朱ȝ名字中的“镕"(rong2,0xe946Q\u9555)Q所以有时还是需要将Encoding/Charset指定ؓGBK。当~WAS中变更~省的encoding没有上面说的那么麻烦,针对a,bQ参考文章5Q在ApplicationServer的命o行参C指定?Dfile.encoding=GBK即可;针ԎdQ在ApplicationServer的命o行参C指定-Ddefault.client.encoding=GBK。如果指定了-Ddefault.client.encoding=GBKQ那么c情况下可以不再指定charset。 上面列出的问题中q有一个关于Tag<%...%>,<%=...%>中的JAVA代码里包含的静态文本未能正显C的问题Q在WAS中的解决Ҏ(gu)是除了设|正的file.encoding,还需要以相同Ҏ(gu)讄-Duser.language=zh?Duser.region=CN。这与JAVAlocale的设|有兟뀂 4.4数据库d时的encoding问题 JSP/Servlet编E中l常出现encoding问题的另一个地Ҏ(gu)d数据库中的数据。 行的关pL据库pȝ都支持数据库encodingQ也是说在创徏数据库时可以指定它自q字符集设|,数据库的数据以指定的~码形式存储。当应用E序讉K数据Ӟ在入口和出口处都会有encoding{换。对于中文数据Q数据库字符~码的设|应当保证数据的完整?GB2312QGBKQUTF-8等都是可选的数据库encodingQ也可以选择ISO8859-1?8-bit)Q那么应用程序在写数据之前须16Bit的一个汉字或Unicode拆分成两个?-bit的字符Q读数据之后则需两个字节合qv来,同时q要判别其中的SBCS字W。没有充分利用数据库encoding的作用Q反而增加了~程的复杂度QISO8859-1不是推荐的数据库encoding。JSP/Servlet~程Ӟ可以先用数据库管理系l提供的理功能查其中的中文数据是否正确。 然后应当注意的是d来的数据的encodingQJAVA程序中一般得到的是Unicode。写数据时则相反。 4.5定位问题时常用的技巧 定位中文encoding问题通常采用最W的也是最有效的办法——在你认为有嫌疑的程序处理后打印字符串的内码。通过打印字符串的内码Q你可以发现什么时候中文字W被转换成UnicodeQ什么时候Unicode被{回中文内码,什么时候一个中文字成了两个Unicode字W,什么时候中文字W串被{成了一串问P什么时候中文字W串的高位被截掉了…… 取用合适的h字符串也有助于区分问题的cd。如Q”aa啊aa丂aa”{中q间、GB、GBK特征字符均有的字W串。一般来_英文字符无论怎么转换或处理,都不会失真(如果遇到了,可以试着增加q箋的英文字母长度)? 5.结束语? 其实JSP/Servlet的中文encodingƈ没有惛_的那么复杂,虽然定位和解决问题没有定规,各种q行环境也各不尽Ӟ但后面的原理是一L。了解字W集的知识是解决字符问题的基。不q,随着中文字符集的变化Q不仅仅是java编E,中文信息处理中的问题q是会存在一D|间的。 ...........................UB修改?002-06-14 10:52:07 作者:UB 旉Q?002-07-22 17:04:00 [修改] [回复] [删除] JAVA~程技术中汉字问题的分析及解决 文章来源Qwww.ibm.com? 在基于Java语a的编E中Q我们经常碰到汉字的处理及显C的问题。一大堆看不懂的q肯定不是我们愿意看到的显C效果,怎样才能够让那些汉字正确昄呢?Java语a默认的编码方式是UNICODE,而我们中国h通常使用的文件和数据库都是基于GB2312或者BIG5等方式~码的,怎样才能够恰当地选择汉字~码方式q正地处理汉字的编码呢Q本文将从汉字编码的常识入手Q结合Java编E实例,分析以上两个问题q提军_们的Ҏ(gu)? 现在Java编E语a已经q泛应用于互联网世界Q早在Sun公司开发Java语a的时候,已l考虑到对非英文字W的支持了。Sun公司公布的Java运行环境(JREQ本w就分英文版和国际版Q但只有国际版才支持非英文字W。不q在Java编E语a的应用中Q对中文字符的支持ƈ非如同JavaSoft的标准规范中所宣称的那样完,因ؓ中文字符集不只一个,而且不同的操作系l对中文字符的支持也不尽相同Q所以会有许多和汉字~码处理有关的问题在我们q行应用开发中困扰着我们。有很多关于q些问题的解{,但都比较琐碎Qƈ不能够满_家迫切解决问题的愿望Q关于Java中文问题的pȝ研究q不多,本文从汉字编码常识出发,分析Java中文问题,希望对大家解册个问题有所帮助? 汉字~码的常? 我们知道Q英文字W一般是以一个字节来表示的,最常用的编码方法是ASCII。但一个字节最多只能区?56个字W,而汉字成千上万,所以现在都以双字节来表C汉字,Z能够与英文字W分开Q每个字节的最高位一定ؓ1Q这样双字节最多可以表C?4K格字W。我们经常碰到的~码方式有GB2312、BIG5、UNICODE等。关于具体编码方式的详细资料Q有兴趣的读者可以查阅相兌料。我肤浅谈一下和我们关系密切的GB2312和UNICODE。GB2312码Q中华h民共和国国家标准汉字信息交换用编码,是一个由中华人民共和国国家标准d发布的关于简化汉字的~码Q通行于中国大陆地区及新加坡,U国标码。两个字节中Q第一个字节(高字节)的gؓ区号值加32Q?0HQ,W二个字节(低字节)的gؓ位号值加32Q?0HQ,用这两个值来表示一个汉字的~码。UNICODE码是微软提出的解决多国字符问题的多字节{长~码Q它对英文字W采取前面加?”字节的{略实现{长兼容。如“A”的ASCII码?x41QUNICODE就?x00Q?x41。利用特D的工具各种~码之间可以互相转换? Java中文问题的初步认识 我们ZJava编E语aq行应用开发时Q不可避免地要处理中文。Java编E语a默认的编码方式是UNICODEQ而我们通常使用的数据库及文仉是基于GB2312编码的Q我们经常碰到这L情况Q浏览基于JSP技术的|站看到的是qQ文件打开后看到的也是qQ被Java修改过的数据库的内容在别的场合应用时无法l正地提供信息。 StringsEnglish?“apple?? StringsChinese?“苹果?? Strings?“苹果apple?? sEnglish的长度?QsChinese的长度是4Q而s默认的长度?4。对于sEnglish来说QJava中的各个类都支持得非常好,肯定能够正确昄。但对于sChinese和s来_虽然JavaSoft声明Java的基本cdl考虑到对多国字符的支持(默认UNICODE编码)Q但是如果操作系l的默认~码不是UNICODE,而是国标码等。从Java源代码到得到正的l果Q要l过“Java源代码->Java字节码->?虚拟?>操作pȝ->昄讑֤”的q程。在上述q程中的每一步骤Q我们都必须正确地处理汉字的~码Q才能够使最l的昄l果正确。 “Java源代码->Java字节码”,标准的Java编译器javac用的字符集是pȝ默认的字W集Q比如在中文Windows操作系l上是GBK?而在Linux操作系l上是ISO-8859-1Q所以大家会发现在Linux操作系l上~译的类中源文g中的中文字符都出了问题,解决的办法就是在~译的时候添加encoding参敎ͼq样才能够与q_无关。用法是 javac–encodingGBK。 “Java字节码->虚拟?>操作pȝ”,Java运行环境QJREQ分英文版和国际版Q但只有国际版才支持非英文字W。Java开发工具包(JDKQ肯定支持多国字符Q但q所有的计算机用户都安装了JDK。很多操作系l及应用软gZ能够更好的支持Java,都内嵌了JRE的国际版本Qؓ自己支持多国字符提供了方ѝ? “操作系l?>昄讑֤”,对于汉字来说Q操作系l必L持ƈ能够昄它。英文操作系l如果不搭配Ҏ(gu)的应用Y件的话,是肯定不能够昄中文的。 q有一个问题,是在Java编E过E中Q对中文字符q行正确的编码{换。例如,向网输Z文字W串的时候,不论你是用 out.println(string);?/string是含中文的字符串 q是用 <%=string%>Q都必须作UNICODE到GBK的转换Q或者手动,或者自动。在JSP?.0中,可以定义输出字符集,从而实现内码的自动转换。用法是 <%@pageContentType=”text/html;charset=gb2312”%> 但是在一些JSP版本中q没有提供对输出字符集的支持Q(例如JSP?.92Q,q就需要手动编码输ZQ方法非常多。最常用的方法是? Strings1?request.getParameter(“keyword?;? Strings2?newString(s1.getBytes(“ISO-8859-1?,”GBK?;? getBytes方法用于将中文字符以“ISO-8859-1”编码方式{化成字节数组Q而“GBK”是目标编码方式。我们从以ISO-8859-1方式~码的数据库中读Z文字W串s1,l过上述转换q程Q在支持GBK字W集的操作系l和应用软g中就能够正确昄中文字符串s2。 Java中文问题的表层分析及处? 背景? 开发环境JDK1.15Vcafe2.0JPadPro? 服务器端NTIISSybaseSystemJconnectQJDBCQ 客户端IE5.0Pwin98? CLASS文件存攑֜服务器端Q由客户端的览器运行APPLET,APPLET只赯入FRAME类{主E序的作用。界面包括Textfield,TextAreaQListQChoice等? I.取中文? 用JDBC执行SELECT语句从服务器端d数据Q中文)后,数据用APPEND方法加到TextAreaQTAQQ不能正显C。但加到List中Ӟ大部分汉字却可正显C。 数据按“ISO-8859-1”~码方式转化为字节数l,再按pȝ~省~码方式(DefaultCharacterEncodingQ转化为STRING,卛_在TA和List中正确昄。 E序D如下:? dbstr2?results.getString(1);? //AfterreadingtheresultfromDBserverQconvertingittostring.? dbbyte1?dbstr2.getBytes(“iso-8859-1?;? dbstr1?newString(dbbyte1);? 在{换字W串时不采用pȝ默认~码方式Q而直接采用“GBK”或者“GB2312”,在A和B两U情况下Q从数据库取数据都没有问题。 II.写中文到数据库? 处理方式与“取中文”相逆,先将SQL语句按pȝ~省~码方式转化为字节数l,再按“ISO-8859-1”编码方式{化ؓSTRING,最后送去执行Q则中文信息可正写入数据库。 E序D如下:? sqlstmt?tf_input.getText();? //BeforesendingstatementtoDBserverQconvertingittosqlstatement.? dbbyte1?sqlstmt.getBytes();? sqlstmt?newString(dbbyte1,”iso-8859-1?;? _stmt?_con.createStatement();? _stmt.executeUpdate(sqlstmt);? …… 问题Q如果客h上存在CLASSPATH指向JDK的CLASSES.ZIP时Q称为A情况)Q上q程序代码可正确执行。但是如果客h只有览器,而没有JDK和CLASSPATH时Q称为B情况)Q则汉字无法正确转换。 我们的分析:? 1.l过试Q在A情况下Q程序运行时pȝ的缺省编码方式ؓGBK或者GB2312。在B情况下Q程序启动时览器的JAVA控制台中出现如下错误信息:? Can'tfindresourceforsun.awt.windows.awtLocalization_zh_CN? 然后pȝ的缺省编码方式ؓ?859-1”。 2.如果在{换字W串时不采用pȝ~省~码方式Q而是直接采用“GBK”或“GB2312”,则在A情况下E序仍然可正常运行,在B情况下Q系l出现错误:? UnsupportedEncodingException? 3.在客h上,把JDK的CLASSES.ZIP解压后Q放在另一个目录中QCLASSPATH只包含该目录。然后一辚w步删除该目录中的.CLASS文Ӟ另一边运行测试程序,最后发现在一千多个CLASS文件中Q只有一个是必不可少的,该文件是Qsun.io.CharToByteDoubleByte.class。 该文g拷到服务器端和其它的cL在一Pq在E序的开头IMPORT它Q在B情况下E序仍然无法正常q行。 4.在A情况下Q如果在CLASSPTH中Lsun.io.CharToByteDoubleByte.class,则程序运行时得默认~码方式为?859-1”,否则为“GBK”或“GB2312”。 如果JDK的版本?.2以上的话Q在B情况下遇到的问题得C很好的解冻I试的步骤同上,有兴的读者可以尝试一下。 Java中文问题的Ҏ(gu)分析及解? 在简体中文MSWindows?8?JDK?.3下Q可以用System.getProperties()得到Java运行环境的一些基本属性,cPoorChinese可以帮助我们得到这些属性。 cPoorChinese的源代码:? publicclassPoorChinese{? publicstaticvoidmain(String[>args){? System.getProperties().list(System.out);? }? }? 执行javaPoorChinese后Q我们会得到:? pȝ变量file.encoding的gؓGBK,user.language的gؓzh,user.region的gؓCN,q些pȝ变量的值决定了pȝ默认的编码方式是GBK。 在上q系l中Q下面的代码GB2312文件{换成Big5文Ӟ它们能够帮助我们理解Java中汉字~码的{?? importjava.io.*;? importjava.util.*;? publicclassgb2big5{? staticintiCharNum=0;? publicstaticvoidmain(String[>args){? System.out.println("InputGB2312file,outputBig5file.");? if?args.length!=2){? System.err.println("Usage:jviewgb2big5gbfilebig5file");? System.exit(1);? }? StringinputString?readInput(args[0>);? writeOutput(inputString,args[1>);? System.out.println("NumberofCharactersinfile:?+iCharNum+".");? }? staticvoidwriteOutput(Stringstr,StringstrOutFile){? try{? FileOutputStreamfos?newFileOutputStream(strOutFile);? Writerout?newOutputStreamWriter(fos,?Big5");? out.write(str);? out.close();? }? catch?IOExceptione){? e.printStackTrace();? e.printStackTrace();? }? }? staticStringreadInput(StringstrInFile){? StringBufferbuffer?newStringBuffer();? try{? FileInputStreamfis?newFileInputStream(strInFile);? InputStreamReaderisr?newInputStreamReader(fis,?GB2312");? Readerin?newBufferedReader(isr);? intch;? while?(ch?in.read())?gt;?1){? iCharNum?=?;? buffer.append((char)ch);? }? in.close();? returnbuffer.toString();? }? catch?IOExceptione){? e.printStackTrace();? returnnull;? }? }? }? ~码转化的过E如下:? ByteToCharGB2312CharToByteBig5? GB2312------------------>Unicode------------->Big5? 执行javagb2big5gb.txtbig5.txt,如果gb.txt的内容是“今天星期三”,则得到的文gbig5.txt中的字W能够正显C;而如果gb.txt的内容是“情快乐”,则得到的文gbig5.txt中对应于“节”和“乐”的字符都是W号“?”(0x3FQ,可见sun.io.ByteToCharGB2312和sun.io.CharToByteBig5这两个基本cdƈ没有~好。 正如上例一PJava的基本cM可能存在问题。由于国际化的工作ƈ不是在国内完成的Q所以在q些基本cd布之前,没有l过严格的测试,所以对中文字符的支持ƈ不像JavaSoft所声称的那样完。前不久Q我的一位技术上的朋友发信给我说Q他l于扑ֈ了JavaServlet中文问题的Ҏ(gu)。两周以来,他一直ؓJavaServlet的中文问题所困扰Q因为每面对一个含有中文字W的字符串都必须q行强制转换才能够得到正的l果Q这好象是大家公认的唯一的解军_法)。后来,他确实不惛_此l安分下MQ因L事情实不应该是高E序员所要做的工作,他就扑ևServlet解码的源代码进行分析,因ؓ他怀疑问题就出在解码q部分。经q四个小时的奋斗Q他l于扑ֈ了问题的Ҏ(gu)所在。原来他的怀疑是正确的,Servlet的解码部分完全没有考虑双字节,直接把%XX当作一个字W。(原来JavaSoft也会犯qُ低的错误!Q 如果你对q个问题有兴或者遇C同样的烦恼的话,你可以按照他的步骤对Servlet.jar进行修改:? 扑ֈ源代码HttpUtils中的staticprivateStringparseName,在返回前sbQStringBufferQ复制成bytebs[>,然后returnnewString(bs,”GB2312?。作上述修改后就需要自p码了Q HashTableform=HttpUtils?parseQueryString(request.getQueryString())或者 form=HttpUtils.parsePostData(…?? 千万别忘了编译后攑ֈServlet.jar里面。 五、关于Java中文问题的ȝ? Java编E语a成长于网l世界,q就要求Java对多国字符有很好的支持。Java编E语a适应了计的|络化的需求,为它能够在网l世界迅速成长奠定了坚实的基。Java的~造者QJavaSoftQ已经考虑到Java编E语a对多国字W的支持Q只是现在的解决Ҏ(gu)有很多缺陷在里面Q需要我们付怸些补偿性的措施。而世界标准化l织也在努力把hcL有的文字l一在一U编码之中,其中一U方案是ISO10646,它用四个字节来表CZ个字W。当Ӟ在这U方案未被采用之前,q是希望JavaSoft能够严格地试它的产品Qؓ用户带来更多的方ѝ 附一个用于从数据库和|络中取Z文ؕ码的处理函数Q入参是有问题的字符Ԍ出参是问题已l解决了的字W串。 StringparseChinese(Stringin)? {? Strings?null;? bytetemp[>;? if?in?=null)? {? System.out.println("Warn:Chinesenullfounded!");? returnnewString("");? }? try? {? temp=in.getBytes("iso-8859-1");? s?newString(temp);? }? catch(UnsupportedEncodingExceptione)? {? System.out.println?e.toString());? }? returns;? }? ? |