抓取网页编码问题 - 字节中的负值

时间:2014-09-06 16:53:12

标签: java encoding apache-httpclient-4.x web-crawler

我使用以下代码抓取网页。

CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
CloseableHttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
System.out.println(entity.getContentType());
//output: Content-Type: text/html; charset=ISO-8859-1

我发现字符“'”的字节值为-110,无法映射到iso-8859-1或utf-8中的有效字符。

我尝试手动打开页面并复制字符并保存为文本文件,然后我看到字节值实际为39. 我认为操作系统在角色通过剪贴板时进行了转换

我想要的只是将网页保存为原始本地磁盘。

我制作了一个简单的代码来将内容保存到磁盘。我直接读取字节和写入字节。当我用十六进制编辑器打开保存的文件时,我可以看到该字节的值是146(-110)。

InputStream in = entity.getContent();
FileOutputStream fos = new FileOutputStream(new File("D:/test.html"));

byte[] buffer = new byte[1024];
int len = 0;
while((len = in.read(buffer)) > 0) {
    fos.write(buffer, 0, len);
    buffer = new byte[1024];
}
in.close();
fos.close();

所以现在问题变成了如何从字节146(-110)重建字符。如果我有任何东西,我会继续尝试和更新。

2 个答案:

答案 0 :(得分:1)

也许您可以提供一些代码如何将页面保存到磁盘?你检查了的值吗? 看起来字符的长度为3个字节,除非我的粘贴或复制失败。看看这个:

    public static void main(String[] args) {
    char c = '’';
    System.out.println("character: " + c);
    System.out.println("int: " + (int)c);
    String s = new String("’");
    // Java uses UTF-16 encoding, other encodings will give different values
    byte[] bytes = s.getBytes();
    System.out.println("bytes: " + Arrays.toString(bytes));
}

编辑:我发现以下建议的charset处理方法,试一试:

    ContentType contentType = ContentType.getOrDefault(entity);
    Charset charset = contentType.getCharset();
    Reader reader = new InputStreamReader(entity.getContent(), charset);

来源:https://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html

答案 1 :(得分:1)

Java中的字节是带符号的类型,其值为-128到127.最高有效位用于指示符号。例如,0111 1111 == 127,以及1000 0000 == -128。

我在ANSI表中查找了你的字符('),发现它的值为146(当然大于127)。二进制表示为1001 0010,因此将其解释为有符号值将产生-110。

重现您所看到的内容:

String s = new String("’");            // ’ is ansi character 146
byte[] bytes = s.getBytes();           
System.out.println( (int)bytes[0] );   // prints -110

将字节值转换为无符号表示:

char c = (char)(bytes[0] & 0xFF);
System.out.println( (int)c );          // prints 146