2010-12-05 43 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