本文介绍了来自API的奇怪字符串的java字符编码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我遇到了来自 API 的响应的奇怪问题.我正在使用 apache HTTP 客户端来获得响应.响应头有以下内容Content-Type=[application/json;字符集=utf-16]传输编码=[分块]X-Powered-By=[ASP.NET]//是的,人们使用 ASP.NET因此基于此,当我收到回复时,我的回复如下代码>笀∀异琀愀琀甀猀䌀漀跨攀∀㨀㈀所以我尝试了以下方法.String body = "笀∀异琀愀琀甀猀䌀漀我攀∀㨀㈀";String charSetString = "utf-8|utf-16|utf-16le,所有可能的组合"body = new String(body.getBytes(Charset.forName(charSetString));body = body.replaceAll("[^\\x00-\\x7F]", "");但没有运气.开始看第一个字符.第一个字符中的实际响应是 { 我将第一个字符从响应转换为 ascii(int)body.charAt(0)值为31488;而 { 的 Ascii 值为 123;如果我执行 31488/256 = 123 并将其转换为 char 给我 { 所以我做了以下操作字符串编码 = "";for(int i=0; i它奏效了.但是对于单个 API 来说,这是非常糟糕的对话.我缺少什么,如果我为 { 获得 31488 响应的字符集到底是什么更新我的 API 调用代码.import java.io.FileNotFoundException;导入 java.io.FileOutputStream;导入 java.io.IOException;导入 java.nio.charset.Charset;导入 java.util.LinkedHashMap;导入 java.util.Map;导入 org.apache.http.impl.client.HttpClientBuilder;导入 org.springframework.http.HttpEntity;导入 org.springframework.http.HttpHeaders;导入 org.springframework.http.HttpMethod;导入 org.springframework.http.ResponseEntity;导入 org.springframework.http.client.HttpComponentsClientHttpRequestFactory;导入 org.springframework.util.SerializationUtils;导入 org.springframework.web.client.RestTemplate;公共类 HTTPClientManager {RestTemplate restTemplate = null;公共无效设置(){HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = null;clientHttpRequestFactory = 新的 HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build());clientHttpRequestFactory.setReadTimeout(5 * 1000);clientHttpRequestFactory.setConnectTimeout(5 * 1000);restTemplate = new RestTemplate(clientHttpRequestFactory);}public static void main(String...strings) 抛出 FileNotFoundException, IOException {HTTPClientManager ht = new HTTPClientManager();ht.setup();映射properties = new LinkedHashMap();properties.put(Const.METHOD, "GET");properties.put(Const.URL,strings[0]);properties.put(Const.CHAR_SET, "UTF-16LE");映射ob = ht.getResponse(属性);尝试 {String res = ob.get(Const.RESPONSE).toString();System.out.println("响应->>>>>>>>>\n" + res);}catch(异常e){e.printStackTrace();}尝试(FileOutputStream fos = new FileOutputStream(响应")){fos.write(SerializationUtils.serialize(ob));}}公共静态类 Const {public static final String REQUEST = "request";public static final String URL = "url";public static final String CHAR_SET = "charSet";public static final String RESPONSE =响应";公共静态最终字符串方法 =方法";public static final String REQUEST_HEADER = "reqHeader";public static final String RESPONSE_HEADER = "resHeader";}公共地图getResponse(Map 属性) {HttpHeaders headers = new HttpHeaders();HttpEntity requestEntity = null;映射responseReturn = new LinkedHashMap();HttpMethod 方法 = null;if (properties.get(Const.METHOD).toString().equals("GET")) {方法 = HttpMethod.GET;requestEntity = new HttpEntity("", headers);} else if (properties.get(Const.METHOD).toString().equals("POST")) {方法 = HttpMethod.POST;requestEntity = new HttpEntity(properties.get(Const.REQUEST).toString(), headers);}else if (properties.get(Const.METHOD).toString().equals("PUT")) {方法 = HttpMethod.PUT;requestEntity = new HttpEntity(properties.get(Const.REQUEST).toString(), headers);}else if (properties.get(Const.METHOD).toString().equals("DELETE")) {方法 = HttpMethod.DELETE;requestEntity = new HttpEntity(properties.get(Const.REQUEST).toString(), headers);}ResponseEntity响应 = 空;尝试 {response = restTemplate.exchange(properties.get(Const.URL).toString(), method, requestEntity, String.class);String body = response.getBody();if(properties.get(Const.CHAR_SET) != null) {尝试 {body = new String(body.getBytes(Charset.forName(properties.get(Const.CHAR_SET).toString())));body = body.replaceAll("[^\\x00-\\x7F]", "");}catch(异常e){e.printStackTrace();}}responseReturn.put(Const.RESPONSE, body!=null?body:"");responseReturn.put(Const.RESPONSE_HEADER, response.getHeaders());} catch (org.springframework.web.client.HttpClientErrorException |org.springframework.web.client.HttpServerErrorException 异常) {异常.printStackTrace();}catch(org.springframework.web.client.ResourceAccessException 异常){异常.printStackTrace();}catch(异常异常){异常.printStackTrace();}返回响应返回;}} 解决方案 我认为您的问题在于您错误地假设您的回复采用 UTF-16 格式,即您的行 Content-Type=[application/json;charset=utf-16] 是错误的.尝试删除字符集部分 (Content-Type=[application/json]) 或将其设置为 UTF-8 (Content-Type=[application/json; charset=utf-8]) 看看会发生什么.我相信您得到的答复是:{"StatusCode":2.不知道为什么回复最后似乎缺少}",但除此之外它是有道理的.顺便说一句,我设法通过将您的回复字符串转换为 unicode 序列来解释您的回复.这给了我序列:\u7b00\u2200\u5300\u7400\u6100\u7400\u7500\u7300\u4300\u6f00\u6400\u6500\u2200\u3a00\u30030.这给出了这样的想法:通过强制将响应解释为 utf-16,您会弄乱内容.因此,如果我将序列更改为 \u007b\u0022\u0053\u0074\u0061\u0074\u0075\u0073\u0043\u006f\u0064\u0065\u0022\u003a\u0从 unicodes 我得到了 {"StatusCode":2.顺便说一句,如果您对将任何字符串转换为 unicode 序列和反之亦然的工具感兴趣,那么您可以使用 MgntUtils 开源库(由我编写).我所要做的就是转换您的响应字符串:String result = "笀∀异琀愀琀甀猀䌀漀我攀∀㨀㈀";result = StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence(result);System.out.println(结果);这是链接 到描述库中的实用程序以及从何处获取它的文章(可在 github 上获得)a> 和 Maven 中心)在文章中查找段落字符串 Unicode 转换器"以解释此功能.该库还包含一个简单的 Http 客户端功能(文章中未描述,但在其 javadoc 中进行了描述.I'm having strange issue with a response got from API. I'm using apache HTTP Client to get response. Response header has the followingContent-Type=[application/json; charset=utf-16]Transfer-Encoding=[chunked]X-Powered-By=[ASP.NET] // Yes, people using ASP.NETSo based on this, when I get response, my response looks like follows笀∀匀琀愀琀甀猀䌀漀搀攀∀㨀㈀ So I tried the following.String body = "笀∀匀琀愀琀甀猀䌀漀搀攀∀㨀㈀";String charSetString = "utf-8|utf-16|utf-16le, all possible combination"body = new String(body.getBytes(Charset.forName(charSetString));body = body.replaceAll("[^\\x00-\\x7F]", "");But no luck. Started to look at first char. Actual response in first char is { I converted first char from response to ascii(int)body.charAt(0)Value is 31488; Whereas Ascii value of { is 123; if I do 31488/256 = 123 and converting this to char giving me { so I did the followingString encoded = "";for(int i=0; i< body.length(); i++) { encoded += ((char) ((int)body.charAt(i) / 256 ));}And it worked. But this is so bad conversation for single API. What I'm missing, what exactly the charset of response if I get 31488 for {UpdateMy API call code.import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.nio.charset.Charset;import java.util.LinkedHashMap;import java.util.Map;import org.apache.http.impl.client.HttpClientBuilder;import org.springframework.http.HttpEntity;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.http.ResponseEntity;import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;import org.springframework.util.SerializationUtils;import org.springframework.web.client.RestTemplate;public class HTTPClientManager { RestTemplate restTemplate = null; public void setup() { HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = null; clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory( HttpClientBuilder.create().build()); clientHttpRequestFactory.setReadTimeout(5 * 1000); clientHttpRequestFactory.setConnectTimeout(5 * 1000); restTemplate = new RestTemplate(clientHttpRequestFactory); } public static void main(String...strings) throws FileNotFoundException, IOException { HTTPClientManager ht = new HTTPClientManager(); ht.setup(); Map<String, Object> properties = new LinkedHashMap<>(); properties.put(Const.METHOD, "GET"); properties.put(Const.URL, strings[0]); properties.put(Const.CHAR_SET, "UTF-16LE"); Map<String, Object> ob = ht.getResponse(properties); try { String res = ob.get(Const.RESPONSE).toString(); System.out.println("Response ->>>>>>>>> \n " + res); }catch(Exception e) { e.printStackTrace(); } try (FileOutputStream fos = new FileOutputStream("response")) { fos.write(SerializationUtils.serialize(ob)); } } public static class Const { public static final String REQUEST = "request"; public static final String URL = "url"; public static final String CHAR_SET = "charSet"; public static final String RESPONSE = "response"; public static final String METHOD = "method"; public static final String REQUEST_HEADER = "reqHeader"; public static final String RESPONSE_HEADER = "resHeader"; } public Map<String, Object> getResponse(Map<String, Object> properties) { HttpHeaders headers = new HttpHeaders(); HttpEntity requestEntity = null; Map<String, Object> responseReturn = new LinkedHashMap<>(); HttpMethod method = null; if (properties.get(Const.METHOD).toString().equals("GET")) { method = HttpMethod.GET; requestEntity = new HttpEntity<String>("", headers); } else if (properties.get(Const.METHOD).toString().equals("POST")) { method = HttpMethod.POST; requestEntity = new HttpEntity<String>(properties.get(Const.REQUEST).toString(), headers); }else if (properties.get(Const.METHOD).toString().equals("PUT")) { method = HttpMethod.PUT; requestEntity = new HttpEntity<String>(properties.get(Const.REQUEST).toString(), headers); }else if (properties.get(Const.METHOD).toString().equals("DELETE")) { method = HttpMethod.DELETE; requestEntity = new HttpEntity<String>(properties.get(Const.REQUEST).toString(), headers); } ResponseEntity<String> response = null; try { response = restTemplate.exchange(properties.get(Const.URL).toString(), method, requestEntity, String.class); String body = response.getBody(); if(properties.get(Const.CHAR_SET) != null) { try { body = new String(body.getBytes(Charset.forName(properties.get(Const.CHAR_SET).toString()))); body = body.replaceAll("[^\\x00-\\x7F]", ""); }catch(Exception e) { e.printStackTrace(); } } responseReturn.put(Const.RESPONSE, body!=null?body:""); responseReturn.put(Const.RESPONSE_HEADER, response.getHeaders()); } catch (org.springframework.web.client.HttpClientErrorException |org.springframework.web.client.HttpServerErrorException exception) { exception.printStackTrace(); }catch(org.springframework.web.client.ResourceAccessException exception){ exception.printStackTrace(); }catch(Exception exception){ exception.printStackTrace(); } return responseReturn; }} 解决方案 I think that your problem is that you make a wrong assumption that your reply comes in UTF-16 i.e your line Content-Type=[application/json; charset=utf-16] is wrong. Try to remove the charset part (Content-Type=[application/json]) or set it to UTF-8 (Content-Type=[application/json; charset=utf-8]) and see what happens. I believe that reply that you are getting is: {"StatusCode":2. Not sure why the reply is seemingly missing '}' at the end, but other then that it makes sense. BTW I managed to interpret your reply by converting your reply string to unicode sequence. That gave me the sequence: \u7b00\u2200\u5300\u7400\u6100\u7400\u7500\u7300\u4300\u6f00\u6400\u6500\u2200\u3a00\u3200. This gave the idea that by forcing to interpret the response as utf-16 you messed up the content. So if I changed the sequence to \u007b\u0022\u0053\u0074\u0061\u0074\u0075\u0073\u0043\u006f\u0064\u0065\u0022\u003a\u0032 and converted it back to String from unicodes I got {"StatusCode":2.BTW If you're interested in tool to convert any string to unicode sequence and vise-versa then you can use MgntUtils open source library (written by me). All I had to do to convert your response string is:String result = "笀∀匀琀愀琀甀猀䌀漀搀攀∀㨀㈀"; result = StringUnicodeEncoderDecoder.encodeStringToUnicodeSequence(result); System.out.println(result);Here is the link to the article that describes the utilities in the library and where to get it (Available both on github and Maven central)In the article look for paragraph "String Unicode converter" for explanation of this feature. The library also contains a simple Http client feature (not described in the article but described in its javadoc. 这篇关于来自API的奇怪字符串的java字符编码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-05 19:27