最近用到了字符串的压缩用到了GZipInputStream和GZipOutputStream再次遇到了阔别已久的中文乱码问题
看了一些相关的文章觉得我们之所以会遇到这样那样的乱码问题基本上都是由于我们在某些地方隐含了byte到char的转换而这种隐含的转换采用的是iso的编码进行的
以jsp页面中文传递为例子假设客户端的编码是GB表单中的中文提交后首先根据GB编码转换为字节流到达服务器端后如果我们直接在servlet中调用requestgetParameter(String name)等方法由于方法返回的是String 对象所以其中必然隐含了一次从byte到char的转换错误也就是在这里产生的如果这次转换采用的编码是iso得到的当然是乱码
public class Login
extends HttpServlet {
private static final String CONTENT_TYPE = text/html; charset=UTF;
//Initialize global variables
public void init() throws ServletException {
}
//Process the HTTP Get request
public void doGet(HttpServletRequest request HttpServletResponse response) throws
ServletException IOException {
String name = requestgetParameter(userid);//隐含的转换
name = new String(namegetBytes(iso) GB);//还原字节重新构造
responsesetContentType(CONTENT_TYPE);
PrintWriter out = responsegetWriter();
outprintln(<html>);
outprintln(<head><title>Login</title></head>);
outprintln(<body bgcolor=\#ffffff\>);
outprintln(<p>The servlet has received a GET This is the reply</p>);
outprintln(</body>);
outprintln(</html>);
outclose();
}
}
幸好以iso进行的默认转换不会损失字节也不会增加字节我们只要按照iso的方式返回原来的字节数组重新按照GB的方式进行byte 到char的转换就可以了
再以压缩流为例(文件流实际上也是一样的)
public String uncompress(byte[] cmp) {
String ret = ;
int i;
byte[] buf = new byte[];
try {
/**
*新的方式始终保持以字节为核心最后再按照合适的编码进行组装
*/
BufferedInputStream bis = new BufferedInputStream(new GZIPInputStream(new
ByteArrayInputStream(cmp)));
/**
* 以前的方式
* 在 new InputStreamReader()的时候发生了隐含的byte到char的转换导致之后出来的都是乱码
*/
//BufferedReader bis = new BufferedReader(new InputStreamReader(new
//GZIPInputStream(new
//ByteArrayInputStream(cmp))));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
while ( (i = bisread(buf)) > ) {
boswrite(buf i);
}
bosclose();
baosclose();
bisclose();
ret = new String(baostoByteArray());//用平台默认的编码进行组装我是GB
}
catch (IOException ex) {
exprintStackTrace();
}
return ret;
}
reader是以字符为核心inputStream是以byte为核心的当他们转换的时候就会进行byte到char的转换所以我们要注意自己的调用的顺序
我们如果今后再遇到乱码的问题就去找找自己是不是什么地方进行了隐含的byte到char的转换