2016-09-22 20 views
0

如何在macOS上以字符串的形式获取桌面目录的文件路径。 我需要它在纯C或一些C级框架中完成。OS X:我如何才能在macOS上获得桌面目录的路径?

+0

检查了这一点:http://stackoverflow.com/questions/5319976/how-to-find-desktop-path-using-c-language – d3r1ck

+0

它是'/用户/用户名/桌面' – Barmar

+0

如果您可能会对项目中的Objective-C文件感到困扰,可以使用[NSHomeDirectory()stringByAppendingPathComponent:@“Desktop”]来获取它。然后,您可以将结果复制到C字符串。否则,您可以很容易地将'getenv(“HOME”)''和'Desktop''与'asprintf'连接起来,但是如果没有定义'$ HOME',那么您运气不好。 – zneak

回答

0

如果你坚持只使用C(为什么?),那么你唯一的选择是使用失效的API:如果你需要一个CFURL,而不是一个路径

#include <limits.h> 
#include <CoreServices/CoreServices.h> 

... 

FSRef fsref; 
UInt8 path[PATH_MAX]; 

if (FSFindFolder(kUserDomain, kDesktopFolderType, kDontCreateFolder, &fsref) == noErr && 
    FSRefMakePath(&fsref, path, sizeof(path)) == noErr) 
{ 
    // Make use of path 
} 

,您可以使用CFURLCreateFromFSRef()而非FSRefMakePath()

其实,在研究这个时,我发现了一个我不知道的API。显然,你可以使用这个,这显然来自于可可,但只使用了C型:

#include <limits.h> 
#include <NSSystemDirectories.h> 

char path[PATH_MAX]; 
NSSearchPathEnumerationState state = NSStartSearchPathEnumeration(NSDesktopDirectory, NSUserDomainMask); 
while (state = NSGetNextSearchPathEnumeration(state, path)) 
{ 
    // Handle path 
} 

API的形式是,它可能(在循环的每个迭代之一)返回多个结果,但你应该这里只有一个具体用途。在这种情况下,您可以将while更改为和if

请注意,使用此API,用户域中目录的返回路径可能使用“〜”而不是用户主目录的绝对路径。你必须自己解决。

+0

肯,我喜欢在回答中的信息,但我想你忽略了最简单的方式...因为MacOS的有BSD在它的核心,真的没有必要去超越POSIX。 – Myst

+0

@Myst:不能保证用户的桌面位于'$ HOME/Desktop'。它可能被命名为其他地方,可能位于不同的位置。这就是这些API存在的原因。参见[苹果的文档(https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Strings/Articles/ManipulatingPaths.html#//apple_ref/doc/uid/20000152-SW2):“请注意,通常应使用NSSearchPathForDirectoriesInDomains函数为当前用户定位标准目录[而不是将硬编码目录与主目录连接起来]“。 –

+0

肯,我不知道你是对这个......没有办法,我知道的是,'Desktop'文件夹可以移动从主文件夹的根目录了。它始终是'〜/ Desktop'文件夹...人们试图移动它,并且 - 据我所知,创建别名与人们一样近......可以移动'$ HOME'根目录,而不是'$ HOME'中的结构。对于Apple Docs:“用户域中返回的目录路径将包含”〜“来引用用户的目录”...因此,NSGetNextSearchPathEnumeration不完整。 – Myst

0

这里是一个简短的功能,适用于多种基于Unix的系统不仅仅是MacOS和返回当前用户的桌面文件夹:

#include <limits.h> 
#include <stdlib.h> 
/** 
* Returns the path to the current user's desktop. 
*/ 
char *path2desktop(void) { 
    static char real_public_path[PATH_MAX + 1] = {0}; 
    if (real_public_path[0]) 
    return real_public_path; 
    strcpy(real_public_path, getenv("HOME")); 
    memcpy(real_public_path + strlen(real_public_path), "/Desktop", 8); 
    return real_public_path; 
} 

的路径将只计算一次。

如果该函数被多次调用,则会返回旧结果(除非第一个调用被保护,否则将返回该结果(不是线程安全的)。

+0

这是不可靠的,因为我在我对你的回复中解释我的答案。 –

+0

它似乎工作,但getenv(“家”)我认为不是最好的解决方案,所以我宁愿去可可应用程序,将返回这个桌面路径到C应用程序; / –

0

我以这样的方式Objective-C中的使用已结束:

// 
// main.m 
// search_path_for_dir 
// 
// Created by Michal Ziobro on 23/09/2016. 
// Copyright © 2016 Michal Ziobro. All rights reserved. 
// 

#import <Foundation/Foundation.h> 

int main(int argc, const char * argv[]) { 
    if(argc != 3) 
     return 1; 

    @autoreleasepool { 
     NSArray *paths = NSSearchPathForDirectoriesInDomains(atoi(argv[1]), atoi(argv[2]), YES); 
     NSString *path = [paths objectAtIndex:0]; 
     [path writeToFile:@"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:nil]; 
    } 
    return 0; 
} 

和不同于命令线I可以以这种方式执行该程序:

./search_path_for_dir 12 1 

12 - NSDesktopDirectory

1 - NSUserDomainMask

我在C中使用脚本,它从命令行执行该程序并检索其输出。

这里的C例程调用这个迷你可可应用程序:

CFStringRef FSGetFilePath(int directory, int domainMask) { 

    CFStringRef scheme = CFSTR("file:///"); 
    CFStringRef absolutePath = FSGetAbsolutePath(directory, domainMask); 

    CFMutableStringRef filePath = CFStringCreateMutable(NULL, 0); 
    if (filePath) { 

     CFStringAppend(filePath, scheme); 
     CFStringAppend(filePath, absolutePath); 

    } 

    CFRelease(scheme); 
    CFRelease(absolutePath); 

    return filePath; 
} 

CFStringRef FSGetAbsolutePath(int directory, int domainMask) { 

    char path_cmd[BUF_SIZE]; 
    sprintf(path_cmd, "./tools/search_path_for_dir %d %d", directory, domainMask); 
    char *path = exec_cmd(path_cmd); 

    return CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); 
} 
相关问题