Java编码问题
2015-12-13 18:53
519 查看
最近在看,How Tomcat Works,反正感觉上就是叼叼的,看完第一章就想自己写个服务器出来了,大概原理应该弄得差不多了:客户端与服务器端通讯,不管是什么B/S,C/S啊,都是在通讯,通讯就是交换信息,就像是两个人交流,你给我发消息,我给你发消息。但是因为这两个人有可能是不同地区的人,他们将不同的语言,所以制定了一系列的交流的规则,首先说什么,然后说什么,不能说什么……这就是协议,web层通讯采用的最多的就是HTTP协议,协议向下封装,什么底层透明性那些就不说了,,,反正到最后在电线中传播的都是0101010101这样的字符串了,物理上使用高低电压表示的,但是我就不知道在光缆、空气等传输介质中是怎么表示的呢,但是最后客户端、服务器端接收到的信息都是010101,就是所谓的字节流(bit),然后将这些字节流按编码(GBK、UTF-8)规则翻译***能够轻松识别的语言,就这样了。接着我的问题就来了:
问题描述:我在一个java文件中写了中文字符,并将这些字符输出到客户端,但是客户端总是显示不出来。
问题探索:我写的java文件是会保存到物理磁盘的,这样保存时会有一个编码选择,但是我的客户端访问这个程序时是访问已编译后的字节码文件啊,就是那个.class文件。我先讲java文件以UTF-8编码格式保存,然后访问那个.class文件,看客户端的输出,然后将java文件以GBK编码格式保存,再试,结果就是设置浏览器的编码为GB2312(GBK的简化版)时,我java代码中的中文能正常显示在浏览器中,浏览器的编码设置为UTF-8时,网页显示乱码,我输出的方式是直接从socket上获取的OutputStream对象,这就是字节流,就是直接将010101输出到了客户端,由客户决定采用哪种编码去显示。
我输出的中文:
其中PrintWriter是将output对象包装了一下:
output是从socket上直接获取的:
然后我发现就是java文件保存的编码格式与编译后的.class文件无关,我想是不是.class文件没有所谓的编码,,,,
哎呀,写着写着,又发现问题了,就是PrintWriter不知道有没有对中文进行编码?
反正我都试了,懒得细说了,直接用output输出,也是一样的,
最后的结论就是:java文件编译生成得.class文件是无所谓编码的,就是与java文件保存的编码格式无关。。。。但我还是不知道这是怎么实现的?
……以上结论无效,,彻底混乱啦!
-------------------------------------------------------------
更新:
结论:只与获取到socket对象的所在代码文件的编码有关,就是在该代码存在的文件中,该文件以什么格式保存,则输出到客户端的格式就是什么样的。
该测试的简化代码如下:
然后我又发现了一个问题:本来我是想加载指定目录下的class文件的,这里我想加载:"G:\HowTomcatWorks\JavaWebServer\webroot\TestServlet.class"这个类文件,可是我将这儿的文件删了,照样可以运行,因为我默认的编译路径是:"G:\HowTomcatWorks\JavaWebServer\bin\TestServlet.class",然后我又将这个文件也删了,才提示找不到类文件的错误,真搞不懂……
------------------------------------------
再分割:很复杂,上面写的也不一定对,后来又测试过,如果你看到了这里,那么也请自己测试一下,不能误导自己呀~如有误解,敬请指教,欢迎探讨!
问题描述:我在一个java文件中写了中文字符,并将这些字符输出到客户端,但是客户端总是显示不出来。
问题探索:我写的java文件是会保存到物理磁盘的,这样保存时会有一个编码选择,但是我的客户端访问这个程序时是访问已编译后的字节码文件啊,就是那个.class文件。我先讲java文件以UTF-8编码格式保存,然后访问那个.class文件,看客户端的输出,然后将java文件以GBK编码格式保存,再试,结果就是设置浏览器的编码为GB2312(GBK的简化版)时,我java代码中的中文能正常显示在浏览器中,浏览器的编码设置为UTF-8时,网页显示乱码,我输出的方式是直接从socket上获取的OutputStream对象,这就是字节流,就是直接将010101输出到了客户端,由客户决定采用哪种编码去显示。
我输出的中文:
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"> @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { System.out.println("servlet service开始执行."); PrintWriter printWriter=res.getWriter(); printWriter.println("你好,小王子~"); printWriter.print("你从哪里来的呀~"); System.out.println("haha~"); }</span></span></span>
其中PrintWriter是将output对象包装了一下:
<span style="font-size:14px;"><span style="font-size:14px;"><span style="font-size:14px;"> @Override public PrintWriter getWriter() throws IOException { printWriter=new PrintWriter(output,true); return printWriter; }</span></span></span>
output是从socket上直接获取的:
<span style="font-size:14px;"><span style="font-size:14px;">OutputStream output=socket.getOutputStream();</span></span>
然后我发现就是java文件保存的编码格式与编译后的.class文件无关,我想是不是.class文件没有所谓的编码,,,,
哎呀,写着写着,又发现问题了,就是PrintWriter不知道有没有对中文进行编码?
反正我都试了,懒得细说了,直接用output输出,也是一样的,
最后的结论就是:java文件编译生成得.class文件是无所谓编码的,就是与java文件保存的编码格式无关。。。。但我还是不知道这是怎么实现的?
……以上结论无效,,彻底混乱啦!
-------------------------------------------------------------
更新:
结论:只与获取到socket对象的所在代码文件的编码有关,就是在该代码存在的文件中,该文件以什么格式保存,则输出到客户端的格式就是什么样的。
该测试的简化代码如下:
<span style="font-size:14px;"><span style="font-size:14px;">package test; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.URL; import java.net.URLClassLoader; import java.net.URLStreamHandler; import java.net.UnknownHostException; import javax.servlet.Servlet; public class HttpServer { public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot"; private boolean shutdown = false; public static void main(String[] args) { HttpServer server = new HttpServer(); System.out.println(WEB_ROOT+"\n"); server.await(); } private void await() { ServerSocket serverSocket = null; int port = 8088; try { serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1")); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } while (!shutdown) { Socket socket = null; OutputStream output = null; Response response=null; try { socket = serverSocket.accept(); output=socket.getOutputStream(); response=new Response(output); output.write("小王子11".getBytes()); URL[] urls=new URL[1]; URLStreamHandler urlStreamHandler = null; File classPath = new File("G:\\HowTomcatWorks\\JavaWebServer\\webroot"); String repository = (new URL("file", null, classPath.getCanonicalPath() + File.separator)).toString(); System.out.println(repository); urls[0] = new URL(null, repository, urlStreamHandler); URLClassLoader loader =new URLClassLoader(urls); Class myClass = null; try { myClass = loader.loadClass("TestServlet"); Servlet servlet = (Servlet) myClass.newInstance(); servlet.service( null, response); } catch (Exception e) { e.printStackTrace(); } socket.close(); } catch (IOException e) { e.printStackTrace(); continue; } } } } </span></span>
然后我又发现了一个问题:本来我是想加载指定目录下的class文件的,这里我想加载:"G:\HowTomcatWorks\JavaWebServer\webroot\TestServlet.class"这个类文件,可是我将这儿的文件删了,照样可以运行,因为我默认的编译路径是:"G:\HowTomcatWorks\JavaWebServer\bin\TestServlet.class",然后我又将这个文件也删了,才提示找不到类文件的错误,真搞不懂……
------------------------------------------
再分割:很复杂,上面写的也不一定对,后来又测试过,如果你看到了这里,那么也请自己测试一下,不能误导自己呀~如有误解,敬请指教,欢迎探讨!
相关文章推荐
- commons之迭代器(Map、过滤、循环)_双向Map_包JAVA141
- spring支持JCP的JSR330规范,使用javax.inject
- 《java并发编程实战》随笔——第二章 线程安全性
- net.sf.json在处理json对象转换为普通java实体对象时的问题和解决方案
- Spring MVC Controller单例陷阱
- JAVA泛型学习笔记
- 《spring in action》笔记(一)
- ubuntu,jdk安装成功后,点击eclipse,提示信息A Java RunTime Environment (JRE) or Java Development Kit (JDK)
- Java IO
- Java----之“关键字”
- 圣思园java se培训总结(50)(类集的总结)
- spring MultiActionController 简单配置
- Ubuntu make 及多版本JDK安装与切换
- 浅析Java中的访问权限控制
- Java Nio 三、Java NIO Channel
- 浅谈Java中的对象和引用
- java webservice 用户验证 (服务端 + 客户端)
- java web开发 高并发处理
- java学习感悟
- spring beans源码解读