【问题标题】:How to handle non-UTF8 html page in Java?如何在 Java 中处理非 UTF8 html 页面?
【发布时间】:2012-02-03 12:53:08
【问题描述】:

我的任务是使用 Java 从 url 中检索 html 字符串。

我知道如何使用 HttpUrlConnection 和 InputStream 来获取字符串。

但是,我有一些页面的编码问题。

如果某些页面有不同的编码(例如,GB2312),而不是 UTF8,我得到的字符串只是任意字符或问号。

谁能告诉我如何解决这个问题?

谢谢

以下是我从 url 下载 html 的代码。

private String downloadHtml(String urlString) {
    URL url = null;
    InputStream inStr = null;
    StringBuffer buffer = new StringBuffer();

    try {
        url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Cast shouldn't fail
        HttpURLConnection.setFollowRedirects(true);
        // allow both GZip and Deflate (ZLib) encodings
        //conn.setRequestProperty("Accept-Encoding", "gzip, deflate"); 
        String encoding = conn.getContentEncoding();
        inStr = null;

        // create the appropriate stream wrapper based on
        // the encoding type
        if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
            inStr = new GZIPInputStream(conn.getInputStream());
        } else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
            inStr = new InflaterInputStream(conn.getInputStream(),
              new Inflater(true));
        } else {
            inStr = conn.getInputStream();
        }
        int ptr = 0;


        InputStreamReader inStrReader = new InputStreamReader(inStr, Charset.forName("GB2312"));

        while ((ptr = inStrReader.read()) != -1) {
            buffer.append((char)ptr);
        }
        inStrReader.close();

        conn.disconnect();
    }
    catch(Exception e) {

        e.printStackTrace();
    }
    finally {
        if (inStr != null)
            try {
                inStr.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    }

    return buffer.toString();
}

【问题讨论】:

    标签: java html string encoding httpurlconnection


    【解决方案1】:

    通过使用InputStreamReader 并指定您的字符集,如下所示:

    inStr = new InputStreamReader(InputStream, Charset.forName("GB2312"));
    

    以下代码对我有用:

    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.nio.charset.Charset;
    import java.util.zip.GZIPInputStream;
    import java.util.zip.Inflater;
    import java.util.zip.InflaterInputStream;
    
    public class Foo {
    
    public static void main(String[] args) {
        System.out.println(downloadHtml("http://baike.baidu.com/view/6000001.htm"));
    }
    
    
    private static String downloadHtml(String urlString) {
        URL url = null;
        InputStream inStr = null;
        StringBuffer buffer = new StringBuffer();
    
        try {
            url = new URL(urlString);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Cast shouldn't fail
            HttpURLConnection.setFollowRedirects(true);
            // allow both GZip and Deflate (ZLib) encodings
            //conn.setRequestProperty("Accept-Encoding", "gzip, deflate"); 
            String encoding = conn.getContentEncoding();
            inStr = null;
    
            // create the appropriate stream wrapper based on
            // the encoding type
            if (encoding != null && encoding.equalsIgnoreCase("gzip")) {
                inStr = new GZIPInputStream(conn.getInputStream());
            } else if (encoding != null && encoding.equalsIgnoreCase("deflate")) {
                inStr = new InflaterInputStream(conn.getInputStream(),
                  new Inflater(true));
            } else {
                inStr = conn.getInputStream();
            }
            int ptr = 0;
    
    
            InputStreamReader inStrReader = new InputStreamReader(inStr, Charset.forName("GB2312"));
    
            while ((ptr = inStrReader.read()) != -1) {
                buffer.append((char)ptr);
            }
            inStrReader.close();
    
            conn.disconnect();
        }
        catch(Exception e) {
    
            e.printStackTrace();
        }
        finally {
            if (inStr != null)
                try {
                    inStr.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }
    
        return buffer.toString();
      }
    
    }
    

    【讨论】:

    • 我已经尝试过你的建议:return new String(buffer.toString().getBytes(), "GB2312"));但它不起作用。 url baike.baidu.com/view/6000001.htm 的编码仍然错误
    • 我很抱歉,我最近确认它不起作用。但是,第一种方法,使用 InputStreamReader 将起作用。不幸的是,这可能意味着您必须重构一些代码......
    • 如果得到一个GB2312编码的字符串,然后直接System.out.println就可以正常显示了吧?
    • 我改了源代码,现在用InputStreamReader,还是错了。您能否看看我的问题中的新源代码。我修改并添加了 InputStreamReader
    • 用对我有用的代码修改了解决方案。如果问题仍然存在,这可能是您机器的字符集渲染的问题吗?
    【解决方案2】:

    使用构造函数 InputStreamReader(InputStream in, Charset cs) 使用 InputStreamReader 读取您的 inputStream

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-04
      • 1970-01-01
      • 2017-09-24
      • 2023-03-27
      • 2015-09-03
      相关资源
      最近更新 更多