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

查看:102
本文介绍了我什么时候应该使用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.

除此之外,我看到的唯一其他文档/信息来自

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?

如果我将路径信息以字符串形式存储在数据库中,我应该存储 .path NSURLCanonicalPathKey ?

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?

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

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.

<身体>
输入 URLByStandardizingPath NSURLCanonicalPathKey
/private/var /var /private/var
/var /var /private/var

Unicode规范化

以下示例使用准备好的APFS卷,该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.)

<身体>
方法结果
fileSystemRepresentation /卷/Canonical_Normalize_Test/symlink_to_dir/precomposed_u \ U0308
URLByStandardizingPath /卷/Canonical_Normalize_Test/symlink_to_dir/precomposed_u \ U0308
NSURLCanonicalPathKey /卷/Canonical_Normalize_Test/symlink_target_dir/precomposed_u \ U0308
URLByResolvingSymlinksInPath /卷/Canonical_Normalize_Test/precomposed_u \ U0308

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

We see that each method gives a different result:

  1. 它们似乎都可以标准化进入NFD的路径,即ü"在所有情况下都会分解.对于不区分大小写的常规卷来说,这是必需且正常的,因为文件名的 lookup 对规范不敏感.但是:对于区分大小写的卷,不得更改其组成,尽管我没有对此进行测试,但我假设上述所有功能都将检测到该卷的区分大小写模式并相应地执行操作.

  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组成无关,并且路径是否包含指向以下位置的符号链接)目录):它解析目录符号链接,但解析 not 位于 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 会根据实际的磁盘路径修复大小写.例如,从"/应用程序"创建的URL被添加到URL.不会变成实际的"/Applications"其他功能的路径.

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天全站免登陆