2013-08-12 34 views
0

我使用httpclient來抓取htmls。在我的代碼中,我發現如何在java中優化「replaceFirst」方法

html = html.replaceFirst("[cC][hH][aA][rR][sS][eE][tT]\\s*?=\\s*?([gG][bB]2312|[gG][bB][kK]|[gG][bB]18030)","charset=utf-8"); 

上面的代碼導致java.lang.OutOfMemoryError。總計程序使用251MB,replaceFirst方法使用64.8%,157MB,並且正在增長。我怎樣才能避免這一點,我需要一些幫助。 ths〜

+1

您正在試圖替換「字符集= GB2312」或「字符集= GBK」或「字符集= GB18030」與「字符集UTF-8 「,不區分大小寫,是否正確?你確定*這是你的記憶問題的原因嗎?你能製作一個最小的測試程序來證明那行代碼實際上導致了大量的內存使用嗎? –

+0

我剛剛運行了一個100K的字符串,在沒有匹配的字符串的情況下替換了300K次,並且沒有發現不正常的內存使用情況。我很確定,今年是 –

+0

。我已經使用jprofiler進行了幾次測試,在程序衝突的時候,「replaceFirst」方法佔用了內存總量的近90% – wangzhiju

回答

1

第一點是:不要使用正則表達式進行HTML解析。改爲使用HTML分析器。第二,如果你已經有了這種模式,並且只是想解決它一點點,試着去理解它做了什麼。

它實際上用非常不優化的方式替代charset=GBK2312charset=GBK18030通過charset=UTF-8

因此,首先改變你的正則表達式如下:

charset=GBK(?:2312|18030)

我相信這wiil已經給你一些優勢。但是這個正則表達式區分大小寫。代替在下部和上部殼體使用Pattern直接手動編寫的每個字符:

Pattern p = Pattern.compile("charset=GBK(?:2312|18030)", Pattern.CASE_INSENSITIVE); 
String newHtml = p.matcher(oldHtml).replaceFirst("charset=utf8"); 
+1

正則表達式應該是'charset = GB(?:K | 2312 | 18030)'。 –