搜索关键字符串NSSCanner:scanUpToString和scanString

来源:互联网 发布:淘宝个人主页怎么看 编辑:程序博客网 时间:2024/06/05 08:25

转载:http://blog.csdn.net/kmyhy/article/details/8258858


假设我们查找某个关键字(比如:【来自网易邮箱的超大附件】)在某段文本中的位置。这段文本的内容是不固定,它可能是这样的:

 

【来自网易邮箱的超大附件】

提示:邮件带有附件预览链接,若您转发或回复此邮件时不希望对方预览附件,建议您手动删除链接。

 

也可能是这样的:

 

开其说颇参差,而皆近於附会,故黄宗羲至诋为经纬混淆,行度无稽。【来自网易邮箱的超大附件】

提示:邮件带有附件预览链接,若您转发或回复此邮件时不希望对方预览附件,建议您手动删除链接。

 

还有可能根本不包含关键字:

 

achartengine

 绘制统计图是 就一个系类  能让这个系类中每个柱形图的颜色都不一样吗

 

我们需要把关键字“【来自网易邮箱的超大附件】”之后的内容统统删除,只保留位于关键字之前的内容,比如第一段文字变成了空或者第二段文本只留下以下文字:

 

开其说颇参差,而皆近於附会,故黄宗羲至诋为经纬混淆,行度无稽。

 

这个任务可以用NSScanner来做,如以下代码片段:

 


-(NSString*)extractBodyFromMessage:(NSString* )msg{

    NSString* body=msg;

    NSString* keyString=@"【来自网易邮箱的超大附件】";

    NSScanner*scanner=[NSScanner scannerWithString:body];

    [scannersetCaseSensitive:NO];

    BOOL b;

    while (![scanner isAtEnd]){

        b=[scannerscanString:keyString intoString:NULL];

        if(b) {

           body=[body substringToIndex:[scanner scanLocation]-keyString.length];

           break;

       }else{

           scanner.scanLocation++;

        }

    }

    return body;

}

 

在while循环里面,我们首先从0位置开始扫描指定关键字,如果未找到,移动scanLocation位置,继续从下一字符查找直至文本末尾;如果找到,直接返回子字符串。

有人会觉得用scanUpToString代替scanString会更好。

因为,scanUpToString在找到指定文本(keyString)后,会将scanLocation停止在keyString之前(scanString方法会将scanLocation移到keyString之后位置),这样我们的substringToIndex:方法就不必再用scanLocation减去keyString的长度了:

 

body=[bodysubstringToIndex:[scanner scanLocation]];

 

你可以试试,用scanUpToString替换scanString,并将substringToIndex:一句改成上面的语句,会是什么结果。

对于第一段文本来说,结果会是:

 

【来自网易邮箱的超大附件】

提示:邮件带有附件预览链接,若您转发或回复此邮件时不希望对方预览附件,建议您手动删除链接。

 

似乎scanner并没有找出keyString关键字。为什么?

因为API文档里面说:

 

If stopStringis the first string in the receiver, then the method returnsNO and stringValue is not changed.

 

如果scanUpToString在文本的开头(第一个字符)就找到目标文本,会返回NO,stringValue不会改变。

 

对于第一段文字来说,keyString就在文本的开头。因此scanUpToString虽然找到了keyString,但它仍然返回NO,并且scanLocation是0。于是从第2个字符又继续查找。结果当然是找不到,一直到最后一个字符之前,然后scanLocation++,scanLocation变成了最后一个字符的索引。

 

对于第二段和第三段文本,scanUpToString得到的结果倒是和scanString是一致的。没有什么问题。

这是因为API文档中说了:

 

If stopStringis present in the receiver, then on return the scan location is set to thebeginning of that string.

If the search string (stopString) isn't present in the scanner's source string, theremainder of the source string is put into stringValue, the receiver’sscanLocation is advanced to the end of thesource string, and the method returnsYES.

 

如果目标文本在receiver文本中被找到,返回YES并将scanLocation设置到已找到的目标文本之前。

如果目标文本未找到,从本次查找开始剩下的整个receiver文本被放入stringValue,scanLocation移动到源串的末尾,返回YES。

 

很显然,对于scanUpToString和scanString的区别,最主要的就在第一种情况上。如果目标文本一开头就出现目标文本(scanner默认是忽略空格和换行的,因此如果开头有这两个空白字符,scanner视若未见),二者将得到完全不同的结果:scanString会返回YES,而scanUpToString返回NO。