public class Parser {
public static void main(String[] args) {
Parser p = new Parser();
p.matchString();
}
parserObject courseObject = new parserObject();
ArrayList<parserObject> courseObjects = new ArrayList<parserObject>();
ArrayList<String> courseNames = new ArrayList<String>();
String theWebPage = " ";
{
try {
URL theUrl = new URL("http://ocw.mit.edu/courses/");
BufferedReader reader =
new BufferedReader(new InputStreamReader(theUrl.openStream()));
String str = null;
while((str = reader.readLine()) != null) {
theWebPage = theWebPage + " " + str;
}
reader.close();
} catch (MalformedURLException e) {
// do nothing
} catch (IOException e) {
// do nothing
}
}
public void matchString() {
// this is my regex that I am using to compare strings on input page
String matchRegex = "#\\w+(-\\w+)+";
Pattern p = Pattern.compile(matchRegex);
Matcher m = p.matcher(theWebPage);
int i = 0;
while (!m.hitEnd()) {
try {
System.out.println(m.group());
courseNames.add(i, m.group());
i++;
} catch (IllegalStateException e) {
// do nothing
}
}
}
}
我想用上面的代码实现的目的是获取MIT OpencourseWare网站上的部门列表。我正在使用与页面源中的部门名称模式匹配的正则表达式。我正在使用Pattern对象和Matcher对象,并尝试查找()并打印与正则表达式匹配的这些部门名称。但代码正在运行,我不认为使用bufferedReader在网页上阅读需要花费很长时间。所以我认为我要么做一些可怕的错误,要么解析网站需要花费相当长的时间。所以如果有任何关于如何提高性能或纠正我的代码中的错误,我将不胜感激。我为编写糟糕的代码道歉。
答案 0 :(得分:13)
问题在于代码
while ((str = reader.readLine()) != null)
theWebPage = theWebPage + " " +str;
变量theWebPage
是一个String,它是不可变的。对于读取的每一行,此代码创建一个 new 字符串,其中包含到目前为止已读取的所有内容的副本,并附加空格和刚刚读取的行。这是一次非常多的不必要的复制,这就是程序运行速度如此之慢的原因。
我下载了相关网页。它有55,000行,大小约为3.25MB。不太大。但由于循环中的复制,第一行最终被复制约<15> 次(55,000平方的1/2)。该计划花费所有时间进行复制和垃圾收集。我在笔记本电脑上运行了这个(2.66GHz Core2Duo,1GB堆),从本地文件读取时运行了15分钟(没有网络延迟或网络爬行对策)。
要解决此问题,请将theWebPage
改为StringBuilder
,然后将循环中的行更改为
theWebPage.append(" ").append(str);
如果您愿意,可以在循环后使用theWebPage
将toString()
转换为字符串。当我运行修改后的版本时,花了不到一秒钟。
BTW您的代码在类{ }
内使用了一个裸代码块。这是实例初始化程序(与静态初始化程序相反)。它在对象构建时运行。这是合法的,但这很不寻常。请注意,它误导了其他评论者。我建议将此代码块转换为命名方法。
答案 1 :(得分:2)
这是你的整个计划吗? parserObject
的声明在哪里?
此外,在调用main()
之前,不应该将所有代码都放在matchString()
中吗?
parserObject courseObject = new parserObject();
ArrayList<parserObject> courseObjects = new ArrayList<parserObject>();
ArrayList<String> courseNames = new ArrayList<String>();
String theWebPage=" ";
{
try {
URL theUrl = new URL("http://ocw.mit.edu/courses/");
BufferedReader reader = new BufferedReader(new InputStreamReader(theUrl.openStream()));
String str = null;
while((str = reader.readLine())!=null)
{
theWebPage = theWebPage+" "+str;
}
reader.close();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
}
您还捕获异常并且不显示任何错误消息。您应始终显示错误消息,并在遇到异常时执行某些操作。例如,如果您无法下载页面,则没有理由尝试解析空字符串。
从你的评论中我了解了类中的静态块(谢谢,不知道它们)。但是,根据我的阅读,您需要在块static
的开头之前添加关键字{
。此外,将代码放入main
可能更好,如果遇到MalformedURLException或IOException,就可以退出。
答案 2 :(得分:1)
当然,您可以使用有限的JDK 1.0 API解决此任务,并遇到Stuart Marks helped you solve in his excellent answer的问题。
或者,您只需使用一个流行的事实上的标准库,例如Apache Commons IO,并使用这样的简单方法将您的网站读成字符串:
// using this...
import org.apache.commons.io.IOUtils;
// run this...
try (InputStream is = new URL("http://ocw.mit.edu/courses/").openStream()) {
theWebPage = IOUtils.toString(is);
}