谁能告诉我如何将标准输出重定向到 NSTextView?
NSLog打印的信息是否属于std?
谢谢
下面的代码用于dup2
将标准输出插入NSPipe
对象的写入端。使用 GCD 调度源观察读取端,该调度源从管道读取数据并将其附加到文本视图。
NSPipe* pipe = [NSPipe pipe];
NSFileHandle* pipeReadHandle = [pipe fileHandleForReading];
dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stdout));
dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, [pipeReadHandle fileDescriptor], 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
dispatch_source_set_event_handler(source, ^{
void* data = malloc(4096);
ssize_t readResult = 0;
do
{
errno = 0;
readResult = read([pipeReadHandle fileDescriptor], data, 4096);
} while (readResult == -1 && errno == EINTR);
if (readResult > 0)
{
//AppKit UI should only be updated from the main thread
dispatch_async(dispatch_get_main_queue(),^{
NSString* stdOutString = [[NSString alloc] initWithBytesNoCopy:data length:readResult encoding:NSUTF8StringEncoding freeWhenDone:YES];
NSAttributedString* stdOutAttributedString = [[NSAttributedString alloc] initWithString:stdOutString];
[self.logView.textStorage appendAttributedString:stdOutAttributedString];
});
}
else{free(data);}
});
dispatch_resume(source);
NSLog(@"...")
虽然不输出到stdout
- 它打印到stderr
. 如果您想将其重定向到您的文本视图中,请更改
dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stdout));
至
dup2([[pipe fileHandleForWriting] fileDescriptor], fileno(stderr));
我知道这个问题是关于objective-c的,但我想我会发布一个快速的答案,以防万一帮助别人。
let pipefd = UnsafeMutablePointer<Int32>.allocate(capacity: 8)
pipe(pipefd)
dup2(pipefd[1], fileno(stdout))
// Print something here
let buf = UnsafeMutableRawPointer.allocate(byteCount: 1024, alignment: 0)
read(pipefd[0], buf, 100)
close(pipefd[1])
let output = self.ptrToString(pointer: buf)
if output != "" {
// Do something with output
}
buf.deallocate()
pipefd.deallocate()
这是我用来将指针转换为字符串的函数:
func ptrToString (pointer buf: UnsafeMutableRawPointer) -> String {
let filteredArray = Array(UnsafeBufferPointer(start: buf.assumingMemoryBound(to: UInt8.self), count: 1024)).filter { item in
return item != 0
}
return filteredArray
.map { String(UnicodeScalar(UInt8($0))) }
.joined()
.components(separatedBy: "\n")[0]
}
适用于 Swift 4
如果目标是仅处理您的 NSLog 输出,而不是系统生成的错误日志,还有另一种方法可以做到这一点,这里是一个覆盖 NSLog 的代码。此代码仅在 stderr 上打印日志和一些额外信息,而不是通常的 NSLog 输出,但您可以在 HyperLog 函数中进行任何适合您需要的更改:
HyperLog.h
#import <Foundation/Foundation.h>
#ifdef HYPER_LOG
#define NSLog(args...) HyperLog(__FILE__,__LINE__,__PRETTY_FUNCTION__,args);
#else
#define NSLog(x...)
#endif
void HyperLog(const char *file, int lineNumber, const char *functionName, NSString *format, ...);
超级日志
#import "HyperLog.h"
void HyperLog(const char *file, int lineNumber, const char *functionName, NSString *format, ...)
{
va_list ap;
va_start (ap, format);
if (![format hasSuffix: @"\n"])
{
format = [format stringByAppendingString: @"\n"];
}
NSString *body = [[NSString alloc] initWithFormat:format arguments:ap];
va_end (ap);
NSString *fileName = [[NSString stringWithUTF8String:file] lastPathComponent];
char mesg[8192]="\0";
NSDate *now =[NSDate date];
NSString *dateString = [NSDateFormatter localizedStringFromDate:now dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterMediumStyle];
if ( sprintf( mesg, "<%s.%03.0f> : %s\n<%s : %d - %s>\n", [dateString UTF8String],roundf(fmod( [now timeIntervalSinceReferenceDate], 1 ) * 1000), [body UTF8String], [fileName UTF8String],
lineNumber,
functionName) < 0 ) printf("message creation failed\n");
fprintf(stderr, "%s", mesg );
}
然后,您只需将这两行放在任何程序文件的顶部即可使其正常工作
#define HYPER_LOG
#import "HyperLog.h"
我尝试使用 Thomas 的上述代码将系统生成的错误日志的结果数据写入使用 C 函数的文本文件,该文件在其他上下文中正常工作,但它保持并崩溃,并且错误原因丢失在过程。任何人都知道为什么?