回 帖 发 新 帖 刷新版面

主题:[讨论]JAVA学习日记

本人在北京传智播客进行精英班的培训,在课余时间整理了下JAVA日记!发到这里!与大家分享!!希望可以帮助些什么!!

1. 同学的一个问题
他用javac(1.4)编译,用java(1.6)运行,出现不支持的类版本错误。我们用javac -version和java -version各看了一下版本,就发现了这个问题。然后查看path环境变量,发现他计算机上安装了oracle,oracle/bin排在了整个path的前面,调整path,让jdk1.6/bin排在最前面即可。
2. 由内存中一切皆二进制引出字符编码的讲解
大陆写的“中”到台湾显示不正常的原理分析,翻译软件的翻译原理,GBK-->“中”-->BIG5。讲解UTF-8编码和unicode编码,ASCII与Unicode码的转换规则,演示记事本显示字符时的趣味问题,分析乱码原因,GB2312码中也包含英文字符,如何识别GB2312码中的英文与汉字。最后课结束时讲了GB18030,如何支持?
3. xml文档中设置encoding属性的重要性
xml文档保存的编码类型和encoding指定的编码方式是两码事,前者表示xml文档内容的编码方式而后者是告诉解析器以什么编码方式来解析xml文档。二者必须一致,否则在浏览器中打开xml文档就会出现问题。默认情况下encoding属性的值是UTF-8。
沈继龙:以为指定了encoding="GBK",那文件就用GBK保存了,这正好理解反了。我是张,我戴顶帽子说明我是张,以便解析软件知道我是谁,如果我戴顶李的帽子,解析软件就认为我是李,显然就出了问题。
4. CDATA区
要小心的是XML文档是通过一个程序生成出来的,如下所示的一个jsp程序,对于用变量生成的信息,
要特别注意加上CDATA区。
<%@page pageEncoding="GBK"%>
<%@page contentType="text/xml;charset=UTF-8"%>
<?xml version="1.0" encoding="UTF-8"?>
<country>
        <name>中国</name>
        <info><![CDATA[${param.info}]]></info>
</country>
这个JSP文件涉及了两个编码:源文件是用什么码写的,程序执行后以什么码输出结果。
为了加深理解处理软件必须文件中的字符编码的情况,又演示了javac编译utf-8源文件的问题。
与CDATA区类似的一个小技巧:
        <%@page pageEncoding="GBK"%>
        <form>
            <input type="hidden" name="email" value="${param.email}"/>
            请输入用户名:<input type="text" name="name" />
        </form>
如果给隐藏字段传递的参数是“zxx" a="b”,那么也会出问题,对于程序生成值时,一定要考虑值的特殊情况。
5. 编码转换
编码转换程序:
        char [] codes = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        byte b = (byte)Integer.parseInt(args[0]);
        System.out.print(codes[((b>>4) & 0x0f)]);
        System.out.println(codes[(b & 0x0f)]);    
得到字符的big5码
<%@page pageEncoding="GBK"%>
<%@page contentType="text/html;charset=GBK"%>//修改contentType="audio/x-mp3"说明头的作用
<%
    String china="中一二";
    for(int i=0;i<china.length();i++)
    {
        out.println(Integer.toHexString((int)china.charAt(i)));
    }
    System.out.println();
    byte[] bufGBK = china.getBytes("GBK");
    for(int i=0;i<bufGBK.length;i++)
    {
        out.println(Integer.toHexString(bufGBK [i]));
    }
    byte[] buf = china.getBytes("Big5");
    for(int i=0;i<buf.length;i++)
    {
        out.println(Integer.toHexString(buf[i]));
    }
    byte [] buf ={0xa4, 0xa4,0xa4,0x40,0xa4,0x47}
%>
输出big5码给浏览器:
<%
    byte [] buf ={(byte)0xa4, (byte)0xa4,(byte)0xa4,(byte)0x40,(byte)0xa4,(byte)0x47};
    response.getOutputStream().write(buf);
%>
6. 区分中文英文的程序代码
buf[] = new byte[1024];
int len = System.in.read(buf);
boolean halfChinese = false;
for(int i=0;i<len;i++)
{
    if(halfChinese)
    {
        //buf[i-1] + buf[i]合并
        System.out.write('[');
        Systen.out.write(buf[i-1]);
        Systen.out.write(buf[i]);
        System.out.write(']');
        halfChinese = false;
        continue;
    }
    if((buf[i] & 0x80) == 0)
    {
        //为什么必须用write???
        System.out.write('[');
        Systen.out.write(buf[i]);
        System.out.write(']');
    }
    else
    {
        halfChinese = true;
        //等下一个,暂时不处理
        /*
        System.out.write('[');
        Systen.out.write(buf[i++]);
        Systen.out.write(buf[i]);
        System.out.write(']');
        */
    }
}
System.out.write();方法要用flush();刷新缓存,才能正常显示。
我写的代码,但还有地方没弄明白:为什么去掉了if()判断是否有'\r','\n'后,显示的结果不正常。
import java.io.*;
class TestInputChinese {
    public static void main(String[] args) {
        byte[] buf = new byte[1024];
        int len = 0;
        try {
            len = System.in.read(buf);
        }catch(IOException e) {
            e.printStackTrace();
        }
        change(buf, len);
    }
    public static void change(byte[] b, int len) {
        for( int i=0; i<len; i++ ) {
            if(b[i] == '\r' || b[i] == '\n' ) {
                continue;
            }
            if((b[i] & 0x80) == 0 ) {
                System.out.write('[');
                System.out.write(b[i]);
                System.out.write(']');
            } else {
                System.out.write('[');
                System.out.write(b[i++]);
                System.out.write(b[i]);
                System.out.write(']');
            }
        }
        System.out.flush();
    }
}

回复列表 (共23个回复)

21 楼

[size=4]培训日记(JSP乱码和out内置对象)[/size]


一、深入out对象(张老师(深入JAVA web开发内幕)书P241)
1、getOutputStream
   返回ServletOutputStream类型的out对象,属于字节输出流
2、getWriter
   返回PrintWriter类型的对象,属于字符输出流
切记:同一个servlet程序向客户端输出内容时,只能选其一使用,不可同时都用。
两种头字段
   Content-Length:n            向客户端输出前知道内容的大小
   Transfer-Encoding:chunked    以下两种情况会出现:
                                A、输出的内容刚好装满缓冲区
                                B、手工执行过刷新(flush)操作
3. 案例
案例1:实现动态文件下载
Response.setContentType("application/x-msdownload");
Response.addHeader("Content-Disposition", "attachment;filename=xx.ext");
使用两种类型的out对象都可以实现文本类型的文件下载;
但其它二进制文件只能使用ServletOutputStream类型的out对象来输出文件内容。

案例2:输出图片
Response.setContentType("image/jpeg"); //显示图片
要实现图片下载,头字段的设置还是
Response.setContentType("application/x-msdownload");
Response.addHeader("Content-Disposition”, “attachment;filename=xx.jpg");

4、JSP内置的out对象
属于JspWriter类型的对象
(1)弄清缓冲区的概念,它对out对象输出内容顺序的影响(和printwriter比较)
Printwriter先输出,out对象后输出
(2)弄清回车换行对jsp执行的影响
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
        request.getRequestDispatcher("input.html").forward(request, response);   
/*转发到静态资源会出错,因为先执行这句代码后,系统默认用outputstream输出静态页,而最后jsp的out对象最后输出换行和回车时,又要调用writer,所以会出错。
*/
       response.sendRedirect("/Test/input.html");   //不会出错
%>
下面是servlet里面的代码,不会出错
PrintWriter out = response.getWriter();
out.print("wrong!");
request.getRequestDispatcher("input.html").forward(request,response);
原因在于defaultservlet内部输出的时候会先判断是否调用过response.getWriter(),
如果已经调用过,就直接用PrintWriter来输出

二、中文输出问题
设置页面发送的编码要在定义的输出流前面
1、Servlet的中文输出问题:
response.setLocale(new java.util.Locale("zh", "CN")); //在tomcat5下无效
response.setCharacterEncoding("gb2312");//设置PrintWriter的编码
response.setContentType("text/html;charset=utf-8");//可增加Content-Type头字段

2、HTML静态页面中文输出问题:
<meta http-equiv="content-type" contentType="text/html; charset=GB18030">
注意:charset=GB18030最好和文件的编码一致

3、下载文本文件输出中文问题:
response.setContentType("application/x-msdownload;charset=gb2312");
//方法一
response.addHeader("Content-Disposition",attachment;filename=x.txt");
//response.setCharacterEncoding("gb2312");
//方法二
PrintWriter out = response.getWriter();
out.print("中国人民");

4、传参时的中文问题:
(1) get方式提交
String name = request.getParameter("name");
name = new String(name.getBytes("iso8859-1"), "gb2312");
//对get和post方式都有效,并且get方式必须用此方法
配置server.xml文件的Connector元素
    <Connector port="8080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true" />
添加两个属性
useBodyEncodingForURI="true",可以按照post方式处理
或者URIEncoding="gb2312",可以直接request.getParameter("name")而不会有问题
但不建议大家使用,因为移植到另一个服务器这些参数可能并不提供了.

(2)post方式提交
request.setCharacterEncoding("gb2312");
//只对实体内容有效,也就是只对post方式提交有效
String name = request.getParameter("name");

5、jsp文件的中文输出问题:
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
 注意这个参数很有作用,
1) 可以设置文件的编码
2) 可以设置输出内容的Content-Type
3) 修改以后文件的存储编码也跟着改变

[url=http://www.itcast.cn]北京传智播客[/url]

22 楼


                       [size=5][color=FF0000]培训日记(include和forward)[/color][/size]

一、include方法
正常
request.getRequestDispatcher("chinese.html").include(request, response);
正常
response.setContentType("text/html;charset=gb18030");
PrintWriter out = response.getWriter();
request.getRequestDispatcher("chinese.html").include(request, response);
出乱码
PrintWriter out = response.getWriter();
request.getRequestDispatcher("chinese.html").include(request, response);
因为使用了PrintWrite但没有设置编码格式,导致页面的编码方式与服务器响应的编码格式不一致。
抛出异常
response.setContentType("text/html;charset=gb18030");
request.getRequestDispatcher("chinese.html").include(request, response);
PrintWriter out = response.getWriter();
out.println("包含");
因为include方法使用的是getOutputStream方法,下面的语句又使用了getWriter()方法,而在一个servlet程序中只能有一个输出方法,所以抛异常.

二、forward方法
下面的代码导致异常发生
response.setContentType("text/html;charset=gb18030");
PrintWriter out = response.getWriter();
out.println("前");
out.flush();    //导致异常发生
request.getRequestDispatcher("chinese.html").forward(request, response);

Forward方法前后的输出都会被忽略,如下代码的"前"和"后"都不会被输出
response.setContentType("text/html;charset=gb18030");
PrintWriter out = response.getWriter();
out.println("前");
request.getRequestDispatcher("chinese.html").forward(request, response);
out.println("后");

Forward方法双方的响应头都会有效
response.addDateHeader("Expires", 0);  //设置了Expires响应头
request.getRequestDispatcher("chinese.html").forward(request, response);  
//设置了Content-Type响应头

如下代码没有问题
response.setContentType("text/html;charset=utf-8");
//response.setContentType("text/html;charset=gb18030");
PrintWriter out = response.getWriter();
request.getRequestDispatcher("chinese.html").forward(request, response);

中文显示有问题
//当前chinese.html的编码是gb18030
response.setContentType("text/html;charset=utf-8");
request.getRequestDispatcher("chinese.html").forward(request, response);

中文显示没有问题
//当前chinese.html的编码是utf-8
response.setContentType("text/html;charset=utf-8");
request.getRequestDispatcher("chinese.html").forward(request, response);

三、URL的编码问题(张老师java web开发内幕一书P361)
处理参数的servlet代码如下:
String name = request.getParameter("name");
name = new String(name.getBytes("iso8859-1"), "GB2312");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
out.println(name);
1、浏览器的地址栏直接传中文参数:没有问题
http://localhost:8080/Test/ChineseReceive?name=中国

2、通过请求转发传参:出现问题
request.getRequestDispatcher("ChineseReceive?name=中国").forward(request, response);
解决方法:
request.getRequestDispatcher("ChineseReceive?name=" + java.net.URLEncoder.encode("中国", "gb2312")).forward(request, response);
    
3、通过请求重定向传参:出现问题
response.sendRedirect("ChineseReceive?name=中国");
解决方法:
response.sendRedirect("ChineseReceive?name=" + java.net.URLEncoder.encode("中国", "gb2312"));

四、各种传递参数的表单元素
<form name="f1" id="f1" action="" method="get">
text
    name1:<input type="text" name="name" value="zhangsan"><br>
    name2:<textarea rows="5" cols="80" name="info"></textarea><br>
    checkbox
    <input type="checkbox" name="favor" value="swim">swim<br>
     <input type="checkbox" name="favor" value="read">read<br>
    radio
    <input type="radio" name="sex" value="male">male<br>
    <input type="radio" name="sex" value="female">female<br>
    hidden
    <input type="hidden" name="hid" value="iii"><br>
    select
    <select name="source" multiple>
        <option>1</option>
        <option selected>2</option>
        <option selected>3</option>
    </select><br>
    button
     <input type="button" name="btn" value="button1"><br>
      <input type="submit" name="btn" value="submit1"><br>
      <input type="submit" name="btn" value="submit2"><br>
      <input type="reset">
    </form>


[img]http://photo.store.qq.com/http_imgload.cgi?/rurl2=46675a41541a870fd43f9162c4246b274fdf458903f9caf21ebc557faadcb82617c5b5924664592bce2e9d6b8eabb4e8f5d9e897ff8518650e54ef9f12b7611fec615ad9aca101a872a2adc08ca488405690f9dd[/img][url]http://www.itcast.cn[/url]

23 楼

樓主寫的眞不錯,怎麽沒人頂啊?

我先復制下來,等我認爲我有能力看時再看。

我来回复

您尚未登录,请登录后再回复。点此登录或注册