问题描述
@GET
@Path("/hello-message")
@Produces(APPLICATION_JSON)
public Response getMessage() throws Exception {
char[] array = {'h','e','l','o',2000,3000,9999};
ChararrayReader chararrayReader = new ChararrayReader(array);
int c = 0;
while ((c = chararrayReader.read()) != -1) {
System.out.println(c + " " + Integer.toBinaryString(c) + " " +(char)c);
}
return Response.status(200).entity(chararrayReader).build();
}
当上面的 REST api 被点击时,这就是打印出来的内容,
104 1101000 h
101 1100101 e
108 1101100 l
108 1101100 l
111 1101111 o
2000 ߐ 11111010000
3000 101110111000 ஸ
9999 10011100001111 ✏
显然我正在使用 Unicode(数组中的最后 3 个字符),因此,这些是物理位(仅上面的位部分),我认为将通过底层网络传输。
但是,当我收到响应时,我将其作为 InputStream 从 apache HTTP api 中获取。
class Test {
public static void main(String[] args) throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:80/hello-message");
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpGet);
InputStream inputStream = response.getEntity().getContent();
int c = -1;
while ((c = inputStream.read()) != -1) {
System.out.println(c + " " + Integer.toBinaryString(c));
}
}
}
当我遍历 InputStream 中的字节时,这是我收到的,
104 1101000
101 1100101
108 1101100
108 1101100
111 1101111
223 11011111
144 10010000
224 11100000
174 10101110
184 10111000
226 11100010
156 10011100
143 10001111
-
对于 h,e,l,o 的前 5 个字符,API 方法和我收到的响应都具有完全相同的位。
-
当超出ASCII限制时,为什么会出现下面的差异, 例如,对于 unicode 2000,
In API method it printed = 11111010000,In Response it printed = 11011111 (223) followed by 10010000 (144) which clearly doesn't matches above. I expected 11111010000 will be broken into 2 bytes like 00000111 (7) 11010000 (208),but I received something else like,223 and 114.
但是当我通读 IoUtils 库时,我得到了正确的响应,
String s = IoUtils.toString(response.getEntity().getContent(),UTF_8);
System.out.println(s);
这将打印与 API 方法返回的字符数组相同的字符串
helloߐஸ✏
这种行为有什么原因吗?流如何将碎片放回原处并形成正确的消息?
解决方法
哇!我真的打了一个很长的问题,为了在下一分钟找到答案,我折腾了一天。
这段 9 分钟的视频太棒了:https://www.youtube.com/watch?v=MijmeoH9LT4