ネストされた NSScanner を実行することは、繰り返し要素の文字列を解析するための最も効率的な方法ですか、それともスキャンを 1 回のパスで実行できますか?
コマンド ライン呼び出し ( NSTAsk
) から Apple の Compressor に返される文字列があります (改行はありません。この質問をスクロールせずに読みやすくするためだけに改行を入れています)。
<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>
これらは同じ文字列で繰り返されるため、返される文字列には 0 ~ 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;
}
ここが懸念事項です。私のコードでは、文字列をスキャンし、データのブロックを取得したら、その部分をスキャンして、配列に入力する辞書を作成しています。これは事実上、ストリングが 2 回歩くことを意味します。これは 15 ~ 30 秒ごとに発生し、数百のジョブが含まれる可能性があるため、CPU とメモリを大量に消費する可能性があり、これを実行しているアプリが Compressor アプリ (つまりすでにメモリと CPU を食い尽くしています) - 必要がなければ負担を増やしたくありません。
データを取得するために NSScanner を使用するより良い方法はありますか?
アドバイスや推奨事項は大歓迎です!