我想解析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
我不知道正则表达式,所以有人能指导我用正则表达式来解析它吗?
或者有人可以帮助我编写regexp来解析下面字符串中的带宽和解析值吗?
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=476416,RESOLUTION=416x234
最佳答案
你可以试试这样的:
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一样。
regex匹配以#EXT-X-STREAM-INF:开头的字符串,并包含BANDWIDTH和RESOLUTION以及正确的值格式。然后在后向参照组1和2中对它们进行后向参照,以便我们可以提取它们。
编辑:
如果分辨率不总是存在,则可以将该部分设置为可选:
"^#EXT-X-STREAM-INF:.*BANDWIDTH=(\\d+).*(?:RESOLUTION=([\\dx]+))?.*"
在只有resolution存在的情况下,null字符串将是BANDWIDTH。
编辑2:
?使事情成为可选的,(?:___)表示一个被动组(而不是反向引用组)。所以它基本上是一个可选的被动组。所以是的,里面的任何东西都是可选的。
a(___)匹配单个字符,而a.makes意味着它将重复零次或多次。因此*将匹配零个或多个字符。我们需要这样做的原因是消耗我们所匹配的内容之间的任何内容,例如.*和#EXT-X-STREAM-INF:之间的任何内容。有很多方法可以做到这一点,但BANDWIDTH是最通用/最广泛的一种。
.*基本上是一组表示数字的字符(\d),但由于我们将字符串定义为Java字符串,所以需要双0-9,否则Java编译器将失败,因为它不识别转义字符\\(在Java中)。相反,它将把\d解析为\\以便在传递给\构造函数的最后一个字符串中得到\d。
Pattern表示字符[\dx]+和+中的一个或多个字符(0-9)。x将是同一组字符中的单个字符(no[\dx\d])。
如果您对regex感兴趣,可以查看regular-expressions.info或/和regexone.com,您将在那里找到所有问题的更深入的答案。