2013-03-07 332 views
3

我想解析HLS主m3u8文件並從中獲取帶寬,分辨率和文件名。目前我使用字符串解析來搜索字符串的一些模式,並做子字符串來獲取價值。使用正則表達式解析HLS m3u8文件

示例文件:

#EXTM3U 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=476416,RESOLUTION=416x234 
Stream1/index.m3u8 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=763319,RESOLUTION=480x270 
Stream2/index.m3u8 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1050224,RESOLUTION=640x360 
Stream3/index.m3u8 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1910937,RESOLUTION=640x360 
Stream4/index.m3u8 
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=3775816,RESOLUTION=1280x720 
Stream5/index.m3u8 

但是,我發現,我們可以使用正則表達式解析它就像在這個問題提到: Problem matching regex pattern in Android

我沒有正則表達式的任何想法,所以會有些一個請指導我使用正則表達式來解析此問題。

或者有人可以幫我寫的正則表達式從以下字符串

#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=476416,RESOLUTION=416x234 

回答

8

解析出帶寬和分辨率值你可以嘗試這樣的事:

final Pattern pattern = Pattern.compile("^#EXT-X-STREAM-INF:.*BANDWIDTH=(\\d+).*RESOLUTION=([\\dx]+).*"); 

    Matcher matcher = pattern.matcher("#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=476416,RESOLUTION=416x234"); 
    String bandwidth = ""; 
    String resolution = ""; 

    if (matcher.find()) { 
     bandwidth = matcher.group(1); 
     resolution = matcher.group(2); 
    } 

會設置帶寬和分辨率的正確(字符串)值。

我還沒有嘗試過這個在Android設備或模擬器上,但從你發送的鏈接和android API來看,它應該像上面的普通老Java一樣工作。

該正則表達式匹配以#EXT-X-STREAM-INF:開頭的字符串,其中包含BANDWIDTHRESOLUTION,後跟正確的值格式。然後這些在後向參照組1和2中被反引用,以便我們可以提取它們。

編輯:

如果分辨率不總是存在,那麼你就可以說部分可選的,因爲這樣的:

"^#EXT-X-STREAM-INF:.*BANDWIDTH=(\\d+).*(?:RESOLUTION=([\\dx]+))?.*" 

resolution字符串在只有BANDWIDTH存在的情況下null

EDIT2:。

?使事情可選的,(?:___)意味着被動組(而不是反向引用組(___)所以它基本上是一個可選的被動組所以,是的,它裏面什麼會可選。

一個.匹配單個字符,和*使得意味着它會被重複零次或多次。所以.*將匹配零個或多個字符。我們需要的原因,這是消耗我們所匹配之間的任何,例如anythin g在#EXT-X-STREAM-INF:BANDWIDTH之間。有很多方法可以做到這一點,但.*是最通用/最廣泛的方法。

\d基本上是一組表示數字(0-9)字符,但由於我們定義字符串作爲一個Java字符串,我們需要加倍\\,否則Java編譯器將失敗,因爲它不承認的轉義字符\d (用Java)。相反,它會將\\解析爲\,以便我們在傳遞給Pattern構造函數的最後一個字符串中獲得\d

[\dx]+表示字符中的一個或多個字符(+0-9x[\dx\d]將是同一組字符中的單個字符(不是+)。

如果你有興趣的正則表達式,你可以檢查出regular-expressions.info或/和regexone.com,那麼你會發現更多的深入解答所有的問題。

+0

感謝您的答覆將嘗試您的代碼。當我們調用'pattern.matcher'時,我有一個關於模式匹配的問題,它在'matcher'中返回的是它在正則表達式中忽略給定的模式的字符串?在做'pattern.matcher'之後,我們爲什麼要調用'find'? – User7723337 2013-03-07 08:58:45

+1

匹配器是您用來根據模式對給定字符串執行匹配操作的對象。當你調用find()時,它會嘗試找到給定字符串中的下一個匹配項,如果它找到一個它返回true,我們可以提取結果。您可以查看[文檔](http://docs.oracle.com/javase/6/docs/api/java/util/regex/Matcher.html)以獲取更多信息(這是Java文檔,但是它應該在Android上表現相同的方式,android文檔沒有太多細節)。 – rvalvik 2013-03-07 09:13:49

+0

感謝您的解釋!我把你的代碼綁定在工作,但如果字符串沒有解決方案,只是帶寬呢?我嘗試過,但'find'在這種情況下失敗了。是否有可能檢查解決方案在任何情況下,如果發現然後確定否則只是忽略或我們需要拖放單獨的表達式來解析帶寬和分辨率,並將相同的字符串傳遞給它們並調用find? – User7723337 2013-03-07 09:34:44