在Java中以Unicode读取和下载页面的源代码

时间:2013-07-16 05:23:00

标签: java html encoding unicode

现在,我有一些代码可以读取页面并将所有内容保存到html文件中。但是,存在一些问题......一些标点符号和特殊字符显示为问号。

当然,如果我手动执行此操作,我将使用Unicode编码而不是默认的ANSI保存.txt文件。我环顾四周,我所看到的就是抱怨说Java不可能或者我不理解的一半解释......

无论如何,有人可以帮我纠正问号吗?以下是我下载页面的代码部分。 (利斯特创建了一个可供下载的网址数组,用于包含网页的网站。您可以忽略它,它可以正常工作。)

public void URLDownloader(String site, int startPage, int endPage) throws Exception {
String[] pages = URLLister(site, startPage, endPage);
String webPage = pages[0];
int fileNumber = startPage;
if (startPage == 0)
  fileNumber++;

//change pages
for(int i = 0; i < pages.length; i++) {
  webPage = pages[i]; 
  URL url= new URL(webPage);
  BufferedReader in = new BufferedReader( 
                                         new InputStreamReader(url.openStream()));
  PrintWriter out = new PrintWriter(name + (fileNumber+i) + ".html");
  String inputLine;


  //while stuff to read on current page
  while ((inputLine = in.readLine()) != null) {
    out.println(inputLine); //write line of text
  }
  out.close();    //end writing text
  if (startPage == 0)
    startPage++;
  console.append("Finished page " + startPage + "\n");
  startPage++;
}      

1 个答案:

答案 0 :(得分:2)

  

如果我手动执行此操作,我将使用Unicode编码保存.txt文件而不是默认的ANSI

Windows在这里给你带来误导性的术语。没有'Unicode'这样的编码; Unicode是以不同方式编码为字节的字符集。 Windows称为“Unicode”的编码实际上是UTF-16LE。这是一个每个代码单位的双字节编码,不兼容ASCII,通常不方便;网页往往不能与之合作。

(因为'ANSI'代码页的价值与ANSI无关。加上ça改变......)

PrintWriter out = new PrintWriter(name + (fileNumber+i) + ".html");

这将使用Java默认编码创建一个文件,这可能是您的案例中的ANSI代码页。要指定不同的编码,请使用PrintWriter的可选第二个参数:

PrintWriter out = new PrintWriter(name + (fileNumber+i) + ".html", "utf-8");

UTF-8通常是一个不错的选择:作为UTF,它可以存储所有Unicode字符,并且它也是ASCII兼容的。

然而!您还使用默认编码读取字符串:

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));

这可能不是页面的编码。同样,您可以使用可选参数指定编码:

BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));

如果网页实际上作为UTF-8提供,这将正常工作。

但如果不是呢?实际上有多种方法可以确定HTML页面的编码:

  1. 来自Content-Type: text/html;charset=...标头参数,如果存在。
  2. 来自<?xml声明,如果它是application/xhtml+xml
  3. 从页面中的<meta>等效标记开始,如果(1)和(2)不存在。
  4. 来自浏览器特定的猜测启发式,可能取决于用户设置。
  5. 您可以通过阅读URL.getConnection().getContentType()并解析参数来获得(1)。要得到(2)或(3)你必须实际解析文件,这是一个坏消息。 (4)遥不可及。

    您可以做的最一致的事情就是Web浏览器(IE除外)在将独立网页保存到光盘时所执行的操作:获取所提供的确切原始字节并将其直接放入文件而不尝试解码它们。然后您不必担心编码或行结束更改。它确实意味着HTTP标头中的任何字符集元数据都会丢失,但是你自己解决HTML并自己插入<meta>标签的可能性并不大(可能是太过分了)。

    InputStream in = url.openStream();
    OutputStream out = new FileOutputStream(name + (fileNumber+i) + ".html");
    
    byte[] buffer = new byte[1024*1024];
    int len;
    while ((len = in.read(buffer)) != -1) {
        out.write(buffer, 0, len);
    }
    

    (来自this question的nb缓冲区复制循环,提供IOUtils等替代方案。)