我应该什么时候使用 NSURLCanonicalPathKey? [英] When should I be using NSURLCanonicalPathKey?

查看:30
本文介绍了我应该什么时候使用 NSURLCanonicalPathKey?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 macOS 10.12 中,NSURLCanonicalPathKey 被添加到 NSURL.文档指出:

In macOS 10.12, NSURLCanonicalPathKey was added to NSURL. The documentation states:

作为规范绝对文件系统路径的 URL 路径.

The URL's path as a canonical absolute file system path.

除此之外,我所看到的唯一其他文档/信息来自 Swift 论坛帖子 指出:

Outside of that, the only other documentation/information I've seen of it is from a Swift Forum post that states:

您可能想看看 .canonicalPathKey (NSURLCanonicalPathKey).在 Apple 平台上,/private/中存在许多标准的 UNIXy 路径,并带有来自根的相应符号链接.所以/etc/实际上是/private/etc/.如果你不规范化路径,你可能会被这个绊倒.

You might want to take a look at .canonicalPathKey (NSURLCanonicalPathKey). On Apple platforms a lot of the standard UNIXy paths exist within /private/, with corresponding symlinks from the root. So /etc/ is actually /private/etc/. If you don’t canonicalise the paths you can get tripped up by this.

这对我来说似乎很重要,但我很惊讶它只在 10.12 中引入.我只依赖 NSURLPathKey.path 或书签数据来解析 URL,从来没有遇到过问题.

This seems like a pretty big deal to me yet I'm surprised it was only introduced in 10.12. I've only ever relied on NSURLPathKey, .path or bookmark data for resolving URLs and never had a problem.

  • 我现在是否应该在以前使用过的所有地方使用规范路径标准路径值?

  • Should I now be using the canonical path everywhere I previously used the standard path value?

如果我将路径信息作为字符串存储在数据库中,我应该存储 .pathNSURLCanonicalPathKey 的值?

If I'm storing path information in a database as a string, should I store the value of .path or NSURLCanonicalPathKey?

如果我将 NSURL 转换为字符串表示以在需要文件路径的 C/C++ 库中使用,我应该使用规范路径表示吗?

If I'm converting an NSURL to a string representation for use in a C/C++ library that requires a file path, should I use canonical path representation?

如果您向用户显示文件路径,是否应该显示规范路径?

If you're displaying the path of a file to the user, should you show the canonical path?

NSURLCanonicalPathKeyURLByStandardizingPathURLByResolvingSymlinksInPath 相比如何,它们似乎在做同样的事情或相反的事情...(?)

How does NSURLCanonicalPathKey compare to URLByStandardizingPath and URLByResolvingSymlinksInPath, which seem to sort of do the same thing or the opposite thing...(?)

这是在 macOS 10.14 上,我只考虑指向文件或文件夹的 URL.我知道书签数据可能应该存储在数据库中而不是路径中.

推荐答案

这取决于你打算如何使用路径:

It depends on how you plan to use the path:

  • 如果您只想向用户显示路径,或者将其存储以供以后使用 [NSURL fileURLWithPath:] 重新创建 URL,那么您可以继续使用常规路径收到它,因为通常你得到路径是因为用户以某种方式给你,然后最好不要改变它.
  • 当然,重新创建 URL 可以使用任一路径表示.但是如果你从/etc"创建一个 URL一个来自/private/etc",[NSURL isEqual:] 会给你 false - 如果你不喜欢那样,你必须规范化它们.
  • 因此,如果您想注册路径以便稍后再次重新识别提供给您的相同路径,那么您应该对其进行规范化.
  • 请记住,获取规范路径会增加大量处理时间(很容易加倍).这就是为什么您要避免在不必要时使用它的原因.
  • If you just want to display the path to the user, or store it for later re-creation of a URL with [NSURL fileURLWithPath:], then you can keep using the regular path as you received it, because usually you get the paths because the user gave it to you in some way, and then it's best if you do not alter it.
  • Re-creating a URL works with either path representation, of course. But if you create a URL from "/etc" and one from "/private/etc", [NSURL isEqual:] will give you false - if you do not like that, you'll have to canonicalize them.
  • So, if you want to register the path in order to re-identify the same path given to you later again, then you should canonicalize it.
  • Keep in mind that getting the canonical path adds significant processing time (it could easily double it). That's why you want to avoid using it if it's not necessary.

Unicode 规范化 也可能很重要.例如,如果文件或文件夹使用预组合 (NFC) 字符,NSURL 方法会将它们转换为 NFD 字符串.OTOH,BSD/POSIX 函数不会那样做.因此,例如,如果您从 shell 命令获取路径,然后将它们与您从 NSURL 获得的路径进行比较,由于使用 NFC 和其他 NFD 字符,它们可能计算不相等.理想情况下,如果 NSURL 或 NSFileManager 涉及到路径,那么您还应该首先通过 NSURL 传递您的 BSD 路径,以便您最终拥有相同组合格式的两种类型的路径.

Unicode normalization may also be of significance. E.g, if a file or folder uses precomposed (NFC) characters, the NSURL methods will turn them into NFD strings. OTOH, the BSD/POSIX functions won't do that. So, if you, for example, get the paths from a shell command and then compare them to paths you have from NSURLs, they may not calculate as equal due to one using NFC and the other NFD chars. Ideally, if NSURL or NSFileManager gets involved with the paths, then you should also first pass your BSD paths through NSURL so that you end up having both types of paths in the same composition format.

<头>
输入URLByStandardizingPathNSURLCanonicalPathKey
/private/var/var/private/var
/var/var/private/var

Unicode 规范化

以下示例使用准备好的 APFS 卷,其中包含具有字母ü"的预组合和分解表示以及符号链接的文件名.您可以在此处下载磁盘映像文件.

目录布局如下:

$ cd /Volumes/Canonical_Normalize_Test/
$ ls -lR
total 24
-rw-r--r--  1 user  staff   19 Dec 29 19:27 decomposed_ü
-rw-r--r--  1 user  staff   19 Dec 29 19:27 precomposed_ü
drwxr-xr-x  4 user  staff  128 Dec 29 19:36 symlink_target_dir
lrwxr-xr-x  1 user  staff   18 Dec 29 19:36 symlink_to_dir -> symlink_target_dir
-rwxr-xr-x@ 1 user  staff  763 Dec 15 16:28 unicode_composition_check.sh

./symlink_target_dir:
total 0
lrwxr-xr-x  1 user  staff  17 Dec 29 19:36 decomposed_ü -> ../decomposed_ü
lrwxr-xr-x  1 user  staff  17 Dec 29 19:36 precomposed_ü -> ../precomposed_ü

文件unicode_composition_check.sh"是一个创建两个...ü"的脚本.文件,一个名称使用 NFD,另一个名称使用 NFC(不幸的是,脚本名称不正确).

The file "unicode_composition_check.sh" is a script that creates the two "...ü" files, one name using NFD, the other NFC (the script is inadequately named, unfortunately).

输入是:

/Volumes/Canonical_Normalize_Test/symlink_to_dir/precomposed_\U00fc

(即路径包含目录符号链接并使用实际文件的 unicode 组合,即预先组合目标文件名的ü".)

(I.e. the path includes a directory symlink and uses the actual file's unicode composition, i.e. the target file name's "ü" is precomposed.)

<头>
方法结果
文件系统表示/Volumes/Canonical_Normalize_Test/symlink_to_dir/precomposed_u\U0308
URLByStandardizingPath/Volumes/Canonical_Normalize_Test/symlink_to_dir/precomposed_u\U0308
NSURLCanonicalPathKey/Volumes/Canonical_Normalize_Test/symlink_target_dir/precomposed_u\U0308
URLByResolvingSymlinksInPath/Volumes/Canonical_Normalize_Test/precomposed_u\U0308

我们看到每种方法给出了不同的结果:

We see that each method gives a different result:

  1. 它们似乎都将路径标准化为 NFD,即ü"在所有情况下都会分解.这对于常规不区分大小写的卷来说是必要和正常的,因为文件名的查找 是规范化不敏感的.但是:对于区分大小写的卷,不得更改组成,虽然我没有测试过这一点,但我假设上述所有功能都会检测卷的区分大小写模式并做出相应的行为.

  1. They all appear to normalize the path into NFD, i.e. the "ü" gets decomposed in all cases. That's necessary and normal for regular case-insensitive volumes, as the lookup for file names is normalization-insensitive. However: For case-sensitive volumes, the composition must not be changed, and while I've not tested this, I assume that all the above functions will detect the volume's case sensitivity mode and behave accordingly.

只有 NSURLCanonicalPathKey 给出正确的结果,如果我们想稍后通过路径重新识别目标项目(不管使用哪种 Unicode 组合以及路径是否包含符号链接到一个目录):它解析目录符号链接,但不是symlink_target_dir 内的最终符号链接.如果它确实解析了最终路径元素(如 URLByResolvingSymlinksInPath 所做的那样),您将无法定位符号链接文件.

Only NSURLCanonicalPathKey gives the correct result that is needed if we want to re-identify the target item later by path (indifferent to which Unicode composition is used and whether the path includes symlinks to a directory): It resolves the directory symlink but not the final symlink that's inside the symlink_target_dir. If it did resolve the final path element (like URLByResolvingSymlinksInPath does), you would not be able to target symlink files.

NSString 的 fileSystemRepresentation 不会改变路径(但将其标准化),而 NSURL 的 URLByStandardizingPath 在某些情况下会改变路径(例如通过删除/private"来自某些根文件夹).

NSString's fileSystemRepresentation does not alter the path (but normalizes it) whereas NSURL's URLByStandardizingPath alters the path in some cases (e.g. by removing "/private" from certain root folders).

只有 NSURLCanonicalPathKey 会根据实际的磁盘路径修复大写/小写.例如,从/applications"创建的 URL不会变成实际的/应用程序"任何其他函数的路径.

Only NSURLCanonicalPathKey will fix upper/lower case based on the actual on-disk path. For example, a URL created from "/applications" will not be turned into the actual "/Applications" path by any of the other functions.

结论

如果以后需要重新标识路径,无论使用哪种表示形式(规范化、指向目录的符号链接),如果需要保留实际项目,请使用 NSURLCanonicalPathKey,即使它是一个符号链接,或使用 URLByResolvingSymlinksInPath 来始终标识提供给您的任何符号链接的目标.

Conclusion

If you need to re-identify the path later, no matter which representation (normalization, symlinks to dirs) is used, use either NSURLCanonicalPathKey if you need to retain the actual item, even if it's a symlink, or use URLByResolvingSymlinksInPath to always identify the target of any symlinks given to you.

但是请注意(参见第一个示例),如果您使用 URLByResolvingSymlinksInPath,/private/var/tmp"等将变成/var/tmp";等等,这是不常用的,因为它仍然包含一个符号链接(即/var").

Note, however (see first example) that if you use URLByResolvingSymlinksInPath, "/private/var/tmp" etc. will be turned into "/var/tmp" etc., which is unusal because it then still contains a symlink (i.e. "/var").

另请记住,除非您获得规范路径,否则案例可能不正确.为了弥补这一点,比较路径要求您首先检查路径是否在不区分大小写的卷上,以便您使用正确的比较选项(并且,作为额外的复杂性,只需将路径与不区分大小写"; 选项对于 HFS+ 卷上的一些罕见脚本可能不正确,因为它们使用较旧的 Unicode 标准,该标准具有一些其他规则而不是当前 macOS 版本使用的规则).

Also keep in mind that the case may not be correct unless you get the canonical path. And to compensate for that, comparing paths requires you to first check whether the path is on a case-insensitive volume or not so that you use the correct comparison options (and, as an added complication, simply comparing paths with the "case insensitive" option may not be correct for some rare scripts on HFS+ volumes, because they use an older Unicode standard that had some other rules than the current macOS versions use).

最后,如果你只是想看看两个路径是否指向同一个文件,使用其他不依赖路径的方式更安全.请参阅此答案.如果您需要持续记住文件位置,最好使用 书签,这样即使用户在此期间重命名或移动了文件,也能找到它们.

Lastly, if you just want to see if two paths point to the same file, it's safer to use other means that do not rely on paths. See this answer. And if you need to persistently remember file locations, it's best to use bookmarks, so that they are even found if the user has renamed or moved the file in the meantime.

免责声明:所有这些发现都是凭经验发现的,在 macOS 10.13.6 和 11.1(以及两者之间的系统)上进行了测试,因此您可能需要仔细检查我的发现,如果您有不同意见,请发表评论结果.

这篇关于我应该什么时候使用 NSURLCanonicalPathKey?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆