日期:2014-05-17  浏览次数:20785 次

字节流和字符流在运行的过程中查码表的方式有什么不同
这个学期我们开了JSP课,让我们最头痛的一件事就是中文字符乱码的问题,虽然老师也给讲了,但是本人资质愚钝,依然没懂,希望能有学长指点一二,在这里谢谢了。问题是这个样子:
1
OutputStream  out=response.getOutputStream();
        out1.write("中国".getBytes());
当我用字节流向浏览器输出中文时,居然没有乱码,记得老师说过,servlet 默认指定的字符集是iso8859-1
我用的是IE浏览器,据老师讲,凡是支持中文的浏览器,都支持gb2312,那么,当我向浏览器输出汉字的话,它应该乱码才对,但是没有。我想知道为什么。
2
        PrintWriter out = response.getWriter();
out.write("中国"); 
当我用字符流向浏览器输出中国时,它果断乱码了,我搞不明白,为什么 字节流不会乱码,而字符流就乱码了。
求大神指教,谢谢了。
------最佳解决方案--------------------
看看tomcat这段源码

public ServletOutputStream getOutputStream() throws IOException
{
stream = createOutputStream();///创建response的2进制的输出流
return stream;
}

public PrintWriter getWriter() throws IOException
{
ResponseStream newStream = (ResponseStream)createOutputStream();////////创建2进制流
OutputStreamWriter osr = new OutputStreamWriter(newStream, getCharacterEncoding());
writer = new ResponseWriter(osr, newStream);///得到response的字符输出流
}

public String getCharacterEncoding()//////response的编码,默认是ISO-8859-1的
{
if(encoding == null)//////////////////////////////////如果没有指定编码
{
return "ISO-8859-1";
} else
{
return encoding;
}
}

public void setContentType(String type);设置response的类型和编码
{
encoding = RequestUtil.parseCharacterEncoding(type);////////得到指定的编码
if(encoding == null)
{
encoding = "ISO-8859-1";//////////////////////////如果沒有指定编码方式
}
 else

{
contentType = type + ";charset=" + encoding;
}
}


"中国" 转编码为iso_8859_1 肯定乱麻
------其他解决方案--------------------
response.setContentType这个方法应该知道吧,是指定输出类型的,默认是text/html
用java.net.URLEncoder类,这个是html格式网络传输文本数据时编码用的,
text/html就会把程序里需要输出的内容利用java.net.URLEncoder解析html传输时需要的格式,
如果你是用PrintWriter去输出的话,因为你没设定字符编码格式,
所以默认编码格式是iso-8859-1,
那么服务器会用URLEncoder.encode("中国", "iso-8859-1")
就是以iso-8859-1的格式去编码字符串"中国",
然后再把编码后的字符串发送给客户端浏览器,客户段浏览器是按照自己的编码格式,
比如是gbk,那么就是URLDecoder.decode(接收的字符串, "gbk")解码,
那么自然得到的就是??
而"中国".getBytes()这个得到的是一个长度为4的byte数组,
而且是用OutputStream直接发送的,不需要经过服务器编码,直接发送给客户浏览器,
客户浏览器也不需要解码,类似于得到new String("中国".getBytes(),"gbk")这样的一个字符串,
所以用outputstream输出没有出现乱码情况。
最后,以上过程只是为了理解方便才用URLEncoder和URLDecoder,
http网络传输协议的解码和编码真实过程要复杂很多,并不是这么简单。
------其他解决方案--------------------
引用:
4楼说的对,但是我如果弄不明白,心里会不舒服,再碰到类似的问题心里就慌张不知所措了,还是弄明白的好。
我把上面的代码稍微改一下,
OutputStream  out=response.getOutputStream();
         out1.write("中国".getBytes("utf-8"));
这样改的话肯定乱码了。
我还有一点不明白就是三楼学长……

你这样理解是对的,应该说string.getBytes(),
里面就是按java默认unicode进行编码而获得字节叔祖的。
out.write("中国".getBytes("utf-8"));
这个得到的流是"utf-8"编码格式的字节流,在客户端浏览器是用gbk编码格式来解码的,当然是乱码,
如果你把浏览器编码改成utf-8那么就能正确显示了,
如果还不能理解你可以输出下
System.out.println(Arrays.toString("中国".getBytes("utf-8")));
System.out.println(Arrays.toString("中国".getBytes("gbk")));
System.out.println(Arrays.toString("中国".getBytes()));
你会发现"中国".getBytes()其实和"中国".getBytes("gbk")是相等的。


------其他解决方案--------------------
简单的理解就是response.writer是以字符形