Java 无法分析和显示从http请求读取的非utf8字符

Java 无法分析和显示从http请求读取的非utf8字符,java,json,parsing,encoding,Java,Json,Parsing,Encoding,我正在使用Java解析这个请求 因此,它有一个JSON文件(为了简洁起见被截断): {"responseData":{"results": <...> "visibleUrl":"www.coolcook.net", "cacheUrl":"http://www.google.com/search?q\u003dcache:p4Ke5q6zpnUJ:www.coolcook.net", "title":"مطبخ مطايب - كباب الدجاج والخضار بصلصة

我正在使用Java解析这个请求

因此,它有一个JSON文件(为了简洁起见被截断):

{"responseData":{"results":
<...>
"visibleUrl":"www.coolcook.net",
"cacheUrl":"http://www.google.com/search?q\u003dcache:p4Ke5q6zpnUJ:www.coolcook.net",
"title":"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب",
"titleNoFormatting":"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب","\u003drz+img+news+recordid+border"}}, 
<...>
"responseDetails": null, "responseStatus": 200}
但是,“before”和“after”结果都是相同的:一组???,不管我是在服务器日志文件中还是在HTML页面中输出它们。有没有其他方法可以取回阿拉伯字符并将其输出到网页中

JSON是否有任何支持这类问题的功能,也许是为了直接从JSONObject读取非utf字符?

首先尝试以下方法:

str = j.getString("titleNoFormatting");
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("c:/test.txt"), "UTF-8"));
writer.write(str);
writer.close();
然后在记事本中打开文件。如果这看起来不错,那么问题在于记录器或控制台没有配置为使用
UTF-8
。否则,问题很可能在于您使用的JSON API没有配置为使用
UTF-8

编辑:如果问题实际上存在于所使用的JSON API中,而您不知道该选择哪个,那么我建议您使用。它确实简化了将Json字符串转换为易于使用的javabean的过程。以下是一个基本示例:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;

import com.google.gson.Gson;

public class Test {

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://ajax.googleapis.com/ajax/services/search/web"
            + "?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border");
        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));
        GoogleResults results = new Gson().fromJson(reader, GoogleResults.class);

        // Show all results.
        System.out.println(results);

        // Show title of 1st result (is arabic).
        System.out.println(results.getResponseData().getResults().get(0).getTitle());
    }

}

class GoogleResults {

    ResponseData responseData;
    public ResponseData getResponseData() { return responseData; }
    public void setResponseData(ResponseData responseData) { this.responseData = responseData; }
    public String toString() { return "ResponseData[" + responseData + "]"; }

    static class ResponseData {
        List<Result> results;
        public List<Result> getResults() { return results; }
        public void setResults(List<Result> results) { this.results = results; }
        public String toString() { return "Results[" + results + "]"; }
    }

    static class Result {
        private String url;
        private String title;
        public String getUrl() { return url; }
        public String getTitle() { return title; }
        public void setUrl(String url) { this.url = url; }
        public void setTitle(String title) { this.title = title; }
        public String toString() { return "Result[url:" + url +",title:" + title + "]"; }
    }

}
导入java.io.BufferedReader;
导入java.io.InputStreamReader;
导入java.net.URL;
导入java.util.List;
导入com.google.gson.gson;
公开课考试{
公共静态void main(字符串[]args)引发异常{
URL=新URL(“http://ajax.googleapis.com/ajax/services/search/web"
+“?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border”);
BufferedReader=新的BufferedReader(新的InputStreamReader(url.openStream(),“UTF-8”);
GoogleResults=new Gson().fromJson(reader,GoogleResults.class);
//显示所有结果。
系统输出打印项次(结果);
//显示第一个结果的标题(阿拉伯语)。
System.out.println(results.getResponseData().getResults().get(0.getTitle());
}
}
GoogleResults类{
响应数据响应数据;
public ResponseData getResponseData(){return ResponseData;}
public void setResponseData(ResponseData ResponseData){this.ResponseData=ResponseData;}
公共字符串toString(){return“ResponseData[“+ResponseData+”]”;}
静态类响应数据{
列出结果;
public List getResults(){return results;}
public void setResults(列出结果){this.results=results;}
公共字符串toString(){return“Results[“+Results+”]”;}
}
静态类结果{
私有字符串url;
私有字符串标题;
公共字符串getUrl(){return url;}
公共字符串getTitle(){return title;}
public void setUrl(字符串url){this.url=url;}
public void setTitle(字符串标题){this.title=title;}
公共字符串toString(){return“Result[url:+url+,title:+title+”];}
}
}

它可以很好地输出结果。希望这有帮助。

问题的重要部分是如何处理HTTP响应的内容。也就是说,如何创建
json
对象?当您看到原始帖子中的代码时,内容已经损坏


请求产生UTF-8编码数据。如何将其解析为JSON对象?是否为解码器指定了正确的编码?或者正在使用您平台的默认字符编码?

谷歌API正确发送UTF-8。我认为问题在于您的默认编码不能输出阿拉伯语。检查您的
文件.encoding
属性或获得如下编码

public static String getDefaultCharSet() throws IOException {
    OutputStreamWriter writer = new OutputStreamWriter(new ByteArrayOutputStream());
    return writer.getEncoding();
}

如果默认编码是ASCII或Latin-1,则会得到“?”s。你需要把它改成UTF-8

您遇到的问题很可能是由于在您从google读取http响应时,字符编码设置不正确造成的。您可以发布实际获取URL并将其解析为JSON对象的代码吗

例如,运行以下命令:

public class Test1 {
  public static void main(String [] args) throws Exception {

    // just testing that the console can output the correct chars
    System.out.println("\"title\":\"مطبخ مطايب - كباب الدجاج والخضار بصلصة الروب");

    URL url = new URL("http://ajax.googleapis.com/ajax/services/search/web?start=0&rsz=large&v=1.0&q=rz+img+news+recordid+border");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    InputStream is  = connection.getInputStream();

    // the important bit is here..........................\/\/\/
    InputStreamReader reader = new InputStreamReader(is, "utf-8");


    StringWriter sw = new StringWriter();

    char [] buffer = new char[1024 * 8];
    int count ;

    while( (count = reader.read(buffer)) != -1){
      sw.write(buffer, 0, count);
    }

    System.out.println(sw.toString());
  }
}
这是使用了一个非常丑陋的标准
URL.openConnection()
,这个标准从时间的黎明就开始了。如果你正在使用类似的东西,那么你可以很容易地做到这一点


了解一些关于编码的背景知识,并解释为什么
新字符串(str.getBytes(),“UTF8”)
永远不会工作读取我认为JSON.org Java JSON包无法处理UTF8,无论它是作为UTF8字符传入还是实际传入
\uxxx
代码。我试了两种方法如下:

import org.json.
public class JsonTest extends TestCase {
    public void testParseText() {
        try {
            JSONObject json1 = new JSONObject("{\"a\":\"\u05dd\"}"); // \u05dd is a Hebrew character
            JSONObject json2 = new JSONObject("{\"a\":\"\\u05dd\"}"); // \u05dd is a Hebrew character
            System.out.println(json1.toString());
            System.out.println(json2.toString());
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
我得到:

{"a":"?"}
{"a":"?"}
有什么想法吗

有一个使用JSon消息保留http响应(捷克语表达式)编码的方法,如下所示:

private static String inputStreamToString(final InputStream inputStream) throws Exception {
 final StringBuilder outputBuilder = new StringBuilder();

 try {
  String string;
  if (inputStream != null) {
   BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
   while (null != (string = reader.readLine())) {
    outputBuilder.append(string).append('\n');
   }
  }
 } catch (Exception ex) {
  throw new Exception("[google-api-translate-java] Error reading translation stream.", ex);
 }

 return outputBuilder.toString();
}
答案很棘手,有几点必须注意,主要是平台编码:

afaik影响打印输出到控制台,从inputstream创建文件,甚至影响DB客户端和服务器之间的通信,即使它们都设置为使用utf-8字符集进行编码-无论我是显式创建utf-8字符串、inputstreamReader还是为utf-8设置JDBC驱动程序,在linux系统上仍要将$LANG属性设置为xx_xx.UTF-8,并将append=“vt.default_utf8=1”添加到LILO引导加载程序(在使用它的系统上),至少对于运行数据库和使用UTF-8编码文件的java应用程序的系统,必须这样做

即使我附加了这个JVM参数-Dfile.encoding=UTF-8,如果没有平台编码,我也无法在正确编码的流中成功。正确设置JDBC连接器是必要的:“JDBC:mysql://localhost/DBname?useUnicode=true&characterEncoding=UTF8,如果要将字符串持久化到数据库,该数据库应处于以下状态:

    mysql> SHOW VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name            | Value  |
+--------------------------+--------+
| character_set_client     | utf8   |
| character_set_connection | utf8   |
| character_set_database   | utf8   |
| character_set_filesystem | binary |
| character_set_results    | utf8   |
| character_set_server     | utf8   |
| character_set_system     | utf8   |
+--------------------------+--------+

谷歌的回应应该是UTF-8。您确定正在使用的终端支持UTF-8吗?您描述的阿拉伯字符是Unicode,可以用UTF-8表示。您可能在输出上有编码问题,而不是在输入上。
System.out.println(Charset.defaultCharset())在我们的服务器中,som
    mysql> SHOW VARIABLES LIKE 'character\_set\_%';
+--------------------------+--------+
| Variable_name            | Value  |
+--------------------------+--------+
| character_set_client     | utf8   |
| character_set_connection | utf8   |
| character_set_database   | utf8   |
| character_set_filesystem | binary |
| character_set_results    | utf8   |
| character_set_server     | utf8   |
| character_set_system     | utf8   |
+--------------------------+--------+