??xml version="1.0" encoding="utf-8" standalone="yes"?>
import java.io.File;
import java.util.HashMap;
import java.util.Vector;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class PraseXML extends DefaultHandler
{
private Vector<String> tagName;
private Vector<String> tagValue;
private int step;
// 开始解析XML文g
public void startDocument() throws SAXException
{
tagName = new Vector<String>();
tagValue = new Vector<String>();
step = 0;
}
// l束解析XML文g
public void endDocument() throws SAXException
{
for (int i = 0; i < tagName.size(); i++)
{
if (!tagName.get(i).equals("") || tagName.get(i) != null)
{
System.out.println("节点名称Q? + tagName.get(i));
System.out.println("节点|(x)" + tagValue.get(i));
}
}
}
/**
* 在解释到一个开始元素时?x)调用此?gu).但是当元素有重复时可以自己写法来区?
* q些重复的元?qName是什? <name:page ll=""></name:page>q样写就?x)抛出SAXException错误
* 通常情况下qName{于localName
*/
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
{
// 节点名称
tagName.add(qName);
// 循环输出属?
for (int i = 0; i < attributes.getLength(); i++)
{
// 获取属性名U?
System.out.println("属性名Uͼ(x)" + attributes.getQName(i));
// 获取属性?
System.out.println("属性|(x)"
+ attributes.getValue(attributes.getQName(i)));
}
}
/**
* 在遇到结束标{时调用此方?
*/
public void endElement(String uri, String localName, String qName)
throws SAXException
{
step = step + 1;
}
/**
* d标签里的?ch用来存放某行的xml的字W数?包括标签,初始大小?048,
* 每解释到新的字符?x)把它添加到char[]里?nbsp; * 注意,q个char字符?x)自q理存储的字符,
* q不是每一行就?x)刷Cơchar,start,length是由xml的元素数据确定的,
* 暂时找不到规?以后看源代码.
*
* q里一个正标签Q反标签都会(x)被执行一ơcharactersQ所以在反标{时不用获得其中的?
*/
public void characters(char ch[], int start, int length)
throws SAXException
{
// 只要当前的标{的长度一臻I值就不赋Q则反标{不被计划在?
if (tagName.size() - 1 == tagValue.size())
{
tagValue.add(new String(ch, start, length));
}
}
public static void main(String[] args)
{
String filename = "MyXml.xml";
SAXParserFactory spf = SAXParserFactory.newInstance();
try
{
SAXParser saxParser = spf.newSAXParser();
saxParser.parse(new File(filename), new PraseXML());
}
catch (Exception e)
{
e.printStackTrace();
}
}
public Vector getTagName()
{
return tagName;
}
public void setTagName(Vector tagName)
{
this.tagName = tagName;
}
public Vector getTagValue()
{
return tagValue;
}
public void setTagValue(Vector tagValue)
{
this.tagValue = tagValue;
}
}
属性|(x)e01
属性名Uͼ(x)enable
属性|(x)true
属性名Uͼ(x)personid
属性|(x)e02
属性名Uͼ(x)enable
属性|(x)false
属性名Uͼ(x)personid
属性|(x)e03
属性名Uͼ(x)enable
属性|(x)true
节点名称Qpeople
节点|(x)
节点名称Qperson
节点|(x)
节点名称Qname
节点|(x)张三
节点名称Qtel
节点|(x)5128
节点名称Qemail
节点|(x)txq512@sina.com
节点名称Qperson
节点|(x)
节点名称Qname
节点|(x)meixin
节点名称Qtel
节点|(x)5252525
节点名称Qemail
节点|(x)wnight88@sina.com
节点名称Qperson
节点|(x)
节点名称Qname
节点|(x)yu
节点名称Qtel
节点|(x)5389654
节点名称Qemail
节点|(x)yu@188.net
<people>
<person personid="e01" enable="true">
<name>张三</name>
<tel>5128</tel>
<email>txq512@sina.com</email>
</person>
<person personid="e02" enable="false">
<name>meixin</name>
<tel>5252525</tel>
<email>wnight88@sina.com</email>
</person>
<person personid="e03" enable="true">
<name>yu</name>
<tel>5389654</tel>
<email>yu@188.net</email>
</person>
</people>
]]>
]]>
Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);
TreeMap tree=new TreeMap(cmp);
String[] arr = {"张三", "李四", "王五"};
// 使根据指定比较器产生的顺序对指定对象数组q行排序?nbsp;
Arrays.sort(arr, cmp);
for (int i = 0; i < arr.length; i++)
System.out.println(arr[i]);
<script>
names = ["张三", "李四", "王五", "刘六"];
names.sort(function(a,b){return a.localeCompare(b)});//a,b 为数la的某两个|自动传入
alert(names);
</script>
?
String [] test = new String[] {
"作业",
"试",
"test",
"我们",
"。空",
"镂空",
"[",
"?,
"?
};
1.5.6
Eclipse 3.1
我们在应用程序中可能?x)经帔R到对中文排序的问题,例如姓名列表Q词汇表{等。对中文排序Q我们用比较多的是Ҏ(gu)汉语拼音发音来确定顺序?br />
我们可能?x)经怋?nbsp;
接口Q?
{类或方法对含有中文字符的对象进行排序,但是q些在默认情况下都是调用
Ҏ(gu)Q这个方法是比较2个字W的 codepoint valueQ如果第一个字W的值小于第二个Q则在排序结果中W一个会(x)在前面,反之亦然?/p>
其实 java 中提供了和语a相关的类Q即 Collator 接口?qing)其实现cR?
是一个具体类Q它实现?nbsp;Comparator 接口中的 compare(Object, Object) Ҏ(gu)? RuleBasedCollator Ҏ(gu)Ҏ(gu)特定语言的默认规则比较字W,也可以按照指定的规则来比较,请参?nbsp;java API 获取此类的详l信 息?br /> 如果我们需要对一个有中文的数l进行排序,则可以用这个类。请看如下示例代码:(x)
以上代码的输出结果ؓ(f)Q?br />
============
[
test
。空
试
我们
作业
?br />
镂空
?br />
大家可能?x)发现只有一部分汉字是按照汉语拼x序了Q还有几个没有?/p>
GB2312:
在简体中文中我们使用比较多的字符集是 GB2312-80Q简UCؓ(f) GB2312Q这个字W集包含了目前最常用的汉字共?nbsp;6736 个。其中的汉字分ؓ(f)两大c:(x)
常用汉字按照汉语拼音来排序,而次常用汉字按照W画部首q行排序?br />
体汉字在 Unicode 中一般是按照 gb2312 的码点值的序来放|的Q所以如果是常用汉字 java p够很准确的进行排序,但如果是ơ常用汉字,则就?x)出现问题。在以上CZ中,"?Q?? 属于ơ常用字?/p>
RuleBasedCollator c?nbsp;getRules() Ҏ(gu)可以q回对应语言的规则设|。简体中文对应的规则?nbsp;gb2312 所对应的字W?/p>
在以下的代码中,我把排过序的汉字直接作ؓ(f) String 对象攑֜c里面了Q如果要让代码变得简z一些,则可以把完整的规则(Ҏ(gu)字符Q排序汉字)存ؓ(f)文g?/p>
javac [ options ] [ sourcefiles ] [ @files ]参数可按Lơ序排列?/p>
说明
javac
有两U方法可源代码文g名传递给 javacQ?/p>
- 如果源文件数量少Q在命o(h)行上列出文g名即可?/li>
- 如果源文件数量多Q则源文g名列在一个文件中Q名U间用空格或回R行来q行分隔。然后在 javac 命o(h)行中使用该列表文件名Q文件名前冠?@ 字符?/li>
源代码文件名U必d?nbsp;
工具d?Java ~程语言~写的类和接口定义,q将它们~译成字节码cL件?/a>内部cd义生附加的cL件。这些类文g的名U将内部cd外部cȝ名称l合在一P例如
应当源文g安排在反映其包树(wi)l构的目录树(wi)中。例如,如果所有的源文件放?/workspace 中,那么
~省情况下,~译器将每个cL件与其源文g攑֜同一目录中。可?-d 选项Q请参阅后面?/a>选项Q指定其它目标目录?/a>
当编译源文gӞ~译器常帔R要它q没有识别出的类型的有关信息。对于源文g中用、扩展或实现的每个类或接口,~译器都需要其cd信息。这包括在源文g中没有明提?qing)、但通过l承提供信息的类和接口?/p>
例如Q当扩展 java.applet.Applet 时还要用?nbsp;Applet 的祖先类Q?strong>java.awt.Panel ?strong>java.awt.Container?nbsp;java.awt.Component ?nbsp;java.awt.Object?/p>
当编译器需要类型信息时Q它?yu)查扑֮义类型的源文件或cL件。编译器先在自Dcd(qing)扩展cM查找Q然后在用户c\径中查找。用L(fng)路径通过两种途径来定义:(x)通过讄 CLASSPATH 环境变量或?nbsp;-classpath 命o(h)行选项。(有关详细资料Q请参阅讄c\径)。如果?nbsp;-sourcepath 选项Q则~译器在 sourcepath 指定的\径中查找源文Ӟ否则Q编译器在用户c\径中查找cL件和源文件。可?strong>-bootclasspath ?nbsp;-extdirs 选项来指定不同的自DcL扩展c;参阅下面的联~选项?/p>
成功的类型搜索可能生成类文g、源文g或两者兼有。以下是 javac 对各U情形所q行的处理:(x)
- 搜烦l果只生成类文g而没有源文gQ?/em> javac 使用cL件?/li>
- 搜烦l果只生成源文g而没有类文gQ?/em> javac ~译源文件ƈ使用由此生成的类文g?/li>
- 搜烦l果既生成源文g又生成类文gQ?strong> 定cL件是否过时。若cL件已q时Q则 javac重新~译源文件ƈ使用更新后的cL件。否则, javac 直接使用cL件?
~省情况下,只要cL件比源文件旧Q?nbsp;javac p为它已过时。( -Xdepend 选项指定相对来说较慢但却比较可靠的过E。)
javac注意Q?nbsp;javac 可以隐式~译一些没有在命o(h)行中提及(qing)的源文g。用 -verbose 选项可跟t自动编译?/p>
为羃短或?nbsp;
@' 字符加上文g名的Ҏ(gu)它指定为文件列表。当 javac 遇到?`例如Q可以在名ؓ(f)
MyClass1.java MyClass2.java MyClass3.java
然后可用下列命o(h)q行~译器:(x)
C:> javac @sourcefiles
~译器有一Ҏ(gu)准选项Q目前的开发环境支持这些标准选项Q将来的版本也将支持它。还有一扚w加的非标准选项是目前的虚拟机实现所Ҏ(gu)的,来可能要有变化。非标准选项?nbsp;-X 打头?/p>
- -classpath c\?/em>
- 讄用户c\径,它将覆盖 CLASSPATH 环境变量中的用户c\径。若既未指定CLASSPATH 又未指定 -classpathQ则用户c\径由当前目录构成。有兌l信息,请参阅设|类路径?
若未指定 -sourcepath 选项Q则在用户c\径中查找cL件和源文件?/p>
- -d 目录
- 讄cL件的目标目录。如果某个类是一个包的组成部分,?nbsp;javac 把该类文g攑օ反映包名的子目录中,必要时创建目录。例如,如果指定 -d c:\myclasses q且该类名叫
若未指定 -d 选项Q则 javac 把cL件放C源文件相同的目录中?/p>
注意Q?nbsp;-d 选项指定的目录不?x)被自动d到用L(fng)路径中?/p>
- -deprecation
- 昄每种不鼓׃用的成员或类的用或覆盖的说明。没有给?nbsp;-deprecation 选项的话Q?nbsp;javac 显CcL文g的名Uͼ(x)q些源文件用或覆盖不鼓׃用的成员或类?/dd>
- -encoding
- 讄源文件编码名Uͼ例如
?JDK 1.2 以前的版本中Qjavac ?nbsp;-g 选项?nbsp;-O 选项不能一起用。在 JDK 1.2 中,可以?nbsp;-g ?nbsp;-O 选项l合hQ但可能?x)得到意想不到的l果Q如丢失变量或重新定位代码或丢失代码?strong>-O 选项不再自动打开 -depend 或关?nbsp;-g 选项。同P -O 选项也不再允许进行跨cd嵌?/p>
- -sourcepath 源\?/em>
- 指定用以查找cL接口定义的源代码路径。与用户c\径一P源\径项用分?(;) q行分隔Q它们可以是目录、JAR 归档文g?ZIP 归档文g。如果用包Q那么目录或归档文g中的本地路径名必d映包名?
注意Q通过c\径查扄c,如果扑ֈ了其源文Ӟ则可能会(x)自动被重新编译?/p>
- -verbose
- 冗长输出。它包括了每个所加蝲的类和每个所~译的源文g的有关信息?/dd>
~省情况下,cLҎ(gu)?nbsp;javac 一起发行的 JDK 自Dcd扩展cL~译。但 javac 也支?em>联编Q在联编中,cLҎ(gu)其它 Javaq_实现的自丄和扩展类来进行编译的。联~时Q?nbsp;-bootclasspath ?nbsp;-extdirs 的用很重要Q请参阅下面的联~程序示例?/p>
- -target 版本
- 生成在指定版本的虚拟机上运行的cL件。缺省情况下生成?1.1 ?1.2 版本的虚拟机都兼容的cL件。JDK 1.2 中的 javac 所支持的版本有Q?dl>
- 1.1
- 保证所产生的类文g?1.1 ?1.2 版的虚拟机兼宏V这是缺省状态?/dd>
- 1.2
- 生成的类文g可在 1.2 版的虚拟Zq行Q但不能?1.1 版的虚拟Zq行?/dd>
- -bootclasspath 自Dc\?/em>
- Ҏ(gu)指定的自丄集进行联~。和用户c\径一P自Dc\径项用分?(;) q行分隔Q它们可以是目录、JAR 归档文g?ZIP 归档文g?/dd>
- -extdirs 目录
- Ҏ(gu)指定的扩展目录进行联~?em>目录是以分号分隔的目录列表。在指定目录的每?JAR 归档文g中查扄文g?/dd>
- -X
- 昄非标准选项的有关信息ƈ退出?/dd>
- -Xdepend
- 递归地搜索所有可获得的类Q以L要重~译的最新源文g。该选项更可靠地查N要编译的c,但会(x)使编译进E的速度大ؓ(f)减慢?/dd>
- -Xstdout
- 编译器信息送到
注意Q?nbsp;CLASSPATH ?nbsp;-classpath ?nbsp;-bootclasspath ?nbsp;-extdirs q?nbsp;?/em> 指定用于q行 javac 的类。如此滥用编译器的实现通常没有M意义而且L很危险的。如果确实需要这样做Q可?nbsp;-J 选项选项传给基本?nbsp;java 启动器?/p>
一个源文g
C:> dir greetings/ C:> dir greetings Hello.java C:> cat greetings\Hello.java package greetings; public class Hello { public static void main(String[] args) { for (int i=0; i < args.length; i++) { System.out.println("Hello " + args[i]); } } } C:> javac greetings\Hello.java C:> dir greetings Hello.class Hello.java C:> java greetings.Hello World Universe Everyone Hello World Hello Universe Hello Everyone
该示例编?nbsp;
C:> dir greetings\ C:> dir greetings Aloha.java GutenTag.java Hello.java Hi.java C:> javac greetings\*.java C:> dir greetings Aloha.class GutenTag.class Hello.class Hi.class Aloha.java GutenTag.java Hello.java Hi.java
对前面示例中的某个源文gq行更改后,重新~译它:(x)
C:> cd \examples C:> javac greetings\Hi.java׃
C:>javac -classpath \examples \examples\greetings\Hi.java
如果再次?nbsp; 要执?nbsp;
C:>javac -classpath \examples:\lib\Banners.jar \
\examples\greetings\Hi.java
C:>java -classpath \examples:\lib\Banners.jar greetings.Hi
源文g和类文g|于不同的目录下l常是很有意义的Q特别是在大型的目中。我们用 -d 选项来指明单独的cL件目标位|。由于源文g不在用户c\径中Q所以用 -sourcepath 选项来协助编译器查找它们?/p>
C:> dir classes\ lib\ src\ C:> dir src farewells\ C:> dir src\farewells Base.java GoodBye.java C:> dir lib Banners.jar C:> dir classes C:> javac -sourcepath src -classpath classes:lib\Banners.jar \ src\farewells\GoodBye.java -d classes C:> dir classes farewells\ C:> dir classes\farewells Base.class GoodBye.class注意Q编译器也编译了
联编E序CZ
q里我们?JDK 1.2 ?nbsp;javac 来编译将?1.1 版的虚拟Zq行的代码?/p>
C:> javac -target 1.1 -bootclasspath jdk1.1.7\lib\classes.zip \ -extdirs "" OldCode.java-target 1.1
JDK 1.2 javac 在缺省状态下也将Ҏ(gu) 1.2 版的自DcLq行~译Q因此我们需要告?strong>javac
让它Ҏ(gu) JDK 1.1 自DcLq行~译。可?nbsp;-bootclasspath ?nbsp;-extdirs 选项来达到此目的。不q样做的话,可能?x)ɾ~译器根?1.2 版的 API 来进行编译。由?1.1 版的虚拟Z可能没有?1.2 版的 APIQ因此运行时出错?/p> 选项可确保生成的cL件与 1.1 版的虚拟机兼宏V在 JDK1.2 中, ~省情况?nbsp;javac ~译生成的文件是?1.1 版的虚拟机兼容的Q因此ƈ非严格地需要该选项。然而,׃别的~译器可能采用其它的~省讄Q所以提供这一选项不׃ؓ(f)是个好习(fn)惯?/blockquote>
下面的讨ZWindowsq_的Sun MicroSystem实现的java5虚拟Zؓ(f)蓝本Q其他操作系l或其他公司实现的虚拟机参数?x)有部分不同Q但大部分含义都和W(xu)indows上的cM。Java5与以前版本相比,虚拟机参数大部分保持了向前兼容,同时也增加了一些新的参敎ͼ本文对q些参数的作用作详细描述Q虚拟更符合运行环境的需要,获得更好的性能和稳定性?/p>
Java在运行已~译完成的类Ӟ是通过java虚拟机来装蝲和执行的Qjava虚拟机通过操作pȝ命o(h)JAVA_HOME\bin\java –option 来启动,-option拟机参数QJAVA_HOME为JDK安装路径Q通过q些参数可对虚拟机的q行状态进行调_(d)掌握参数的含义可对虚拟机的运行模式有更深入理解?br />
虚拟机参数分为基本和扩展两类Q在命o(h)行中输入JAVA_HOME\bin\java 可得到基本参数列表Q?br />
在命令行输入JAVA_HOME\bin\java –X 可得到扩展参数列表?br />
基本参数说明Q?br />
-clientQ?server
q两个参数用于设|虚拟机使用何种q行模式Qclient模式启动比较快,但运行时性能和内存管理效率不如server模式Q通常用于客户端应用程序。相反,server模式启动比client慢,但可获得更高的运行性能?br />
在windows上,~省的虚拟机cd为client模式Q如果要使用server模式Q就需要在启动虚拟机时?server参数Q以获得更高性能Q对服务器端应用Q推荐采用server模式Q尤其是多个CPU的系l。在LinuxQSolaris上缺省采用server模式?br />
-hotspot
含义与client相同Qjdk1.4以前使用的参敎ͼjdk1.4开始不再用,代之以client?br />
-classpath,-cp
虚拟机在q行一个类Ӟ需要将其装入内存,虚拟机搜索类的方式和序如下Q?br />
Bootstrap classesQExtension classesQUser classes?br />
Bootstrap 中的路径是虚拟机自带的jar或zip文gQ虚拟机首先搜烦q些包文Ӟ用System.getProperty("sun.boot.class.path")可得到虚拟机搜烦的包名?br />
Extension是位于jre\lib\ext目录下的jar文gQ虚拟机在搜索完Bootstrap后就搜烦该目录下的jar文g。用System. getProperty("java.ext.dirs”)可得到虚拟机使用Extension搜烦路径?br />
User classes搜烦序为当前目录、环境变?CLASSPATH?classpath?br />
-classpath告知虚拟机搜索目录名、jar文档名、zip文档名,之间用分?分隔?br />
例如当你自己开发了公共cdƈ包装成一个common.jar包,在用common.jar中的cLQ就需要用-classpath common.jar 告诉虚拟Zcommon.jar中查找该c,否则虚拟机就?x)抛出java.lang.NoClassDefFoundError异常Q表明未扑ֈcd义?br />
在运行时可用System.getProperty(“java.class.path”)得到虚拟机查扄的\径?br />
使用-classpath后虚拟机不再用CLASSPATH中的cL索\径,如果-classpath和CLASSPATH都没有设|,则虚拟机使用当前路径(.)作ؓ(f)cL索\径?br />
推荐使用-classpath来定义虚拟机要搜索的c\径,而不要用环境变量CLASSPATH的搜索\径,以减多个项目同时用CLASSPATH时存在的潜在冲突。例如应?要用a1.0.jar中的cGQ应?要用a2.0.jar中的cG,a2.0.jar是a1.0.jar的升U包Q当a1.0.jarQa2.0.jar都在CLASSPATH中,虚拟机搜索到W一个包中的cG时就停止搜烦Q如果应?应用2的虚拟机都从CLASSPATH中搜索,׃(x)有一个应用得不到正确版本的类G?br />
-D<propertyName>=value
在虚拟机的系l属性中讄属性名/值对Q运行在此虚拟机之上的应用程序可用System.getProperty(“propertyName”)得到value的倹{?br />
如果value中有I格Q则需要用双引号将该值括hQ如-Dname=”space string”?br />
该参数通常用于讄pȝU全局变量|如配|文件\径,应ؓ(f)该属性在E序中Q何地斚w可访问?br />
-verbose[:class|gc|jni]
在输备上昄虚拟行信息?br />
verbose和verbose:class含义相同Q输拟机装入的类的信息,昄的信息格式如下:(x)
[Loaded java.io.FilePermission$1 from shared objects file]
当虚拟机报告cL不到或类冲突时可用此参数来诊断来查看虚拟Z装入cȝ情况?br />
-verbose:gc在虚拟机发生内存回收时在输出讑֤昄信息Q格式如下:(x)
[Full GC 268K->168K(1984K), 0.0187390 secs]
该参数用来监视虚拟机内存回收的情c(din)?br />
-verbose:jni在虚拟机调用nativeҎ(gu)时输备显CZ息,格式如下Q?br />
[Dynamic-linking native method HelloNative.sum ... JNI]
该参数用来监视虚拟机调用本地Ҏ(gu)的情况,在发生jni错误时可断提供便利?br />
-version
昄可运行的虚拟机版本信息然后退出。一台机器上装有不同版本的JDK?br />
-showversion
昄版本信息以及(qing)帮助信息?br />
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
从JDK1.4开始,java可支持断a机制Q用于诊断运行时问题。通常在测试阶D断言有效Q在正式q行时不需要运行断a。断a后的表达式的值是一个逻辑|为true时断a不运行,为false时断aq行Q抛出java.lang.AssertionError错误?br />
上述参数q来设|虚拟机是否启动断言机制Q缺省时虚拟机关闭断a机制Q用-ea可打开断言机制Q不?lt;packagename>和classname时运行所有包和类中的断言Q如果希望只q行某些包或cM的断aQ可包名或cd加到-ea之后。例如要启动包com.foo.util中的断言Q可用命?–ea:com.foo.util ?br />
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
用来讄虚拟机关闭断a处理Qpackagename和classname的用方法和-ea相同?br />
-esa | -enablesystemassertions
讄虚拟机显C系l类的断a?br />
-dsa | -disablesystemassertions
讄虚拟机关闭系l类的断a?br />
-agentlib:<libname>[=<options>]
该参数是JDK5新引入的Q用于虚拟机装蝲本地代理库?br />
Libname为本C理库文g名,虚拟机的搜烦路径为环境变量PATH中的路径QoptionsZl本地库启动时的参数Q多个参C间用逗号分隔。在Windowsq_上虚拟机搜烦本地库名为libname.dll的文Ӟ在Unix上虚拟机搜烦本地库名为libname.so的文Ӟ搜烦路径环境变量在不同系l上有所不同QLinux、SunOS、IRIX上ؓ(f)LD_LIBRARY_PATHQAIX上ؓ(f)LIBPATHQHP-UX上ؓ(f)SHLIB_PATH?br />
例如可?agentlib:hprof来获取虚拟机的运行情况,包括CPU、内存、线E等的运行数据,q可输出到指定文件中Q可?agentlib:hprof=help来得C用帮助列表。在jre\bin目录下可发现hprof.dll文g?br />
-agentpath:<pathname>[=<options>]
讄虚拟机按全\径装载本地库Q不再搜索PATH中的路径。其他功能和agentlib相同?br />
-javaagent:<jarpath>[=<options>]
虚拟机启动时装入java语言讑֤代理。Jarpath文g中的mainfest文g必须有Agent-Class属性。代理类要实现public static void premain(String agentArgs, Instrumentation inst)Ҏ(gu)。当虚拟机初始化Ӟ按代理cȝ说明序调用premainҎ(gu)?br />
参见Qjava.lang.instrument
扩展参数说明
-Xmixed
讄-client模式虚拟机对使用频率高的方式q行Just-In-Time~译和执行,对其他方法用解释方式执行。该方式是虚拟机~省模式?br />
-Xint
讄-client模式下运行的虚拟Z解释方式执行cȝ字节码,不将字节码编译ؓ(f)本机码?br />
-Xbootclasspath:path
-Xbootclasspath/a:path
-Xbootclasspath/p:path
改变虚拟载缺省系l运行包rt.jar而从-Xbootclasspath中设定的搜烦路径中装载系l运行类。除非你自己能写一个运行时Q否则不?x)用到该参数?br />
/a:在~省搜烦路径后加上path 中的搜烦路径?br />
/p:在缺省搜索\径前先搜索path中的搜烦路径?br />
-Xnoclassgc
关闭虚拟机对class的垃圑֛收功能?br />
-Xincgc
启动增量垃圾攉器,~省是关闭的。增量垃圾收集器能减偶然发生的长时间的垃圾回收造成的暂停时间。但增量垃圾攉器和应用E序q发执行Q因此会(x)占用部分CPU在应用程序上的功能?br />
-Xloggc:<file>
虚拟机每次垃圾回收的信息写到日志文件中Q文件名由file指定Q文件格式是qxӞ内容?verbose:gc输出内容相同?br />
-Xbatch
虚拟机的~省q行方式是在后台~译cM码,然后在前台执行代码,使用-Xbatch参数关闭虚拟机后台~译Q在前台~译完成后再执行?br />
-Xms<size>
讄虚拟机可用内存堆的初始大,~省单位为字节,该大ؓ(f)1024的整数倍ƈ且要大于1MBQ可用k(K)或m(M)为单位来讄较大的内存数。初始堆大小?MB?br />
例如Q?Xms6400KQ?Xms256M
-Xmx<size>
讄虚拟机内存堆的最大可用大,~省单位为字节。该值必Mؓ(f)1024整数倍,q且要大?MB。可用k(K)或m(M)为单位来讄较大的内存数。缺省堆最大gؓ(f)64MB?br />
例如Q?Xmx81920KQ?Xmx80M
当应用程序申请了大内存运行时虚拟机抛出java.lang.OutOfMemoryError: Java heap space错误Q就需要?Xmx讄较大的可用内存堆?br />
-Xss<size>
讄U程栈的大小Q缺省单位ؓ(f)字节。与-XmxcMQ也可用K或M来设|较大的倹{通常操作pȝ分配l线E栈的缺省大ؓ(f)1MB?br />
另外也可在java中创建线E对象时讄栈的大小Q构造函数原型ؓ(f)Thread(ThreadGroup group, Runnable target, String name, long stackSize)?br />
-Xprof
输出CPUq行时的诊断信息?br />
-Xfuture
对类文gq行严格格式查,以保证类代码W合cM码规范。ؓ(f)保持向后兼容Q虚拟机~省不进行严格的格式查?br />
-Xrs
减少虚拟Z操作pȝ的信PsingalsQ的使用。该参数通常用在虚拟Z后台服务方式q行时用(如ServletQ?br />
-Xcheck:jni
调用JNI函数时进行附加的查,特别地虚拟机校验传递给JNI函数参数的合法性,在本C码中遇到非法数据Ӟ虚拟机将报一个致命错误而终止。用该参数后将造成性能下降?/p>
comet是HTTP长连接,是在HTTP发送请求时Q服务器不立d送响应信息给客户端, 而是保持着q接Q等待一定情况发生后才把数据发送回ȝ客户端。所以用comet可以实现服务器端的数据实时地发送给客户端?/p>
本文主要是用java和js来简单地实现cometQ最后附上源码和使用例子?/p>
在客L(fng)用XMLRequest发送请求到服务器,在服务器端用一个servlet来接收XMLRequest的请求,当接收到? 求时Qƈ不立d应客L(fng)Q而是把该servletU程dQ等C定事件发生后Q再响应客户端。当客户端接收到服务端的响应后,调用自定义的回调函数? 处理服务器发送回来的数据Q处理完成后Q再发送一个XMLRequesth到服务端Q这样@环下去,可以实现数据的实时更新Q又不必要在客户端不断地 轮@QpollingQ?/p>
利用该comet的实玎ͼ以后UCؓ(f)keeperQ时Q只要在客户端注册事件和写一个处理返回数据的回调函数Q然后在服务端实? keeper中的EventListener接口Q调用Controller.action(eventListener,eventType)可? 了?/p>
keeper分成两大部分Q第一部分为客L(fng)的javascript,W二部分是服务端的servlet和事件处理?/p>
一.客户?/p>
建立一个XMLRequest对象池,每发送一ơ请求,从对象池中取一个XMLRequest对象Q如果没有可用的对象Q则创徏一 个,把它加入到对象池中。这部分的代码来自于|络?/p>
Z使用方便Q再d一些方法,用来注册事g。这样只要调用注册函数来注册事gQƈ且把回调函数传给注册事g函数p了,处理数据 的事情,交给回调函数Qƈqh实现?/p>
keeperZ方便使用Q把客户端的javascript代码集成在servlet中,当配|好keeper的servletQ? 启动HTTP服务器时Qkeeper?x)根据用L(fng)配置Q在相应的目录下生成客户端的javascript代码?/p>
?服务?/p>
服务端的servlet初始化时Q根据配|来生成相应的客L(fng)javascript代码?/p>
servlet的入口由keeper.servlet.Keeper.java中的doGetq入。在Keeper的doGet 中,从请求中获取用户注册事g的名Uͼ字符串类型)Q然后根据事件的名称Q构造一个事ӞEventcdQ,再把它注册到NameRegister中,? 册完成后Q该servletU程调用wait(),把自已停止。等待该servletU程被唤醒后Q从Event中调用事件的EventListener 接口的process(request,response)来处理客L(fng)的请求?/p>
在服务端处理事gӞ调用了keeper.control.Controller中的静态方? action(EventListener listener,String eventName)来处理。如下所C?/span>
下面开始用keeper来写一个简单的|页聊天E序和基于服务端的时间?/p>
1.客户端设|?/span>
注册两个事gQ一个用于是旉事gQ一个是消息事g。同时还要写两个回调函数Q用于处理服? 端返回的旉和聊天消息。如下所于:(x)
2.配置服务?/span>
服务端的配置? web.xml文g中,如下所C?/span>
?lt;script type="text/javascript" src="./keeperScript.js"></script>在页面包含JavaScriptӞq里的src一定要和上面配 |的一臟뀂上面的讄除了<init-param></init-param>为可选的讄外,其他的都是必要的Q而且不能? 变?/p>
3.~写事g处理代码Q消息的处理代码如下Q?/span>到这Ӟ一个基本的keeper应用完成了。其它部分请参考附件中的例子源码?/p>
转蝲自:(x)http://www.regexlab.com/zh/encoding.htm
U别Q中U?/p>
摘要Q本文介l了字符与编码的发展q程Q相x늚正确理解。D例说明了一些实际应用中Q编码的实现Ҏ(gu)。然后,本文 讲述了通常对字W与~码的几U误解,׃q些误解而导致ؕ码生的原因Q以?qing)消除ؕ码的办法。本文的内容늛?#8220;中文问题”Q?#8220;q问题”?/p>
掌握~码问题的关键是正确地理解相x念,~码所涉及(qing)的技术其实是很简单的。因此,阅读本文旉要慢d惻I多思考?/p>
“字符与编?#8221;是一个被l常讨论的话题。即使这P时常出现的ؕ码仍然困扰着大家。虽然我们有很多的办法可以用来消除ؕ 码,但我们ƈ不一定理解这些办法的内在原理。而有的ؕ码生的原因Q实际上׃底层代码本n有问题所D的。因此,不仅是初学者会(x)对字W编码感到模p,? 的底层开发h员同样对字符~码~Z准确的理解?/p>
![]() |
|||
|
从计机对多国语a的支持角度看Q大致可以分Z个阶D:(x)
pȝ内码 | 说明 | pȝ | |
阶段一 | ASCII | 计算机刚开始只支持pQ其它语a不能够在计算Z存储和显C?/td> | 英文 DOS |
阶段?/td> | ANSI~码 Q本地化Q?/td> | Z计算机支持更多语aQ通常使用 0x80~0xFF 范围?2
个字节来表示 1 个字W。比如:(x)汉字 '? 在中文操作系l中Q?[0xD6,0xD0] q两个字节存储?br />
不同的国家和地区制定了不同的标准Q由此生了 GB2312, BIG5, JIS {各自的~码标准。这些?2 个字节来代表一个字W的各种汉字延~码方式Q称?strong> ANSI ~码。在体中文系l下QANSI ~码代表 GB2312 ~码Q在日文操作pȝ下,ANSI ~码代表 JIS ~码?br /> 不同 ANSI ~码之间互不兼容Q当信息在国际间交流Ӟ无法属于两U语a的文字,存储在同一D?strong> ANSI ~码的文本中?/td> | 中文 DOSQ中?Windows 95/98Q日?Windows 95/98 |
阶段?/td> | UNICODE Q国际化Q?/td> | Z使国际间信息交流更加方便Q国际组l制定了 UNICODE 字符?/strong>Q?
为各U语a中的每一个字W设定了l一q且唯一的数字编P以满语言、跨q_q行文本转换、处理的要求?/td>
Windows NT/2000/XPQLinuxQJava |
|
字符串在内存中的存放Ҏ(gu)Q?/p>
?ASCII 阶段Q?strong>单字节字W串使用一个字节存放一个字W(SBCSQ。比如,"Bob123" 在内存中为:(x)
42 | 6F | 62 | 31 | 32 | 33 | 00 |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
B | o | b | 1 | 2 | 3 | "0 |
在?ANSI ~码支持多种语言阶段Q每个字W用一个字节或多个字节来表C(MBCSQ,因此Q这U方式存攄字符也被UC多字节字W?/strong>。比如,"中文 123" 在中?Windows 95 内存中ؓ(f)7个字节,每个汉字?个字节,每个英文和数字字W占1个字节:(x)
D6 | D0 | CE | C4 | 31 | 32 | 33 | 00 |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||
?/td> | ?/td> | 1 | 2 | 3 | "0 |
?UNICODE 被采用之后,计算机存攑֭W串Ӟ改ؓ(f)存放每个字符?UNICODE 字符集中的序受目前计机一般?2 个字节(16 位)来存放一个序PDBCSQ,因此Q这U方式存攄字符也被UC宽字节字W?/strong>? 比如Q字W串 "中文123" ?Windows 2000 下,内存中实际存攄?5 个序P(x)
2D | 4E | 87 | 65 | 31 | 00 | 32 | 00 | 33 | 00 | 00 | 00 | ← ?x86 CPU 中,低字节在?/font> |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
||||||
?/td> | ?/td> | 1 | 2 | 3 | "0 |
一共占 10 个字节?/p>
![]() |
|||
|
理解~码的关键,是要把字W的概念和字节的概念理解准确。这两个概念Ҏ(gu)hQ我们在此做一下区分:(x)
概念描述 | 举例 | |
字符 | Z使用的记P抽象意义上的一个符受?/td> | '1', '?, 'a', '$', 'K?, …… |
字节 | 计算Z存储数据的单元,一?位的二进制数Q是一个很具体的存储空间?/td> | 0x01, 0x45, 0xFA, …… |
ANSI 字符?/td> | 在内存中Q如?#8220;字符”是以 ANSI ~码形式存在的,一个字W? 可能使用一个字节或多个字节来表C,那么我们U这U字W串?ANSI 字符?/strong>或?strong>多字节字W串?/td> | "中文123" Q占7字节Q?/td> |
UNICODE 字符?/td> | 在内存中Q如?#8220;字符”是以?UNICODE 中的序号存在的,那么我们U这U字W串?UNICODE 字符?/strong>或?strong>宽字节字W串?/td> | L"中文123" Q占10字节Q?/td> |
׃不同 ANSI ~码所规定的标准是不相同的Q因此,对于一个给定的多字节字W串Q我们必ȝ道它采用
的是哪一U编码规则,才能够知道它包含了哪?#8220;字符”。而对?UNICODE 字符?/strong>来说Q不在什么环境下Q它所代表?#8220;字符”内容?
是不变的?/p>
各个国家和地区所制定的不?ANSI
~码标准中,都只规定了各自语a所需?#8220;字符”。比如:(x)汉字标准QGB2312Q中没有规定韩国语字W怎样存储。这?ANSI
~码标准所规定的内容包含两层含义:(x) 各个国家和地区在制定~码标准的时候,“字符的集?#8221;?#8220;~码”一般都是同时制定的。因此,q_我们所说的“字符?#8221;Q比
如:(x)GB2312, GBK, JIS {,除了?#8220;字符的集?#8221;q层含义外,同时也包含了“~码”的含义?/p>
“UNICODE 字符?/strong>”包含了各U语a中用到的所?#8220;字符”。用来给 UNICODE
字符集编码的标准有很多种Q比如:(x)UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig {?/p>
单介l一下常用的~码规则Qؓ(f)后边的章节做一个准备。在q里Q我们根据编码规则的特点Q把所有的~码分成三类Q?/p>
我们实际上没有必要去q每一U编码具体把某一个字W编码成了哪几个字节Q我们只需要知?#8220;~码”的概念就是把“字符”?
化成“字节”可以了。对?#8220;UNICODE ~码”Q由于它们是可以通过计算得到的,因此Q在Ҏ(gu)的场合,我们可以M解某一U?#8220;UNICODE
~码”是怎样的规则?/p>
?C++ ?Java 中,用来代表“字符”?#8220;字节”的数据类型,以及(qing)q行~码的方法:(x) 以上需要注意几点:(x) 声明一D字W串帔RQ?/p>
UNICODE 字符串的 I/O 操作Q字W与字节的{换操作:(x) ?Visual C++ 中,UNICODE 字符串常量有更简单的表示Ҏ(gu)。如果源E序的编码与当前默认 ANSI
~码不符Q则需要?#pragma setlocaleQ告诉编译器源程序用的~码Q?/p>
以上需要注?#pragma setlocale ?setlocale(LC_ALL, "")
的作用是不同的,#pragma setlocale 在编译时起作用,setlocale() 在运行时起作用?/p>
字符串类 String 中的内容?UNICODE 字符Ԍ(x) 字符?I/O 操作Q字W与字节转换操作。在 Java ?java.io.*
中,?#8220;Stream”l尾的类一般是用来操作“字节?#8221;的类Q以“Reader”Q?#8220;Writer”l尾的类一般是用来操作“字符?#8221;的类?/p>
如果 java 的源E序~码与当前默?ANSI ~码不符Q则在编译的时候,需要指明一下源E序的编码。比如:(x) 以上需要注意区分源E序的编码与 I/O 操作的编码,前者是在编译时起作用,后者是在运行时起作用?/p>
W一U误解,往往是导致ؕ码生的原因。第二种误解Q往往D本来Ҏ(gu)U正的ؕ码问题变得更复杂?/p>
在这里,我们可以看到Q其中所讲的“误解一”Q即采用?#8220;一个字?#8221;是“一个字W?#8221;的{化方法,实际上也q同于采用
iso-8859-1 q行转化。因此,我们常常使用 bytes = string.getBytes("iso-8859-1")
来进行逆向操作Q得到原始的“字节?#8221;。然后再使用正确?ANSI ~码Q比?string = new String(bytes,
"GB2312")Q来得到正确?#8220;UNICODE 字符?#8221;?/p>
?UNICODE E序中的字符Ԍ都是以某U?ANSI
~码形式存在的。如果程序运行时的语a环境与开发时的语a环境不同Q将?x)导?ANSI 字符串的昄p|?/p>
比如Q在日文环境下开发的?UNICODE
的日文程序界面,拿到中文环境下运行时Q界面上显CZؕ码。如果这个日文程序界面改为采?UNICODE
来记录字W串Q那么当在中文环境下q行Ӟ界面上将可以昄正常的日文?/p>
׃客观原因Q有时候我们必d中文操作pȝ下运行非 UNICODE
的日文YӞq时我们可以采用一些工P比如Q南极星QAppLocale {,暂时的模拟不同的语言环境?/p>
当页面中的表单提交字W串Ӟ首先把字W串按照当前面的编码,转化成字节串。然后再每个字节{化成 "%XX"
的格式提交到 Web 服务器。比如,一个编码ؓ(f) GB2312 的页面,提交 "? q个字符串时Q提交给服务器的内容?"%D6%D0"?/p>
在服务器端,W(xu)eb 服务器把收到?"%D6%D0" 转化?[0xD6, 0xD0] 两个字节Q然后再Ҏ(gu)
GB2312 ~码规则得到 "? 字?/p>
?Tomcat 服务器中Qrequest.getParameter()
得到qӞ常常是因为前面提到的“误解一”造成的。默认情况下Q当提交 "%D6%D0" l?Tomcat
服务器时Qrequest.getParameter() 返?[0x00D6, 0x00D0] 两个 UNICODE 字符Q而不是返回一?
"? 字符。因此,我们需要?bytes = string.getBytes("iso-8859-1") 得到原始的字节串Q再?
string
= new String(bytes, "GB2312") 重新得到正确的字W串 "??/p>
通过数据库客L(fng)Q比?ODBC ?JDBCQ从数据库服务器中读取字W串Ӟ客户端需要从服务器获知所使用?
ANSI ~码。当数据库服务器发送字节流l客L(fng)Ӟ客户端负责将字节按照正的~码转化?UNICODE 字符丌Ӏ?/p>
如果从数据库d字符串时得到qQ而数据库中存攄数据又是正确的,那么往往q是因ؓ(f)前面提到?#8220;误解一”造成的。解?
的办法还是通过 string = new String( string.getBytes("iso-8859-1"), "GB2312")
的方法,重新得到原始的字节串Q再重新使用正确的编码{化成字符丌Ӏ?/p>
当一D?Text 或?HTML 通过?sh)子邮g传送时Q发送的内容首先通过一U指定的字符~码转化?#8220;?
节串”Q然后再?#8220;字节?#8221;通过一U指定的传输~码QContent-Transfer-EncodingQ进行{化得到另一?#8220;字节
?#8221;。比如,打开一电(sh)子邮件源代码Q可以看到类似的内容Q?/p>
最常用?Content-Transfer-Encoding ?Base64 ?
Quoted-Printable 两种。在对二q制文g或者中文文本进行{化时QBase64 得到?#8220;字节?#8221;?Quoted-Printable
更短。在对英文文本进行{化时QQuoted-Printable 得到?#8220;字节?#8221;?Base64 更短?/p>
邮g的标题,用了一U更短的格式来标?#8220;字符~码”?#8220;传输~码”。比如,标题内容?
"?Q则在邮件源代码中表CZؓ(f)Q?/p>
其中Q?/p>
如果“传输~码”改ؓ(f) Quoted-PrintableQ同P如果标题内容?"?Q?/p>
如果阅读邮g时出Cؕ码,一般是因ؓ(f)“字符~码”?#8220;传输~码”指定有误Q或者是没有指定。比如,有的发邮件组件在发送邮
件时Q标?"?Q?/p>
q样的表C,实际上是明确指明了标题ؓ(f) [0x00D6, 0x00D0]Q即 "ÖÐ"Q而不?"??/p>
非也。iso-8859-1 只是单字节字W集中最单的一U,也就?#8220;字节~号”?#8220;UNICODE
字符~号”一致的那种~码规则。当我们要把一?#8220;字节?#8221;转化?#8220;字符?#8221;Q而又不知道它是哪一U?ANSI
~码Ӟ先暂时地?#8220;每一个字?#8221;作ؓ(f)“一个字W?#8221;q行转化Q不?x)造成信息丢失。然后再使用 bytes =
string.getBytes("iso-8859-1") 的方法可恢复到原始的字节丌Ӏ?/p>
Java 中,字符串类 java.lang.String 处理的是 UNICODE 字符Ԍ不是 ANSI
字符丌Ӏ我们只需要把字符串作?#8220;抽象的符L(fng)?#8221;来看待。因此不存在字符串的内码的问题?/p>
1.3 字符集与~码
1.4 常用的编码简?/h5>
分类
~码标准
说明
单字节字W编?/td>
ISO-8859-1
最单的~码规则Q每一个字节直接作Z?UNICODE
字符。比如,[0xD6, 0xD0] q两个字节,通过 iso-8859-1 转化为字W串Ӟ直接得?[0x00D6, 0x00D0] 两个
UNICODE 字符Q即 "ÖÐ"?br />
反之Q将 UNICODE 字符串通过 iso-8859-1 转化为字节串Ӟ只能正常转化 0~255
范围的字W?/td>
ANSI ~码
GB2312,
BIG5,
Shift_JIS,
ISO-8859-2 ……?UNICODE 字符串通过 ANSI
~码转化?#8220;字节?#8221;ӞҎ(gu)各自~码的规定,一?UNICODE 字符可能转化成一个字节或多个字节?br />
反之Q将字节串{化成字符串时Q也可能多个字节转化成一个字W。比如,[0xD6, 0xD0] q两个字节,通过
GB2312 转化为字W串Ӟ得?[0x4E2D] 一个字W,?'? 字?br />
“ANSI ~码”的特点:(x)
1. q些“ANSI ~码标准”都只能处理各自语a范围之内?UNICODE 字符?br />
2. “UNICODE 字符”?#8220;转换出来的字?#8221;之间的关pLZؓ(f)规定的?/td>
UNICODE
~码
UTF-8,
UTF-16, UnicodeBig ……?#8220;ANSI ~码”cM的,把字W串通过 UNICODE
~码转化?#8220;字节?#8221;Ӟ一?UNICODE 字符可能转化成一个字节或多个字节?br />
?#8220;ANSI ~码”不同的是Q?br />
1. q些“UNICODE ~码”能够处理所有的 UNICODE 字符?br />
2. “UNICODE 字符”?#8220;转换出来的字?#8221;之间是可以通过计算得到的?/td>
2. 字符与编码在E序中的实现
2.1 E序中的字符与字?/h5>
cd或操?/strong>
C++
Java
字符
wchar_t
char
字节
char
byte
ANSI
字符?/td>
char[]
byte[]
UNICODE
字符?/td>
wchar_t[]
String
字节?#8594;字符?/td>
mbstowcs(), MultiByteToWideChar()
string = new String(bytes, "encoding")
字符?#8594;字节?/td>
wcstombs(), WideCharToMultiByte()
bytes = string.getBytes("encoding")
2.2 C++ 中相兛_现方?/h5>
// ANSI 字符Ԍ内容长度 7 字节
char sz[20] = "中文123";
// UNICODE 字符Ԍ内容长度 5 ?wchar_tQ?0 字节Q?br />
wchar_t wsz[20] = L""x4E2D"x6587"x0031"x0032"x0033";
// q行时设定当?ANSI ~码QVC
格式
setlocale(LC_ALL, ".936");
// GCC 中格?br />
setlocale(LC_ALL, "zh_CN.GBK");
// Visual C++ 中用小?%sQ按?setlocale
指定~码输出到文?br />
// GCC 中用大?%S
fwprintf(fp, L"%s"n", wsz);
// ?UNICODE 字符串按?setlocale
指定的编码{换成字节
wcstombs(sz, wsz, 20);
// 把字节串按照 setlocale 指定的编码{换成 UNICODE 字符?br />
mbstowcs(wsz, sz, 20);
// 如果源程序的~码与当前默?ANSI
~码不一_(d)
// 则需要此行,~译时用来指明当前源E序使用的编?/span>
#pragma setlocale(".936")
// UNICODE 字符串常量,内容长度 10 字节
wchar_t wsz[20] = L"中文123";
2.3 Java 中相兛_现方?/h5>
// Java 代码Q直接写中文
String string = "中文123";
// 得到长度?5Q因为是 5 个字W?br />
System.out.println(string.length());
// 字符串与字节串间怺转化
// 按照 GB2312 得到字节Q得到多字节字符Ԍ
byte [] bytes = string.getBytes("GB2312");
// 从字节按?GB2312 得到 UNICODE 字符?br />
string = new String(bytes,
"GB2312");
// 要将 String 按照某种~码写入文本文gQ有两种Ҏ(gu)Q?br />
// W一U办法:(x)?Stream cd入已l按照指定编码{化好的字节串
OutputStream os = new
FileOutputStream("1.txt");
os.write(bytes);
os.close();
// W二U办法:(x)构造指定编码的 Writer 来写入字W串
Writer ow = new
OutputStreamWriter(new FileOutputStream("2.txt"), "GB2312");
ow.write(string);
ow.close();
/* 最后得到的 1.txt ?2.txt 都是 7 个字?*/
E:">javac -encoding
BIG5 Hello.java
3. 几种误解Q以?qing)ؕ码生的原因和解军_?/h4>
3.1 Ҏ(gu)产生的误?/h5>
对编码的误解
误解一
在将“字节?#8221;转化?#8220;UNICODE
字符?#8221;Ӟ比如在读取文本文件时Q或者通过|络传输文本ӞҎ(gu)?#8220;字节?#8221;单地作ؓ(f)单字节字W串Q采用每“一个字?#8221;是“一个字
W?#8221;的方法进行{化?br />
而实际上Q在非英文的环境中,应该?#8220;字节?#8221;作ؓ(f) ANSI 字符Ԍ采用适当的编码来得到 UNICODE
字符Ԍ有可?#8220;多个字节”才能得到“一个字W?#8221;?br />
通常Q一直在英文环境下做开发的E序员们Q容易有q种误解?/td>
误解?/td>
?DOSQW(xu)indows 98 {非 UNICODE 环境下,字符串都是以
ANSI ~码的字节Ş式存在的。这U以字节形式存在的字W串Q必ȝ道是哪种~码才能被正地使用。这使我们Ş成了一个惯性思维Q?#8220;字符串的~码”?br />
?UNICODE 被支持后QJava 中的 String
是以字符?#8220;序号”来存储的Q不是以“某种~码的字?#8221;来存储的Q因此已l不存在“字符串的~码”q个概念了。只有在“字符?#8221;?#8220;字节?#8221;转化Ӟ?
者,一?#8220;字节?#8221;当成一?ANSI 字符串时Q才有编码的概念?br />
不少的h都有q个误解?/td>
3.2 ?UNICODE E序在不同语a环境间移植时的ؕ?/h5>
3.3 |页提交字符?/h5>
3.4 从数据库d字符?/h5>
3.5 ?sh)子邮g中的字符?/h5>
Content-Type: text/plain;
charset="gb2312"
Content-Transfer-Encoding: base64
sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==
// 正确的标题格?br />
Subject: =?GB2312?B?1tA=?=
// 正确的标题格?br />
Subject: =?GB2312?Q?=D6=D0?=
// 错误的标题格?br />
Subject: =?ISO-8859-1?Q?=D6=D0?=
4. 几种错误理解的纠?/h4>
误解Q?#8220;ISO-8859-1 是国际编码?”
误解Q?#8220;Java 中,怎样知道某个字符串的内码Q?#8221;
标签Q?a class="tag" target="_blank">杂谈 |
分类Q?a >计算?/a> |
通常我们的做法是Q尤其是在学?fn)阶D)Q定义一个新的变量,借助它完成交换。代码如下:(x)
int a,b; a=10; b=15; int t; t=a; a=b; b=t; q种法易于理解Q特别适合帮助初学者了解计机E序的特点,是赋D句的l典应用。在实际软g开发当中,此算法简单明了,不会(x)产生歧义Q便于程序员之间的交,一般情况下到交换变量值的问题Q都应采用此法Q以下称为标准算法)?br /> 上面的算法最大的~点是需要借助一个(f)时变量。那么不借助临时变量可以实现交换吗?{案是肯定的Q这里我们可以用三种法来实玎ͼ(x)1Q算术运;2Q指针地址操作Q?Q位q算?br /> 1Q?术q算 单来_(d)是通过普通的+?q算来实现。代码如下:(x) int a,b; a=10;b=12; a=b-a; //a=2;b=12 b=b-a; //a=2;b=10 a=b+a; //a=10;b=10 通过以上q算Qa和b中的值就q行了交换。表面上看v来很单,但是不容易想刎ͼ其是在?fn)惯标准法之后?br /> 它的原理是:(x)把a、b看做数u上的点,围绕两点间的距离来进行计?br /> 具体q程Q第一?#8220;a=b-a”求出ab两点的距,q且其保存在a中;W二?#8220;b=b-a”求出a到原点的距离Qb到原点的距离与ab两点距离之差Q,q且其保存在b中;W三?#8220;a=b+a”求出b到原点的距离Qa到原点距Mab两点距离之和Q,q且其保存在a中。完成交换?br /> 此算法与标准法相比Q多了三个计的q程Q但是没有借助临时变量。(以下UCؓ(f)术法Q?br /> 2Q?指针地址操作 因ؓ(f)对地址的操作实际上q行的是整数q算Q比如:(x)两个地址相减得到一个整敎ͼ表示两个变量在内存中的储存位|隔了多个字节Q地址和一个整数相加即“a+10”表示以a为基地址的在a?0个acL据单元的地址。所以理Z可以通过和算术算法类似的q算来完成地址的交换,从而达C换变量的目的。即Q?br /> int *a,*b; //假设 *a=new int(10); *b=new int(20); //&a=0x00001000h,&b=0x00001200h a=(int*)(b-a); //&a=0x00000200h,&b=0x00001200h b=(int*)(b-a); //&a=0x00000200h,&b=0x00001000h a=(int*)(b+int(a)); //&a=0x00001200h,&b=0x00001000h 通过以上q算a、b的地址真的已经完成了交换,且a指向了原先b指向的|b指向原先a指向的g吗?上面的代码可以通过~译Q但是执行结果却令h匪夷所思!原因何在Q?br /> 首先必须了解Q操作系l把内存分ؓ(f)几个区域Q系l代?数据区、应用程序代?数据区、堆栈区、全局数据区等{。在~译源程序时Q常量、全局变量{都攑օ全局数据区,局部变量、动态变量则攑օ堆栈区。这样当法执行?#8220;a=(int*)(b-a)”Ӟa的值ƈ不是0x00000200hQ而是要加上变量a所在内存区的基地址Q实际的l果是:(x)0x008f0200hQ其?x008f即ؓ(f)基地址Q?200即ؓ(f)a在该内存区的位移。它是由~译器自动添加的。因此导致以后的地址计算均不正确Q得a,b指向所在区的其他内存单元。再ơ,地址q算不能出现负数Q即当a的地址大于b的地址Ӟb-a<0Q系l自动采用补码的形式表示负的位移Q由此会(x)产生错误Q导致与前面同样的结果?br /> 有办法解军_Q当Ӟ以下是改q的法Q?br /> if(a<b) { a=(int*)(b-a); b=(int*)(b-(int(a)&0x0000ffff)); a=(int*)(b+(int(a)&0x0000ffff)); } else { b=(int*)(a-b); a=(int*)(a-(int(b)&0x0000ffff)); b=(int*)(a+(int(b)&0x0000ffff)); } 法做的最大改q就是采用位q算中的与运?#8220;int(a)&0x0000ffff”Q因为地址中高16位ؓ(f)D地址Q后16位ؓ(f)位移地址Q将它和0x0000ffffq行与运后Q段地址被屏蔽,只保留位Ud址。这样就原始法dQ从而得到正的l果?br /> 此算法同h有用第三变量就完成了值的交换Q与术法比较它显得不好理解,但是它有它的优点卛_交换很大的数据类型时Q它的执行速度比算术算法快。因为它交换的时地址Q而变量值在内存中是没有Udq的。(以下UCؓ(f)地址法Q?br /> 3Q?位运?br /> 通过异或q算也能实现变量的交换,q也许是最为神奇的Q请看以下代码:(x) int a=10,b=12; //a=1010^b=1100; a=a^b; //a=0110^b=1100; b=a^b; //a=0110^b=1010; a=a^b; //a=1100=12;b=1010; 此算法能够实现是由异或运的特点军_的,通过异或q算能够使数据中的某些位{Q其他位不变。这意味着L一个数与Q意一个给定的Dl异或两ơ,g变?br /> 卻I(x)a^b^b=a。将a=a^b代入b=a^b则得b=a^b^b=a;同理可以得到a=b^a^a=b;L完成交换?br /> 以上三个法均实C不借助其他变量来完成两个变量值的交换Q相比较而言术法和位法计算量相当,地址法中计较复杂Q却可以很轻杄实现大类型(比如自定义的cLl构Q的交换Q而前两种只能q行整Ş数据的交换(理论上重?#8220;^”q算W,也可以实CQ意结构的交换Q?br /> 介绍q三U算法ƈ不是要应用到实践当中Q而是Z探讨技术,展示E序设计的魅力。从中可以看出,数学中的技巧对E序设计而言h相当的媄响力Q运用得当会(x)有意想不到的奇效果。而从实际的Y件开发看Q标准算法无疑是最好的Q能够解决Q意类型的交换问题 |