2010-12-05 107 views
2

运行嵌套的NSScanner是解析出重复元素字符串的最有效方法,还是一次扫描就可以完成?嵌套的NSScanner效率

我是从一个命令行调用(NSTAsk)苹果的压缩机返回的字符串(没有换行符,休息是纯粹为了便于这个问题无需滚动是清晰的):

<jobStatus name="compressor.motn" submissionTime="12/4/10 3:56:16 PM" 
sentBy="localuser" jobType="Compressor" priority="HighPriority" 
timeElapsed="32 second(s)" timeRemaining="0" timeElapsedSeconds="32" 
timeRemainingSeconds="0" percentComplete="100" resumePercentComplete="100" 
status="Successful" jobid="CD4046D8-CDC1-4F2D-B9A8-460DF6AF184E" 
batchid="0C9041F5-A499-4D00-A26A-D7508EAF3F85" /jobStatus> 

这些重复相同的字符串从而有可能为零,通过在返回字符串的这n:

<jobstatus .... /jobstatus><jobstatus .... /jobstatus> 
<jobstatus .... /jobstatus> 

此外,还有可能是其他标签包括它们是没有意义的我的代码(在这个例子中batchstatus) :

<jobstatus .... /jobstatus><batchstatus .... /batchstatus> 
<jobstatus .... /jobstatus> 

这不是一个返回的XML文档,只是一系列恰好被包裹在XML中的状态块,如标签。没有任何块被嵌套。它们都是顺序性的。我无法控制返回的数据。

我的目标(和当前工作代码)将字符串解析为包含jobstatus块中的详细信息字典的“作业”。任何其他块(例如batchstatus)和其他任何字符串都将被忽略。我只关心jobstatus块的内容。

NSScanner * jobScanner = [NSScanner scannerWithString:dataAsString]; 
NSScanner * detailScanner = nil; 

NSMutableDictionary * jobDictionary = [NSMutableDictionary dictionary]; 
NSMutableArray * jobsArray = [NSMutableArray array]; 

NSString * key = @""; 
NSString * value = @""; 

NSString * jobStatus = @""; 

NSCharacterSet * whitespace = [NSCharacterSet whitespaceCharacterSet]; 

while ([jobScanner isAtEnd] == NO) { 

    if ([jobScanner scanUpToString:@"<jobstatus " intoString:NULL] && 
     [jobScanner scanUpToCharactersFromSet:whitespace intoString:NULL] && 
     [jobScanner scanUpToString:@" /jobstatus>" intoString:&jobStatus]) { 

     detailScanner = [NSScanner scannerWithString:jobStatus]; 

     [jobDictionary removeAllObjects]; 

     while ([detailScanner isAtEnd] == NO) { 

      if ([detailScanner scanUpToString:@"=" intoString:&key] && 
       [detailScanner scanString:@"=\"" intoString:NULL] && 
       [detailScanner scanUpToString:@"\"" intoString:&value] && 
       [detailScanner scanString:@"\"" intoString:NULL]) { 

       [jobDictionary setObject:value forKey:key]; 

       //NSLog(@"Key:(%@) Value:(%@)", key, value); 
      } 
     } 

     [jobsArray addObject: 
     [NSDictionary dictionaryWithDictionary:jobDictionary]]; 
    } 

} 

NSLog(@"Jobs Dictionary:%@", jobsArray); 

上面的代码生成以下日志输出:

Jobs Dictionary:(
    { 
    batchid = "0C9041F5-A499-4D00-A26A-D7508EAF3F85"; 
    jobType = Compressor; 
    jobid = "CD4046D8-CDC1-4F2D-B9A8-460DF6AF184E"; 
    name = "compressor.motn"; 
    percentComplete = 100; 
    priority = HighPriority; 
    resumePercentComplete = 100; 
    sentBy = localuser; 
    status = Successful; 
    submissionTime = "12/4/10 3:56:16 PM"; 
    timeElapsed = "32 second(s)"; 
    timeElapsedSeconds = 32; 
    timeRemaining = 0; 
    timeRemainingSeconds = 0; 
} 

这里的关注。在我的代码中,我正在扫描字符串,然后当我得到一块数据时,通过扫描该块创建一个填充数组的字典。这实际上意味着该字符串会走两次。由于这种情况每15到30秒发生一次,可能包含数百个作业,我认为这是一个潜在的CPU和内存垃圾,因为运行该应用程序的应用程序可能与Compressor应用程序在同一台机器上(这是已经是内存和CPU了) - 如果我不需要,我不想增加任何负担。

当我走过它来获取数据时,是否有更好的方式来使用NSScanner?

任何意见或建议非常感谢!

回答

1

您的嵌套是正确的,因为您正在构造具有jobScanner扫描的jobStatus的detailScanner。这不是问题。不过,你还有两个人。一个是你太空冒空白字符,但更糟糕的是,你的最外层循环永远不会退出,因为你的初始if条件形成的方式。

变化

if ([jobScanner scanUpToString:@"<jobstatus " intoString:NULL] && 
[jobScanner scanUpToCharactersFromSet:whitespace intoString:NULL] && 
[jobScanner scanUpToString:@" /jobstatus>" intoString:&jobStatus]) 

if ([jobScanner scanString:@"<jobstatus" intoString:NULL] && 
[jobScanner scanUpToString:@"/jobstatus>" intoString:&jobStatus] && 
[jobScanner scanString:@"/jobstatus>" intoString:NULL]) 

当然,你可以删除你的行中,你缓存你的空格字符集。您不需要扫描空格字符,也不需要将它们包含在您扫描或扫描的字符串中。默认情况下,扫描仪跳过空白字符。取消注释您的第一个NSLog声明就可以解决这个问题。输出中没有任何杂散空间。

但是,您确实需要扫描一个给定的字符串,自己扫描该字符串,否则在下一次迭代过程中您不会继续前进。

除此之外,我认为你的方法是正确的。

+0

trudyscousin - 谢谢!这些变化正在并且正在顺利进行。我是一个关注字符集的机器人,因为根据文档,这是一个昂贵的操作,但我当然错过了空白字节被跳过的位置,因此无论如何它都变得毫无意义!再次感谢! – Hooligancat 2010-12-05 05:37:51