我在php中设置一个header, 可以重现楼主的问题:
header("newheader: 中");
但因为我的php是gbk编码, 所以使用
new String(value.getBytes("ISO-8859-1"), "gbk");
可以解决问题.
下面来具体分析一下:
看HttpURLConnection的getHeaderField代码最终追到sun.net.www.MessageHeader类的mergeHeader(InputStream paramInputStream)方法,反编译可见此方法的处理过程:
//从流中每次读一个字节, 按ascii码处理,比较有用的信息:
int i = paramInputStream.read(); //读一个字节
...
Object localObject1 = new char[10];
...
localObject1[(j++)] = (char)i; //字节转为char(2字节)
...
str = String.copyValueOf(localObject1, k, j - k); //生成最后的string
...
当然代码要复杂很多了. 上面摘取的代码可以帮我们理解一下发生了什么.
所以这里也不是按iso8859-1来处理,对我的例子来说:
1. '中' gbk编码为 0xD6 0xD0;
2. 按字节处理转为unicode char后为0x00D6 0x00D0(因为char为2字节);注意java里char其实是用unicode来存储.
3. 把 0x00D6 0x00D0按gbk解码, 因为gbk和unicode不兼容, 0x00D6在gbk里是非法字符, 所以直接转为0x3f, 也就是?.
4. 把字符串 0x00D6 0x00D0按iso8859-1解码, 因为unicode兼容iso8859-1, char 0x00D6转为字节0xD6.0x00D0转为0xD0; 这样就转回到了一开始 '中' 的gbk编码
所以new String(value.getBytes("ISO-8859-1"), "gbk");可以解决上述乱码问题.