Cocoa 如何将nslog输出重定向到文件而不是控制台

Cocoa 如何将nslog输出重定向到文件而不是控制台,cocoa,xcode,macos,nslog,Cocoa,Xcode,Macos,Nslog,我在OSX上运行了cocoa应用程序。我使用了NSLog进行调试。现在我想将日志语句重定向到文件而不是控制台 我使用过这种方法,但它会导致在控制台和文件中进行日志记录 - (BOOL)redirectNSLog { // Create log file [@"" writeToFile:@"/NSLog.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil]; id fileHandle = [NSFile

我在OSX上运行了cocoa应用程序。我使用了NSLog进行调试。现在我想将日志语句重定向到文件而不是控制台

我使用过这种方法,但它会导致在控制台和文件中进行日志记录

- (BOOL)redirectNSLog
{
    // Create log file
    [@"" writeToFile:@"/NSLog.txt" atomically:YES encoding:NSUTF8StringEncoding error:nil];
    id fileHandle = [NSFileHandle fileHandleForWritingAtPath:@"/NSLog.txt"];
    if (!fileHandle)    return NSLog(@"Opening log failed"), NO;
    [fileHandle retain];

    // Redirect stderr
    int err = dup2([fileHandle fileDescriptor], STDERR_FILENO);
    if (!err)   return  NSLog(@"Couldn't redirect stderr"), NO;

    return  YES;
}

是否可以在控制台中不包含log语句,而只包含在文件中???

NSLog
用于登录控制台。您需要定义自己的函数
MyLog
或其他任何函数,并将所有出现的
NSLog
替换为
MyLog

步骤1:在AppDelegate中包含以下函数:

 - (void) redirectConsoleLogToDocumentFolder
 {
       NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                     NSUserDomainMask, YES);
       NSString *documentsDirectory = [paths objectAtIndex:0];
       NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"];
       freopen([logPath fileSystemRepresentation],"a+",stderr);
 }
步骤2:在函数ApplicationIDFinishLaunchingWithOptions开始时调用此函数


就是这样,每个NSLog()现在都会被重定向到这个console.log文件,您可以在documents目录中找到它。

您可能会感兴趣。它是一个非常灵活的日志框架,适用于Mac OS X和iOS。一条日志语句不仅可以发送到控制台,还可以同时发送到文件。另外,它实际上比NSLog更快。我在一个项目中使用了它,该项目对OSX和iOS都有相同的代码。

最近我遇到了类似的要求,我就是这样做的

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // Override point for customization after application launch.

    [self redirectConsoleLogToDocumentFolder];


    return YES;
}

- (void) redirectConsoleLogToDocumentFolder
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                         NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.txt"];
    freopen([logPath fileSystemRepresentation],"a+",stderr);
} 
现在如果你想把这个控制台给用户

-(void)displayLog{

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths firstObject];
    NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.txt"];

    NSError *err = nil;
    NSString *fileContents = [NSString stringWithContentsOfFile:logPath
                                                       encoding:NSUTF8StringEncoding
                                                          error:&err];
    if (fileContents == nil) {
        NSLog(@"Error reading %@: %@", logPath, err);
    } else {
        self.textView.text = fileContents;
    }

}

我确实定义了我的函数,并用我定义的函数替换了NSLog。但我仍然在Cosole应用程序和我创建的日志文件中看到了日志。我喜欢为日志定义自己的函数。确认文件创建工作正常。我已经测试了这段代码,它是有效的。链接的代码将文件写入根目录,我将其更改为本地主目录。肯定是比我的更好的答案:)将
cStringWithEncoding:NSASCII…
更改为
fileSystemRepresentation
。人们可以在路径中使用非ASCII字母(这在
~/Documents/
上不太可能),太棒了!它也适用于iOS应用程序。您将在如下目录中找到console.log:
/Users/Fernando/Library/Application Support/iPhone Simulator/6.1/Applications/18FB521C-A782-44E4-9DFA-B963FD7DC44B/Documents/console.log
谢谢:-)要关闭/停止在控制台中写入输出,请使用
fflush(fileP);fclose(fileP)
要获取文件指针,请使用
file*fileP=freopen([logPath..
在上面的方法中,并保留此指针。通过这种方式,您可以围绕对此输出文件的特定流/nslog调用进行包装。您能解释一下为什么流来自strwhy,而不是freopen中的stdout吗?谢谢dbainbridge。我对我的应用程序使用相同的框架。CocoaLumberjack是否重定向nslog?我搜索了它的code base没有freopen的迹象。我想没有。最好用CoCoalLumberJack的正确DDLog*语句替换NSLog。CoCoalLumberJack也使用GCD,因此比简单地用另一种方法替换NSLog要快得多。这正是我快速调试所需的:-)您可以使用
tail-f console.log
runtime查看日志,或者使用
tail-f console.log|grep“xxx”