Проблема с кодом - цель c - ожидание появления строкового значения в строковом значении - PullRequest
1 голос
/ 13 августа 2010
task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObject:@"/applications/jarvis/brain/server.sh"]];
[task setCurrentDirectoryPath:@"/"];

NSPipe *outputPipe = [NSPipe pipe];
[task setStandardInput:[NSPipe pipe]];
[task setStandardOutput:outputPipe];

[task launch];

NSMutableString *outputString = [NSMutableString string];
while ([outputString rangeOfString:@"Jarvis>"].location == NSNotFound) {
    [outputString appendString:[[[NSString alloc] initWithData:[[outputPipe fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding] autorelease]];
     }

NSArray* substrings = [outputString componentsSeparatedByString:@"Jarvis>"];
NSString* finalCharlieOutputNSTask = [substrings lastObject];
NSSpeechSynthesizer * syn = [[NSSpeechSynthesizer alloc] init];
[syn startSpeakingString:finalCharlieOutputNSTask]; 
self.charlieOutput.stringValue = finalCharlieOutputNSTask;

Хорошо, это мой код. Он запускает файл SH и читает вывод. НО, я хочу подождать, пока в строке не появится «Jarvis>», прежде чем сказать и напечатать результат Но, похоже, что с циклом while мой код там зависает. Без этого он читает нормальный вывод запуска файла server.sh, но все это. Есть идеи, почему это не работает?

Вот файл Server.sh:

echo Starting Jarvis Program D.
ALICE_HOME=.
SERVLET_LIB=lib/servlet.jar
ALICE_LIB=lib/aliceserver.jar
JS_LIB=lib/js.jar

# Set SQL_LIB to the location of your database driver.
SQL_LIB=lib/mysql_comp.jar

# These are for Jetty; you will want to change these if you are using a different http server.
 HTTP_SERVER_LIBS=lib/org.mortbay.jetty.jar

 PROGRAMD_CLASSPATH=$SERVLET_LIB:$ALICE_LIB:$JS_LIB:$SQL_LIB:$HTTP_SERVER_LIBS
 java -classpath $PROGRAMD_CLASSPATH -Xms64m -Xmx128m org.alicebot.server.net.AliceServer $1

Ответы [ 4 ]

1 голос
/ 13 августа 2010

Элайджа, отредактируй свой код так:

...
[task launch];

NSMutableString *outputString = [NSMutableString string];
while ([outputString rangeOfString:@"Jarvis>"].location == NSNotFound) {
    [outputString appendString:[[[NSString alloc] initWithData:[[outputPipe fileHandleForReading] readDataToEndOfFile] encoding:NSUTF8StringEncoding] autorelease];
}

if ([task isRunning]) {
    [task terminate];
}

NSArray *subStrings = [outputString componentsSeparatedByString:@"Jarvis>"];
...

Этот код в цикле будет последовательно считывать выходные данные из вашего файла и добавлять их к текущему выводу, а также останавливать чтение, когда найден @ "Jarvis>" (он также завершит задачу после того, как @ "Jarvis>" будет найден, так что он не будет работать вечно).

1 голос
/ 17 августа 2010

Может быть, попробуйте сбросить NSPipe вдоль строк кода, опубликованного в статье:

"NSTasks, NSPipes и взаимоблокировки при чтении ...",

http://dev.notoptimal.net/2007/04/nstasks-nspipes-and-deadlocks-when.html

Еще один подход может проверить использование NSTask & NSUnbufferedIO.

Вы можете найти пример кода в книге "Программирование какао" Дона Яктмана.

# http://www.cocoaprogramming.net
# http://www.cocoaprogramming.net/CocoaProgramming-20021010.tgz

open -e CocoaProgramming-20021010/Chapter\ 24/Animal/AnimalController.h \
        CocoaProgramming-20021010/Chapter\ 24/Animal/AnimalController.m \
        CocoaProgramming-20021010/Chapter\ 24/Calendar/CalendarController.m

# for yet another try with sample code using waitForDataInBackgroundAndNotify see:
# http://cocoawithlove.com/2009/05/invoking-other-processes-in-cocoa.html

open -e OpenFileKiller/NSTask+OneLineTasksWithOutput.m
# --> [standardOutputFile waitForDataInBackgroundAndNotify];
1 голос
/ 13 августа 2010

Вы хотите поместить readDataToEndOfFile в цикл.В противном случае он считывает данные один раз, проверяет наличие вашей строки, а затем зацикливается, если не обнаруживает их при первом чтении.

0 голосов
/ 18 августа 2010

Для неблокирующего кода ввода-вывода для NSTask & NSFileManager также см. Исходный код DOCtor:

# http://www.stone.com/DOCtor/
# http://www.stone.com/DOCtor/DOCtor.tar.gz

open -e DOCTor/NSFileHandle_CFRNonBlockingIO.h \
        DOCTor/NSFileHandle_CFRNonBlockingIO.m \
        DOCTor/NSFileManager-Extensions.h \
        DOCTor/NSFileManager-Extensions.m

Также обратите внимание, что многие программы командной строки (внутренне) блокируют свой вывод на стандартный вывод, если stdoutтруба а не интерактивный терминал (tty).По этой причине некоторые программы командной строки имеют специальные опции для буферизации строк своего вывода независимо от отправки вывода в канал или tty.

tcpdump -l
grep --line-buffered
...
...