You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 11使用UTF-8解析HttpResponse时特殊字符转为问号如何解决

Java抓取RSS特殊字符(含emoji)显示问号解决方案

问题根因

你遇到的乱码问题由以下几个错误操作导致:

  • 用BodyHandlers.ofString()接收响应时,若响应头未明确指定编码,HttpClient默认会用ISO-8859-1解码内容,UTF-8编码的emoji等特殊字符在这一步就会被转成乱码,后续无法恢复
  • 你后续将已解码错误的字符串再转成UTF-8字节流的操作完全多余,反而会放大编码问题
  • 部分情况下控制台默认编码不是UTF-8,也会导致正常的字符串打印出来显示问号,需要区分是字符串本身错误还是显示错误

最优修改方案

直接跳过String中转,用字节流直接交给DocumentBuilder解析,XML解析器会自动识别XML头部的编码声明,从根源避免转码问题,修改后的代码如下:

import java.nio.charset.StandardCharsets;
import java.io.InputStream;

ArrayList<Entry> pullRss(){
    ArrayList<Entry> output = new ArrayList<>();
    try{
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create("https://www.reddit.com/r/anysubreddit/.rss"))
              // 主动告知服务端优先返回UTF-8编码内容
              .header("Accept-Charset", "UTF-8")
              .build();

        // 直接获取响应字节流,不做中间字符串转码
        HttpResponse<InputStream> response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
    
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = factory.newDocumentBuilder();
        // 直接传入字节流解析,无需手动转码
        Document doc = db.parse(response.body());
        
        NodeList nList = doc.getElementsByTagName("entry");
        for (int temp = 0; temp < nList.getLength(); temp++) {
            Node nNode = nList.item(temp);
            Element eElement = (Element) nNode;
            
            String user     = eElement.getElementsByTagName("name").item(0).getTextContent();
            String userUri  = eElement.getElementsByTagName("uri").item(0).getTextContent();
            String id       = eElement.getElementsByTagName("id").item(0).getTextContent();
            String link     = eElement.getElementsByTagName("link").item(0).getAttributes().getNamedItem("href").toString();
            String date     = eElement.getElementsByTagName("published").item(0).getTextContent();
            String title    = eElement.getElementsByTagName("title").item(0).getTextContent();
            
            output.add(new Entry(user, userUri, id, link, date, title));
        }
    }catch (Exception e) {
        e.printStackTrace();
    }

    return output;
}

可选修改方案

如果你一定要用String类型接收响应内容,可明确指定解码编码为UTF-8,修改响应接收行即可:

// 明确指定UTF-8解码响应
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8));

注意事项

如果修改后控制台打印仍显示问号,可在JVM启动参数中添加-Dfile.encoding=UTF-8,同时将IDE的控制台编码设置为UTF-8即可解决,该问题仅为显示问题,不影响字符串本身存储的内容正确性。

内容的提问来源于stack exchange,提问作者Georodin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 00:39:03