您的位置:首页 > 编程语言 > Java开发

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输出到了客户端,由客户决定采用哪种编码去显示。

我输出的中文:

<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",然后我又将这个文件也删了,才提示找不到类文件的错误,真搞不懂……

------------------------------------------

再分割:很复杂,上面写的也不一定对,后来又测试过,如果你看到了这里,那么也请自己测试一下,不能误导自己呀~如有误解,敬请指教,欢迎探讨!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: