现在,我有一些代码可以读取页面并将所有内容保存到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++;
}
答案 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页面的编码:
Content-Type: text/html;charset=...
标头参数,如果存在。<?xml
声明,如果它是application/xhtml+xml
。<meta>
等效标记开始,如果(1)和(2)不存在。您可以通过阅读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
等替代方案。)