【问题标题】:NSTask output into a listNSTask 输出到列表中
【发布时间】:2019-12-13 06:07:16
【问题描述】:

我尝试使用 NSTask 列出 Director 中的文件/文件夹,如何将每行的输出放入列表中?我尝试打印出来,它只显示第一行。

NSTask * list = [[NSTask alloc] init];
[list setLaunchPath:@"/bin/ls"];
[list setCurrentDirectoryPath:@"/"];

NSPipe * out = [NSPipe pipe];
[list setStandardOutput:out];

[list launch];
[list waitUntilExit];

NSFileHandle * read = [out fileHandleForReading];
NSData * dataRead = [read readDataToEndOfFile];
NSString * stringRead = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding]];
HBLogDebug(@"PATH: %@", stringRead); //Only the first line printed

NSMutableArray *outputlist = [[NSMutableArray alloc] init];

//This part here I'm not so sure how to proceed since it's only one line, I expected multiples line
for (NSString *s in stringRead?dataRead?){
    [outputlist addObject:s];
}

提前致谢!

【问题讨论】:

  • waitUntilExit 在使用 fileHandleForReading 获得输入之前,也许只是放弃前者,这样你的进程在你尝试获得它的输出之前还没有死掉?也就是说,对于这个特定任务,您最好使用NSFileManager documentationDiscovery Directory Contents 部分中的一种方法。 HTH
  • 删除waitUntilExit 将冻结运行此代码的系统/UI,不幸的是。关于NSFileManager,这将起作用,但仅出于此目的,上面的代码只是一个示例(ls
  • 如前所述,您可以使用 NSFileHandle 的 readToEndOfFileInBackgroundAndNotify 在后台运行任务并发出通知。从那里只需在行终止符(\n 和/或 \r)处分解结果字符串,使用 NSString 的 componentsSeparatedByStringcomponentsSeparatedByCharactersInSet 将其放入数组中。
  • @GregorIsack - 删除 waitUntilExit 不应该冻结你的 UI,如果有的话它可能会产生相反的效果 - 在同步读取之前等待 可能会导致挂起。我添加了一些工作代码作为答案,它可以帮助您找出导致冻结的代码的不同之处。 HTH

标签: objective-c


【解决方案1】:

这里的 cmets 之后是一个在 Xcode 中构建的工作示例。 runCommand 方法基于 this answer 更新并可选使用 waitUntilExit,因此您可以看到不使用它不会冻结应用程序。

@implementation AppDelegate

// Arguments:
//    atPath: full pathname of executable
//    arguments: array of arguments to pass, or nil if none
// Return:
//    the standard output, or nil if any error
//
// This method blocks the caller until the called command completes
// (due to both readDataToEndOfFile & waitUntilExit)
// If this an issue either run on a thread or use the asynchronous read alternatives to readDataToEndOfFile
// If there is no need to check terminatation status the waitUntilExit and terminationStatus can be skipped
// by defining RUN_COMMAND_CHECK_TERMINATION as 0

#define RUN_COMMAND_CHECK_TERMINATION 0

+ (NSString *) runCommand:(NSString *)atPath withArguments:(nullable NSArray *)arguments
{
   NSTask *task = [NSTask new];
   NSPipe *pipe = [NSPipe new];

   task.standardOutput = pipe;     // pipe standard output

   task.launchPath = atPath;       // set path
   if(arguments)
      task.arguments = arguments;  // set arguments

   [task launch];                  // execute

   NSData *data = pipe.fileHandleForReading.readDataToEndOfFile; // read standard output

#if RUN_COMMAND_CHECK_TERMINATION
   [task waitUntilExit];           // verify process has exited to prevent terminationStatus faulting
                                   // must do this *after* read otherwise if pipe fills wait can block forever

   if (task.terminationStatus != 0) // check termination status & have output
      return nil;
#endif

   if (data == nil) // check termination status & have output
      return nil;

   return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; // return stdout as string
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
   NSString *stringRead =  [AppDelegate runCommand:@"/bin/ls" withArguments:@[@"/"]];
   NSLog(@"PATH: %@", stringRead);
   NSArray *outputList = [stringRead componentsSeparatedByString:@"\n"]; // Note: will produce an empty last line, removing that is left as an exercise
   NSLog(@"Lines: %@", outputList);
}

@end

如果您的代码被冻结为 HBLogDebug 的奇怪内容(因为上面使用了 NSLog),或者您必须找出代码中的其他内容。

HTH

【讨论】:

    【解决方案2】:

    1.使用NSLog代替HBLogDebug

    `NSLog(@"PATH: %@", stringRead); //it prints all lines in my case`
    
    1. 用换行符分割字符串读取

      for (NSString *s in [stringRead componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]]){ [outputlist addObject:s]; }

    2. 在 Objective-c for MACOS 中列出文件的更好方法

      [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"<path>" error:nil]

    【讨论】:

    • [outputlist addObjectsFromArray:…]代替for (NSString *s in …) [outputlist addObject:s]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    • 2015-06-15
    • 1970-01-01
    • 2013-05-30
    相关资源
    最近更新 更多