??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美一区在线看,久久国产精品免费一区,国产精品4hu.wwwhttp://www.aygfsteel.com/wdlfellow/category/21227.htmlJAVA 技?/description>zh-cnMon, 16 Apr 2007 18:01:32 GMTMon, 16 Apr 2007 18:01:32 GMT60d明白Java的IOpȝ-?/title><link>http://www.aygfsteel.com/wdlfellow/archive/2007/04/13/110305.html</link><dc:creator>泡面</dc:creator><author>泡面</author><pubDate>Thu, 12 Apr 2007 16:07:00 GMT</pubDate><guid>http://www.aygfsteel.com/wdlfellow/archive/2007/04/13/110305.html</guid><wfw:comment>http://www.aygfsteel.com/wdlfellow/comments/110305.html</wfw:comment><comments>http://www.aygfsteel.com/wdlfellow/archive/2007/04/13/110305.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/wdlfellow/comments/commentRss/110305.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/wdlfellow/services/trackbacks/110305.html</trackback:ping><description><![CDATA[<p>转蝲?a ><font color=#0000ff>http://hi.baidu.com/ahunspun/blog/item/0069084e9882a0cbd0c86a66.html</font></a><br><br></p> <p><font color=#000000>一Q?Input和Output<br>1. stream代表的是M有能力出数据的数据源,或是M有能力接收数据的接收源。在Java的IO中,所有的streamQ包括Input和Out </font></p> <p><font color=#000000>streamQ都包括两种cdQ?/font></p> <p><font color=#000000>1.1 以字节ؓ导向的stream<br>以字节ؓ导向的streamQ表CZ字节为单位从stream中读取或往stream中写入信息。以字节为导向的stream包括下面几种cdQ?br>1) inputstreamQ?br>1) ByteArrayInputStreamQ把内存中的一个缓冲区作ؓInputStream使用<br>2) StringBufferInputStreamQ把一个String对象作ؓInputStream<br>3) FileInputStreamQ把一个文件作为InputStreamQ实现对文g的读取操?br>4) PipedInputStreamQ实Cpipe的概念,主要在线E中使用<br>5) SequenceInputStreamQ把多个InputStream合ƈZ个InputStream</font></p> <p><font color=#000000>2) Outputstream<br>1) ByteArrayOutputStreamQ把信息存入内存中的一个缓冲区?br>2) FileOutputStreamQ把信息存入文g?br>3) PipedOutputStreamQ实Cpipe的概念,主要在线E中使用<br>4) SequenceOutputStreamQ把多个OutStream合ƈZ个OutStream</font></p> <p><font color=#000000>1.2 以Unicode字符为导向的stream<br>以Unicode字符为导向的streamQ表CZUnicode字符为单位从stream中读取或往stream中写入信息。以Unicode字符为导向的stream包括下面?/font></p> <p><font color=#000000>U类型:<br>1) Input Stream<br>1) CharArrayReaderQ与ByteArrayInputStream对应<br>2) StringReaderQ与StringBufferInputStream对应<br>3) FileReaderQ与FileInputStream对应<br>4) PipedReaderQ与PipedInputStream对应</font></p> <p><font color=#000000>2) Out Stream<br>1) CharArrayWriteQ与ByteArrayOutputStream对应<br>2) StringWriteQ无与之对应的以字节为导向的stream<br>3) FileWriteQ与FileOutputStream对应<br>4) PipedWriteQ与PipedOutputStream对应<br>以字Wؓ导向的stream基本上对有与之相对应的以字节为导向的stream。两个对应类实现的功能相同,字是在操作时的导向不同。如</font></p> <p><font color=#000000>CharArrayReaderQ和ByteArrayInputStream的作用都是把内存中的一个缓冲区作ؓInputStream使用Q所不同的是前者每ơ从内存中读取一?/font></p> <p><font color=#000000>字节的信息,而后者每ơ从内存中读取一个字W?br>1.3 两种不现导向的stream之间的{?br>InputStreamReader和OutputStreamReaderQ把一个以字节为导向的stream转换成一个以字符为导向的stream?br>2. streamd属?br>2.1 “为streamd属?#8221;的作?br>q用上面介绍的Java中操作IO的APIQ我们就可完成我们想完成的Q何操作了。但通过FilterInputStream和FilterOutStream的子c,我们可以</font></p> <p><font color=#000000>为streamd属性。下面以一个例子来说明q种功能的作用?br>如果我们要往一个文件中写入数据Q我们可以这h作:<br>FileOutStream fs = new FileOutStream(“test.txt”);<br>然后可以通过产生的fs对象调用write()函数来往test.txt文g中写入数据了。但是,如果我们惛_?#8220;先把要写入文件的数据先缓存到内存</font></p> <p><font color=#000000>中,再把~存中的数据写入文g?#8221;的功能时Q上面的API没有一个能满我们的需求了。但是通过FilterInputStream和FilterOutStream?/font></p> <p><font color=#000000>子类QؓFileOutStreamd我们所需要的功能?br>2.2 FilterInputStream的各U类?br>2.2.1 用于装以字节ؓ导向的InputStream<br>1) DataInputStreamQ从stream中读取基本类型(int、char{)数据?br>2) BufferedInputStreamQ用缓冲区<br>3) LineNumberInputStreamQ会记录input stream内的行数Q然后可以调用getLineNumber()和setLineNumber(int)<br>4) PushbackInputStreamQ很用刎ͼ一般用于编译器开?br>2.2.2 用于装以字Wؓ导向的InputStream<br>1) 没有与DataInputStream对应的类。除非在要用readLine()时改用BufferedReaderQ否则用DataInputStream<br>2) BufferedReaderQ与BufferedInputStream对应<br>3) LineNumberReaderQ与LineNumberInputStream对应<br>4) PushBackReaderQ与PushbackInputStream对应<br>2.3 FilterOutStream的各U类?br>2.2.3 用于装以字节ؓ导向的OutputStream<br>1) DataIOutStreamQ往stream中输出基本类型(int、char{)数据?br>2) BufferedOutStreamQ用缓冲区<br>3) PrintStreamQ生格式化输出<br>2.2.4 用于装以字Wؓ导向的OutputStream<br>1) BufferedWriteQ与对应<br>2) PrintWriteQ与对应<br>3. RandomAccessFile<br>1) 可通过RandomAccessFile对象完成Ҏ件的d操作<br>2) 在生一个对象时Q可指明要打开的文件的性质QrQ只读;wQ只写;rw可读?br>3) 可以直接跛_文g中指定的位置<br>4. I/O应用的一个例?br>import java.io.*;<br>public class TestIO{<br>public static void main(String[] args)<br>throws IOException{<br>//1.以行为单位从一个文件读取数?br>BufferedReader in = <br>new BufferedReader(<br>new FileReader("F:\\nepalon\\TestIO.java"));<br>String s, s2 = new String();<br>while((s = in.readLine()) != null)<br>s2 += s + "\n";<br>in.close();</font></p> <p><font color=#000000>//1b. 接收键盘的输?br>BufferedReader stdin = <br>new BufferedReader(<br>new InputStreamReader(System.in));<br>System.out.println("Enter a line:");<br>System.out.println(stdin.readLine());</font></p> <p><font color=#000000>//2. 从一个String对象中读取数?br>StringReader in2 = new StringReader(s2);<br>int c;<br>while((c = in2.read()) != -1)<br>System.out.println((char)c);<br>in2.close();</font></p> <p><font color=#000000>//3. 从内存取出格式化输入<br>try{<br>DataInputStream in3 = <br>new DataInputStream(<br>new ByteArrayInputStream(s2.getBytes()));<br>while(true)<br>System.out.println((char)in3.readByte()); <br>}<br>catch(EOFException e){<br>System.out.println("End of stream");<br>}</font></p> <p><font color=#000000>//4. 输出到文?br>try{<br>BufferedReader in4 =<br>new BufferedReader(<br>new StringReader(s2));<br>PrintWriter out1 =<br>new PrintWriter(<br>new BufferedWriter(<br>new FileWriter("F:\\nepalon\\ TestIO.out")));<br>int lineCount = 1;<br>while((s = in4.readLine()) != null)<br>out1.println(lineCount++ + "Q? + s);<br>out1.close();<br>in4.close();<br>}<br>catch(EOFException ex){<br>System.out.println("End of stream");<br>}</font></p> <p><font color=#000000>//5. 数据的存储和恢复<br>try{<br>DataOutputStream out2 = <br>new DataOutputStream(<br>new BufferedOutputStream(<br>new FileOutputStream("F:\\nepalon\\ Data.txt")));<br>out2.writeDouble(3.1415926);<br>out2.writeChars("\nThas was pi:writeChars\n");<br>out2.writeBytes("Thas was pi:writeByte\n");<br>out2.close();<br>DataInputStream in5 =<br>new DataInputStream(<br>new BufferedInputStream(<br>new FileInputStream("F:\\nepalon\\ Data.txt")));<br>BufferedReader in5br =<br>new BufferedReader(<br>new InputStreamReader(in5));<br>System.out.println(in5.readDouble());<br>System.out.println(in5br.readLine());<br>System.out.println(in5br.readLine());<br>}<br>catch(EOFException e){<br>System.out.println("End of stream");<br>}</font></p> <p><font color=#000000>//6. 通过RandomAccessFile操作文g<br>RandomAccessFile rf =<br>new RandomAccessFile("F:\\nepalon\\ rtest.dat", "rw");<br>for(int i=0; i<10; i++)<br>rf.writeDouble(i*1.414);<br>rf.close();</font></p> <p><font color=#000000>rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "r");<br>for(int i=0; i<10; i++)<br>System.out.println("Value " + i + "Q? + rf.readDouble());<br>rf.close();</font></p> <p><font color=#000000>rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "rw");<br>rf.seek(5*8);<br>rf.writeDouble(47.0001);<br>rf.close();</font></p> <p><font color=#000000>rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "r");<br>for(int i=0; i<10; i++)<br>System.out.println("Value " + i + "Q? + rf.readDouble());<br>rf.close();<br>}<br>}<br>关于代码的解释(以区为单位)Q?br>1ZQ当d文gӞ先把文g内容d~存中,当调用in.readLine()Ӟ再从~存中以字符的方式读取数据(以下U?#8220;~存字节d?/font></p> <p><font color=#000000>?#8221;Q?br>1bZQ由于想以缓存字节读取方式从标准IOQ键盘)中读取数据,所以要先把标准IOQSystem.inQ{换成字符导向的streamQ再q行</font></p> <p><font color=#000000>BufferedReader装?br>2ZQ要以字W的形式从一个String对象中读取数据,所以要产生一个StringReadercd的stream?br>4ZQ对String对象s2d数据Ӟ先把对象中的数据存入~存中,再从~冲中进行读取;对TestIO.out文gq行操作Ӟ先把格式化后的信</font></p> <p><font color=#000000>息输出到~存中,再把~存中的信息输出到文件中?br>5ZQ对Data.txt文gq行输出Ӟ是先把基本类型的数据输出屋缓存中Q再把缓存中的数据输出到文g中;Ҏ件进行读取操作时Q先把文</font></p> <p><font color=#000000>件中的数据读取到~存中,再从~存中以基本cd的Ş式进行读取。注意in5.readDouble()q一行。因为写入第一个writeDouble()Q所以ؓ?/font></p> <p><font color=#000000>正确昄。也要以基本cd的Ş式进行读取?br>6区是通过RandomAccessFilecd文gq行操作?/font></p> <img src ="http://www.aygfsteel.com/wdlfellow/aggbug/110305.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wdlfellow/" target="_blank">泡面</a> 2007-04-13 00:07 <a href="http://www.aygfsteel.com/wdlfellow/archive/2007/04/13/110305.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 通用U程池-转自CSDNhttp://www.aygfsteel.com/wdlfellow/archive/2007/04/12/110297.html泡面泡面Thu, 12 Apr 2007 15:33:00 GMThttp://www.aygfsteel.com/wdlfellow/archive/2007/04/12/110297.htmlhttp://www.aygfsteel.com/wdlfellow/comments/110297.htmlhttp://www.aygfsteel.com/wdlfellow/archive/2007/04/12/110297.html#Feedback0http://www.aygfsteel.com/wdlfellow/comments/commentRss/110297.htmlhttp://www.aygfsteel.com/wdlfellow/services/trackbacks/110297.html阅读全文

泡面 2007-04-12 23:33 发表评论
]]>
JAVA虚拟机加载类的方式解?/title><link>http://www.aygfsteel.com/wdlfellow/archive/2007/04/11/109819.html</link><dc:creator>泡面</dc:creator><author>泡面</author><pubDate>Wed, 11 Apr 2007 01:47:00 GMT</pubDate><guid>http://www.aygfsteel.com/wdlfellow/archive/2007/04/11/109819.html</guid><wfw:comment>http://www.aygfsteel.com/wdlfellow/comments/109819.html</wfw:comment><comments>http://www.aygfsteel.com/wdlfellow/archive/2007/04/11/109819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/wdlfellow/comments/commentRss/109819.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/wdlfellow/services/trackbacks/109819.html</trackback:ping><description><![CDATA[虚拟机加载类的途径Q?br><br>1、Dog dog Q?new DogQ)Q?br>q个动作会导致常量池的解析,Dogc被隐式装蝲?br>如果当前ClassLoader无法扑ֈDogQ则抛出NoClassDefFoundError?br><br>2、Class clazz Q?Class.forNameQ?#8220;Dog”Q;<br>   Object dog Qclazz.newInstanceQ)Q?br>通过反射加蝲cdQƈ创徏对象实例<br>如果无法扑ֈDogQ则抛出ClassNotFoundException?br><br>3、Class clazz Q?classLoader.loadClassQ?#8220;Dog”Q;<br>   Object dog Qclazz.newInstanceQ)Q?br>通过反射加蝲cdQƈ创徏对象实例<br>如果无法扑ֈDogQ则抛出ClassNotFoundException?br><br>那么Q???I竟有什么区别呢Q分别用于什么情况呢Q?br><br>1?使用的类加蝲器是相同的,都是当前cd载器。(卻Ithis.getClass.getClassLoaderQ?br>3qh定类加蝲器?br><br>如果需要在当前c\径以外寻扄Q则只能采用W?U方式。第3U方式加载的cM当前cd属不同的命名I间?br>当前cd载器命名I间对其不可见。当Ӟ如果被加载类的超cd于当前类命名I间可见的话Q则可以q行强制转型?br><br>W?和第2U情况区别不大。如果,Dogcd~译时无法得刎ͼ则用第2U方式?br><br>另外Q第1U和W?U都会导致类被初始化Q即Q执行类的静态初始化语句Q而第3U情况不会?br>另外注意Q第1U抛出ErrorQ第2?U抛出ExceptionQ它们分属于不同的异?错误分支?br> <img src ="http://www.aygfsteel.com/wdlfellow/aggbug/109819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/wdlfellow/" target="_blank">泡面</a> 2007-04-11 09:47 <a href="http://www.aygfsteel.com/wdlfellow/archive/2007/04/11/109819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java字符?转自键者天?http://www.aygfsteel.com/wdlfellow/archive/2007/04/03/108287.html泡面泡面Tue, 03 Apr 2007 15:33:00 GMThttp://www.aygfsteel.com/wdlfellow/archive/2007/04/03/108287.htmlhttp://www.aygfsteel.com/wdlfellow/comments/108287.htmlhttp://www.aygfsteel.com/wdlfellow/archive/2007/04/03/108287.html#Feedback2http://www.aygfsteel.com/wdlfellow/comments/commentRss/108287.htmlhttp://www.aygfsteel.com/wdlfellow/services/trackbacks/108287.html1. 概述 

本文主要包括以下几个斚wQ编码基本知识,javaQ系lYӞurlQ工兯Y件等?nbsp;

在下面的描述中,以"中文"两个字ؓ例,l查表可以知道其GB2312~码?d6d0 cec4"QUnicode~码?4e2d 6587"QUTF~码是"e4b8ad e69687"。注意,q两个字没有iso8859-1~码Q但可以用iso8859-1~码?表示"?nbsp;

2. ~码基本知识 

最早的~码是iso8859-1Q和ascii~码怼。但Z方便表示各种各样的语aQ逐渐出现了很多标准编码,重要的有如下几个?nbsp;

2.1. iso8859-1 

属于单字节编码,最多能表示的字W范围是0-255Q应用于英文pd。比如,字母'a'的编码ؓ0x61=97?nbsp;

很明显,iso8859-1~码表示的字W范围很H,无法表示中文字符。但是,׃是单字节~码Q和计算机最基础的表C单位一_所以很多时候,仍旧使用iso8859-1~码来表C。而且在很多协议上Q默认用该~码。比如,虽然"中文"两个字不存在iso8859-1~码Q以gb2312~码ZQ应该是"d6d0 cec4"两个字符Q用iso8859-1~码的时候则它拆开?个字节来表示Q?d6 d0 ce c4"Q事实上Q在q行存储的时候,也是以字节ؓ单位处理的)。而如果是UTF~码Q则?个字?e4 b8 ad e6 96 87"。很明显Q这U表C方法还需要以另一U编码ؓ基础?nbsp;

2.2. GB2312/GBK 

q就是汉子的国标码,专门用来表示汉字Q是双字节编码,而英文字母和iso8859-1一_兼容iso8859-1~码Q。其中gbk~码能够用来同时表示J体字和体字Q而gb2312只能表示体字Qgbk是兼容gb2312~码的?nbsp;

2.3. unicode 

q是最l一的编码,可以用来表示所有语a的字W,而且是定长双字节Q也有四字节的)~码Q包括英文字母在内。所以可以说它是不兼容iso8859-1~码的,也不兼容M~码。不q,相对于iso8859-1~码来说Quniocode~码只是在前面增加了一?字节Q比如字?a'?00 61"?nbsp;

需要说明的是,定长~码便于计算机处理(注意GB2312/GBK不是定长~码Q,而unicode又可以用来表C所有字W,所以在很多软g内部是用unicode~码来处理的Q比如java?nbsp;

2.4. UTF 

考虑到unicode~码不兼容iso8859-1~码Q而且Ҏ占用更多的空_因ؓ对于英文字母Qunicode也需要两个字节来表示。所以unicode不便于传输和存储。因此而生了utf~码Qutf~码兼容iso8859-1~码Q同时也可以用来表示所有语a的字W,不过Qutf~码是不定长~码Q每一个字W的长度?-6个字节不{。另外,utf~码自带单的校验功能。一般来Ԍ英文字母都是用一个字节表C,而汉字用三个字节?nbsp;

注意Q虽然说utf是ؓ了用更的I间而用的Q但那只是相对于unicode~码来说Q如果已l知道是汉字Q则使用GB2312/GBK无疑是最节省的。不q另一斚wQ值得说明的是Q虽然utf~码Ҏ字?个字节,但即使对于汉字网,utf~码也会比unicode~码节省Q因为网中包含了很多的英文字符?nbsp;

3. java对字W的处理 

在java应用软g中,会有多处涉及到字W集~码Q有些地斚w要进行正的讄Q有些地斚w要进行一定程度的处理?nbsp;

3.1. getBytes(charset) 

q是java字符串处理的一个标准函敎ͼ其作用是字W串所表示的字W按照charset~码Qƈ以字节方式表C。注意字W串在java内存中L按unicode~码存储的。比?中文"Q正常情况下Q即没有错误的时候)存储?4e2d 6587"Q如果charset?gbk"Q则被编码ؓ"d6d0 cec4"Q然后返回字?d6 d0 ce c4"。如果charset?utf8"则最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1"Q则׃无法~码Q最后返?nbsp;"3f 3f"Q两个问P?nbsp;

3.2. new String(charset) 

q是java字符串处理的另一个标准函敎ͼ和上一个函数的作用相反Q将字节数组按照charset~码q行l合识别Q最后{换ؓunicode存储。参考上qgetBytes的例子,"gbk" ?utf8"都可以得出正的l果"4e2d 6587"Q但iso8859-1最后变成了"003f 003f"Q两个问P?nbsp;

因ؓutf8可以用来表示/~码所有字W,所以new String( str.getBytes( "utf8" ), "utf8" ) === strQ即完全可逆?nbsp;

3.3. setCharacterEncoding() 

该函数用来设|httph或者相应的~码?nbsp;

对于requestQ是指提交内容的~码Q指定后可以通过getParameter()则直接获得正的字符Ԍ如果不指定,则默认用iso8859-1~码Q需要进一步处理。参见下q?表单输入"。值得注意的是在执行setCharacterEncoding()之前Q不能执行Q何getParameter()。java doc上说明:This method must be called prior to reading request parameters or reading input using getReader()。而且Q该指定只对POSTҎ有效Q对GETҎ无效。分析原因,应该是在执行W一个getParameter()的时候,java会按照~码分析所有的提交内容Q而后l的getParameter()不再q行分析Q所以setCharacterEncoding()无效。而对于GETҎ提交表单是,提交的内容在URL中,一开始就已经按照~码分析所有的提交内容QsetCharacterEncoding()自然无效?nbsp;

对于responseQ则是指定输出内容的~码Q同Ӟ该设|会传递给览器,告诉览器输出内Ҏ采用的编码?nbsp;

3.4. 处理q程 

下面分析两个有代表性的例子Q说明java对编码有关问题的处理Ҏ?nbsp;

3.4.1. 表单输入 

User input  *(gbk:d6d0 cec4)  browser  *(gbk:d6d0 cec4)  web server  iso8859-1(00d6 00d 000ce 00c4)  classQ需要在class中进行处理:getbytes("iso8859-1")为d6 d0 ce c4Qnew String("gbk")为d6d0 cec4Q内存中以unicode~码则ؓ4e2d 6587?nbsp;

l 用户输入的编码方式和面指定的编码有养I也和用户的操作系l有养I所以是不确定的Q上例以gbkZ?nbsp;

l 从browser到web serverQ可以在表单中指定提交内Ҏ使用的字W集Q否则会使用面指定的编码。而如果在url中直接用?的方式输入参敎ͼ则其~码往往是操作系l本w的~码Q因时和面无关。上qC旧以gbk~码Z?nbsp;

l Web server接收到的是字节流Q默认时QgetParameterQ会以iso8859-1~码处理之,l果是不正确的,所以需要进行处理。但如果预先讄了编码(通过request. setCharacterEncoding ()Q,则能够直接获取到正确的结果?nbsp;

l 在页面中指定~码是个好习惯,否则可能失去控制Q无法指定正的~码?nbsp;

3.4.2. 文g~译 

假设文g是gbk~码保存的,而编译有两种~码选择Qgbk或者iso8859-1Q前者是中文windows的默认编码,后者是linux的默认编码,当然也可以在~译时指定编码?nbsp;

Jsp  *(gbk:d6d0 cec4)  java file  *(gbk:d6d0 cec4)  compiler read  uincode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  compiler write  utf(gbk: e4b8ad e69687; iso8859-1: *)  compiled file  unicode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  class。所以用gbk~码保存Q而用iso8859-1~译的结果是不正的?nbsp;

class  unicode(4e2d 6587)  system.out / jsp.out  gbk(d6d0 cec4)  os console / browser?nbsp;

l 文g可以以多U编码方式保存,中文windows下,默认为ansi/gbk?nbsp;

l ~译器读取文件时Q需要得到文件的~码Q如果未指定Q则使用pȝ默认~码。一般class文gQ是以系l默认编码保存的Q所以编译不会出问题Q但对于jsp文gQ如果在中文windows下编辑保存,而部|在英文linux下运?~译Q则会出现问题。所以需要在jsp文g中用pageEncoding指定~码?nbsp;

l Java~译的时候会转换成统一的unicode~码处理Q最后保存的时候再转换为utf~码?nbsp;

l 当系l输出字W的时候,会按指定~码输出Q对于中文windows下,System.out用gbk~码Q而对于responseQ浏览器Q,则用jsp文g头指定的contentTypeQ或者可以直接ؓresponse指定~码。同Ӟ会告诉browser|页的编码。如果未指定Q则会用iso8859-1~码。对于中文,应该为browser指定输出字符串的~码?nbsp;

l browser昄|页的时候,首先使用response中指定的~码Qjsp文g头指定的contentType最l也反映在response上)Q如果未指定Q则会用网中metaҎ定中的contentType?nbsp;

3.5. 几处讄 

对于web应用E序Q和~码有关的设|或者函数如下?nbsp;

3.5.1. jsp~译 

指定文g的存储编码,很明显,该设|应该置于文件的开头。例如:<%@page pageEncoding="GBK"%>。另外,对于一般class文gQ可以在~译的时候指定编码?nbsp;

3.5.2. jsp输出 

指定文g输出到browser是用的~码Q该讄也应该置于文件的开头。例如:<%@ page contentType="text/html; charset= GBK" %>。该讄和response.setCharacterEncoding("GBK"){效?nbsp;

3.5.3. meta讄 

指定|页使用的编码,该设|对静态网尤其有作用。因为静态网|法采用jsp的设|,而且也无法执行response.setCharacterEncoding()。例如:<META http-equiv="Content-Type" content="text/html; charset=GBK" /> 

如果同时采用了jsp输出和meta讄两种~码指定方式Q则jsp指定的优先。因为jsp指定的直接体现在response中?nbsp;

需要注意的是,apache有一个设|可以给无编码指定的|页指定~码Q该指定{同于jsp的编码指定方式,所以会覆盖静态网中的meta指定。所以有人徏议关闭该讄?nbsp;

3.5.4. form讄 

当浏览器提交表单的时候,可以指定相应的编码。例如:<form accept-charset= "gb2312">。一般不必不使用该设|,览器会直接使用|页的编码?nbsp;

4. pȝ软g 

下面讨论几个相关的系lY件?nbsp;

4.1. mysql数据?nbsp;

很明显,要支持多语言Q应该将数据库的~码讄成utf或者unicodeQ而utf更适合与存储。但是,如果中文数据中包含的英文字母很少Q其实unicode更ؓ适合?nbsp;

数据库的~码可以通过mysql的配|文件设|,例如default-character-set=utf8。还可以在数据库链接URL中设|,例如Q?nbsp;useUnicode=true&characterEncoding=UTF-8。注意这两者应该保持一_在新的sql版本里,在数据库链接URL里可以不q行讄Q但也不能是错误的设|?nbsp;

4.2. apache 

appache和编码有关的配置在httpd.conf中,例如AddDefaultCharset UTF-8。如前所qͼ该功能会所有静态页面的~码讄为UTF-8Q最好关闭该功能?nbsp;

另外Qapacheq有单独的模块来处理|页响应_其中也可能对~码q行讄?nbsp;

4.3. linux默认~码 

q里所说的linux默认~码Q是指运行时的环境变量。两个重要的环境变量是LC_ALL和LANGQ默认编码会影响到java URLEncode的行为,下面有描q?nbsp;

都设|ؓ"zh_CN.UTF-8"?nbsp;

4.4. 其它 

Z支持中文文g名,linux在加载磁盘时应该指定字符集,例如Qmount /dev/hda5 /mnt/hda5/ -t ntfs -o iocharset=gb2312?nbsp;

另外Q如前所qͼ使用GETҎ提交的信息不支持request.setCharacterEncoding()Q但可以通过tomcat的配|文件指定字W集Q在tomcat的server.xml文g中,形如Q?lt;Connector ... URIEncoding="GBK"/>。这U方法将l一讄所有请求,而不能针对具体页面进行设|,也不一定和browser使用的编码相同,所以有时候ƈ不是所期望的?nbsp;

5. URL地址 

URL地址中含有中文字W是很麻烦的Q前面描q过使用GETҎ提交表单的情况,使用GETҎӞ参数是包含在URL中?nbsp;

5.1. URL~码 

对于URL中的一些特D字W,览器会自动q行~码。这些字W除?/?&"{外Q还包括unicode字符Q比如汉子。这时的~码比较Ҏ?nbsp;

IE有一个选项"L使用UTF-8发送URL"Q当该选项有效ӞIE会对特D字W进行UTF-8~码Q同时进行URL~码。如果改选项无效Q则使用默认~码"GBK"Qƈ且不q行URL~码。但是,对于URL后面的参敎ͼ则L不进行编码,相当于UTF-8选项无效。比?中文.html?a=中文"Q当UTF-8选项有效Ӟ发送链?%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87"Q而UTF-8选项无效Ӟ发送链?\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"两个字只?个字节,而前者却?8个字节,q主要时URL~码的原因?nbsp;

当web serverQtomcatQ接收到该链接时Q将会进行URL解码Q即L"%"Q同时按照ISO8859-1~码Q上面已l描qͼ可以使用URLEncoding来设|成其它~码Q识别。上qC子的l果分别?\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"?\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87"Q注意前者前面的"中文"两个字恢复成?个字W。这里用"\u"Q表C是unicode?nbsp;

所以,׃客户端设|的不同Q相同的链接Q在服务器上得到了不同结果。这个问题不h都遇刎ͼ却没有很好的解决办法。所以有的网站会用户试关闭UTF-8选项。不q,下面会描qC个更好的处理办法?nbsp;

5.2. rewrite 

熟悉的h都知道,apache有一个功能强大的rewrite模块Q这里不描述其功能。需要说明的是该模块会自动将URL解码Q去?Q,卛_成上qweb serverQtomcatQ的部分功能。有相关文档介绍说可以用[NE]参数来关闭该功能Q但我试验ƈ未成功,可能是因为版本(我用的是apache 2.0.54Q问题。另外,当参C含有"?& "{符L时候,该功能将Dpȝ得不到正常结果?nbsp;

rewrite本ng完全是采用字节处理的方式Q而不考虑字符串的~码Q所以不会带来编码问题?nbsp;

5.3. URLEncode.encode() 

q是Java本n提供对的URL~码函数Q完成的工作和上qUTF-8选项有效时浏览器所做的工作怼。值得说明的是Qjava已经不赞成不指定~码来用该ҎQdeprecatedQ。应该在使用的时候增加编码指定?nbsp;

当不指定~码的时候,该方法用系l默认编码,q会D软gq行l果得不定。比如对?中文"Q当pȝ默认~码?gb2312"Ӟl果?%4e%2d%65%87"Q而默认编码ؓ"UTF-8"Q结果却?%e4%b8%ad%e6%96%87"Q后l程序将难以处理。另外,q儿说的pȝ默认~码是由q行tomcat时的环境变量LC_ALL和LANG{决定的Q曾l出现过tomcat重启后就出现q的问题,最后才郁闷的发现是因ؓ修改修改了这两个环境变量?nbsp;

l一指定?UTF-8"~码Q可能需要修改相应的E序?nbsp;

5.4. 一个解x?nbsp;

上面说vq,因ؓ览器设|的不同Q对于同一个链接,web server收到的是不同内容Q而Y件系l有无法知道q中间的区别Q所以这一协议目前q存在缺陗?nbsp;

针对具体问题Q不应该侥幸认ؓ所有客LIE讄都是UTF-8有效的,也不应该_暴的徏议用户修改IE讄Q要知道Q用户不可能去记住每一个web server的设|。所以,接下来的解决办法只能是让自qE序多一Ҏ能:Ҏ内容来分析编码是否UTF-8?nbsp;

比较q运的是UTF-8~码相当有规律,所以可以通过分析传输q来的链接内容,来判断是否是正确的UTF-8字符Q如果是Q则以UTF-8处理之,如果不是Q则使用客户默认~码Q比?GBK"Q,下面是一个判断是否UTF-8的例子,如果你了解相应规律,容易理解?nbsp;

public static boolean isValidUtf8(byte[] b,int aMaxCount){ 

       int lLen=b.length,lCharCount=0; 

       for(int i=0;i<lLen && lCharCount<aMaxCount;++lCharCount){ 

              byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;) 

              if(lByte>=0) continue;//>=0 is normal ascii 

              if(lByte<(byte)0xc0 || lByte>(byte)0xfd) return false; 

              int lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4 

                     :lByte>(byte)0xf0?3:lByte>(byte)0xe0?2:1; 

              if(i+lCount>lLen) return false; 

              for(int j=0;j<lCount;++j,++i) if(b[i]>=(byte)0xc0) return false; 

       } 

       return true; 



相应圎ͼ一个用上q方法的例子如下Q?nbsp;

public static String getUrlParam(String aStr,String aDefaultCharset) 

throws UnsupportedEncodingException{ 

       if(aStr==null) return null; 

       byte[] lBytes=aStr.getBytes("ISO-8859-1"); 

       return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset); 



不过Q该Ҏ也存在缺P如下两方面: 

l 没有包括对用户默认编码的识别Q这可以Ҏh信息的语a来判断,但不一定正,因ؓ我们有时候也会输入一些韩文,或者其他文字?nbsp;

l 可能会错误判断UTF-8字符Q一个例子是"学习"两个字,其GBK~码? \xd1\xa7\xcf\xb0"Q如果用上qisValidUtf8Ҏ判断Q将q回true。可以考虑使用更严格的判断ҎQ不q估计效果不大?nbsp;

有一个例子可以证明google也遇C上述问题Q而且也采用了和上q相似的处理ҎQ比如,如果在地址栏中输入"http://www.google.com/search?hl=zh-CN&newwindow=1&q=学习"Qgoogle无法正识别,而其他汉字一般能够正常识别?nbsp;

最后,应该补充说明一下,如果不用rewrite规则Q或者通过表单提交数据Q其实ƈ不一定会遇到上述问题Q因时可以在提交数据时指定希望的~码。另外,中文文g名确实会带来问题Q应该}慎用?nbsp;

6. 其它 

下面描述一些和~码有关的其他问题?nbsp;

6.1. SecureCRT 

除了览器和控制C~码有关外,一些客L也很有关pR比如在使用SecureCRTq接linuxӞ应该让SecureCRT的显C编码(不同的sessionQ可以有不同的编码设|)和linux的编码环境变量保持一致。否则看到的一些帮助信息,可能是q?nbsp;

另外Qmysql有自q~码讄Q也应该保持和SecureCRT的显C编码一致。否则通过SecureCRT执行sql语句的时候,可能无法处理中文字符Q查询结果也会出Cؕ码?nbsp;

对于Utf-8文gQ很多编辑器Q比如记事本Q会在文件开头增加三个不可见的标志字节,如果作ؓmysql的输入文Ӟ则必要Lq三个字W。(用linux的vi保存可以Lq三个字W)。一个有的现象是,在中文windows下,创徏一个新txt文gQ用C本打开Q输?q?两个字,保存Q再打开Q你会发C个字没了Q只留下一个小黑点?nbsp;

6.2. qo?nbsp;

如果需要统一讄~码Q则通过filterq行讄是个不错的选择。在filter class中,可以l一为需要的h或者回应设|编码。参加上qsetCharacterEncoding()。这个类apache已经l出了可以直接用的例子SetCharacterEncodingFilter?nbsp;

6.3. POST和GET 

很明显,以POST提交信息ӞURL有更好的可读性,而且可以方便的用setCharacterEncoding()来处理字W集问题。但GETҎ形成的URL能够更容易表辄늚实际内容Q也能够用于收藏?nbsp;

从统一的角度考虑问题Q徏议采用GETҎQ这要求在程序中获得参数是进行特D处理,而无法用setCharacterEncoding()的便利,如果不考虑rewriteQ就不存在IE的UTF-8问题Q可以考虑通过讄URIEncoding来方便获取URL中的参数?nbsp;

6.4. J体~码转换 

GBK同时包含体和J体~码Q也是说同一个字Q由于编码不同,在GBK~码下属于两个字。有时候,Z正确取得完整的结果,应该繁体和体进行统一。可以考虑UTF、GBK中的所有繁体字Q{换ؓ相应的简体字QBIG5~码的数据,也应该{化成相应的简体字。当Ӟ仍旧以UTF~码存储?nbsp;

例如Q对?语言 ?a"Q用UTF表示?\xE8\xAF\xAD\xE8\xA8\x80 \xE8\xAA\x9E\xE8\xA8\x80"Q进行简J体~码转换后应该是两个相同?nbsp;"\xE8\xAF\xAD\xE8\xA8\x80>"?nbsp;

 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1145171



泡面 2007-04-03 23:33 发表评论
]]>
վ֩ģ壺 ƽ| Դ| | | ׯ| ̨| ¡| ɽʡ| | ξ| | DZɽ| | | | ̩| | ˮ| ƺ| | | ƽ| | | ʯȪ| »| | | | | ɽ| | ۽| Ͽ| | | ˷| ij| ƽ| ľ| ̨|