我在OSX,Objective-C。
我有路径/ NSURL喜欢
/Users/xxx/Desktop/image2.png
但是我将它传递给第三方应用程序,该应用程序可以感知像
这样的查找程序Harddisk:Users:Desktop:image2.png
是否有任何方法(我找不到)来转换这样的pathes或将它们从NSURL中取出(如果可能的话,不进行字符串修改)?
在AppleScript中它是
return POSIX file "/Users/xxx/Desktop/image2.png" --> Harddisk:Users:xxx:Desktop:image2.png
编辑:这几乎是一样的:Cocoa path string conversion 不幸的是,该方法已被弃用......
答案 0 :(得分:2)
目前没有(简单)替代方案。
不推荐使用函数CFURLCopyFileSystemPath
,仅弃用枚举案例kCFURLHFSPathStyle
,但原始值1
仍然有效并避免出现警告。
我正在使用此类NSString
@implementation NSString (POSIX_HFS)
- (NSString *)hfsPathFromPOSIXPath
{
CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)[NSURL fileURLWithPath:self], 1);
return (NSString *)CFBridgingRelease(hfsPath);
}
@end
该功能也适用于Swift。 Swift版本稍微复杂一些,并且隐式添加了代表字典的尾随分号,这里是URL
的扩展名:
extension URL {
func hfsPath() -> String?
{
if let cfpathHFS = CFURLCopyFileSystemPath(self as CFURL, CFURLPathStyle(rawValue: 1)!) { // CFURLPathStyle.CFURLHFSPathStyle)
let pathHFS = cfpathHFS as String
do {
let info = try self.resourceValues(forKeys: [.isDirectoryKey, .isPackageKey])
let isDirectory = info.isDirectory!
let isPackage = info.isPackage!
if isDirectory && !isPackage {
return pathHFS + ":" // directory, not package
}
} catch _ {}
return pathHFS
}
return nil
}
}
答案 1 :(得分:1)
Vadians的回答比这个好 - 但如果不推荐使用vadians方法,这将是另一种选择。想法是使用applescripts方法通过NSString类别的osascript轻松调用HFS路径。
NSString类别(信用:https://stackoverflow.com/a/19014463/4591992)
@implementation NSString (ShellExecution)
- (NSString*)runAsCommand {
NSPipe* pipe = [NSPipe pipe];
NSTask* task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/sh"];
[task setArguments:@[@"-c", [NSString stringWithFormat:@"%@", self]]];
[task setStandardOutput:pipe];
NSFileHandle* file = [pipe fileHandleForReading];
[task launch];
NSString* result = [[NSString alloc] initWithData:[file readDataToEndOfFile] encoding:NSUTF8StringEncoding];
return result;
}
@end
此案例的用法:
NSString* posixToHFS = [NSString stringWithFormat:@"osascript -e 'POSIX file \"%@\" as text'",filePath];
filePath = [posixToHFS runAsCommand];
答案 2 :(得分:0)
在我自己的测试中(在10.13.6、10.14.6和10.15b7上),@ vadian的解决方案不适用于文件夹名称组件包含“ /”的路径(在Finder中查看时),然后出现在POSIX路径中为“:”,在HFS路径中为“ /”。
这是一个快速测试程序,您可以通过在Xcode中创建新的“命令行”项目来构建该程序:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *posixPath = @"/EndsInSlash:";
NSURL *url = [NSURL fileURLWithPath:posixPath];
if (url == nil) {
NSLog(@"Oops, this went wrong");
} else {
CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)url, 1);
NSString *res = (NSString *)CFBridgingRelease (hfsPath);
NSLog(@"HFS path: <%@>", res);
}
}
return 0;
}
运行它时,您可能会看到打印正确的结果,即以“ /”结尾的路径。但是,仅当文件夹不存在时,该方法才有效。因此,在根文件夹中创建一个名为“ EndsInSlash /”的文件夹(而不是文件!),然后再次运行该应用程序-现在生成的路径不再以“ /”结尾。
下面是一个“智能”函数,它会尽可能使用更快的CFURLCopyFileSystemPath()
函数,即,除非POSIX路径中出现“:”-在这种情况下,它通过将POSIX路径进入其组件,将它们分别转换(将“:”替换为“ /”),在卷名之前添加,然后再次合并这些组件。尽管已弃用警告,但即使在macOS 10.15(Catalina)上,这似乎也能正常工作。
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
static NSString* stringWithHFSUniStr255(const HFSUniStr255* hfsString)
{
CFStringRef stringRef = FSCreateStringFromHFSUniStr(nil, hfsString);
NSString* result = CFBridgingRelease(stringRef);
return result;
}
NSString* hfsPathFromPOSIXPath (NSString *posixPath)
{
if (posixPath == nil) return @"";
if ([posixPath containsString:@":"]) {
// slow version, but can handle ":" appearing in path components
NSString *result = nil;
FSRef ref;
Boolean isDir;
if (FSPathMakeRef ((const UInt8*)posixPath.UTF8String, &ref, &isDir) == noErr) {
HFSUniStr255 elemName;
FSCatalogInfo catInfo;
NSMutableArray<NSString*> *elems = [NSMutableArray arrayWithCapacity:16];
while (FSGetCatalogInfo (&ref, kFSCatInfoNodeID, &catInfo, &elemName, nil, &ref) == noErr) {
[elems insertObject: stringWithHFSUniStr255(&elemName) atIndex:0];
if (catInfo.nodeID == 2) break;
}
result = [elems componentsJoinedByString:@":"];
}
return result;
} else {
// see https://stackoverflow.com/a/45085776/43615
NSURL *url = [NSURL fileURLWithPath:posixPath];
if (url == nil) {
// could not convert because the path doesn't exist
return nil;
}
CFStringRef hfsPath = CFURLCopyFileSystemPath((CFURLRef)url, kCFURLHFSPathStyle);
return (NSString *)CFBridgingRelease (hfsPath);
}
}
#pragma clang diagnostic pop
讨论与AppleScript相关的错误,并解决:https://forum.latenightsw.com/t/xxx/2097
向苹果提交的错误报告:http://www.openradar.me/radar?id=4994410022436864