代码问题-目标c-等待字符串值出现在字符串值中
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
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;
Ok, so that's my code. It launches an SH file and reads the output. BUT, I want it to wait until "Jarvis>" appears in the string before saying and printing the result. But, it seems like with the while loop, my code freezes there. Without it it reads the normal output of launching the server.sh file, but the whole thing. Any ideas why this doesn't work?
Here is the Server.sh file:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Elijah,将您的代码编辑为如下所示:
循环中的此代码将连续从文件中读取输出数据并将其附加到当前输出,并在@“Jarvis>”时停止读取找到(它也会在找到@“Jarvis>”后终止任务,因此它不会永远运行)。
Elijah, edit your code to look like this:
This code within the loop will successively read output data from your file and append it to the current output, and stop reading when @"Jarvis>" is found (it will also kill the task after a @"Jarvis>" is found, so it doesn't keep running forever).
您想将 readDataToEndOfFile 放入循环内。否则,它会读取一次数据,检查字符串是否存在,如果在第一次读取中没有找到它,则永远循环。
You want to put the readDataToEndOfFile inside the loop. Otherwise, it reads the data once, checks for existence of your string, then loops forever if it doesn't find it in that first reading.
也许尝试按照文章中发布的代码行刷新 NSPipe:
“NSTasks、NSPipes 和读取时的死锁...”,
http://dev.notoptimal.net/2007/04/nstasks-nspipes-and-deadlocks-when.html
另一种方法可以测试NSTask 的使用NSUnbufferedIO。
您可以在 Don Yacktman 所著的《Cocoa 编程》一书中找到一些示例代码。
Maybe try flushing NSPipe along the lines of code published in the article:
"NSTasks, NSPipes, and deadlocks when reading...",
http://dev.notoptimal.net/2007/04/nstasks-nspipes-and-deadlocks-when.html
Yet another approach could test the use of NSTask & NSUnbufferedIO.
You will find some example code in the book "Cocoa Programming" by Don Yacktman.
对于 NSTask & 的非阻塞 IO 代码NSFileManager 还可以查看 DOCtor 的源代码:
另请注意,如果 stdout 是管道而不是交互式终端 (tty),则许多命令行程序(内部)会阻止将其输出缓冲到 stdout。因此,某些命令行程序具有特殊选项来行缓冲其输出,而不管将输出发送到管道还是 tty。
For non-blocking IO code for NSTask & NSFileManager also see the source code of DOCtor:
Also note that many command line programs (internally) block buffer their output to stdout if stdout is a pipe and not an interactive terminal (tty). For this reason some command line programs have special options to line-buffer their output regardless of sending output to a pipe or tty.