cString(使用:.utf8)和withUnsafeFileSystemRepresentation(_ :)如何相互不同?

时间:2017-11-12 20:23:51

标签: c swift string pointers

请考虑以下代码段:

let url = FileManager.default.homeDirectoryForCurrentUser

let cString1 = url.absoluteString.cString(using: .utf8)

let cString2 = url.withUnsafeFileSystemRepresentation { $0 }

我们可以期望cString1cString2是相等的C字符串吗?

withUnsafeFileSystemRepresentation(_:)的文档中所述,它将Swift字符串转换为具有UTF8编码的C字符串。这与cString(using: .utf8)正在做的完全相同。

两者都将Swift字符串转换为UnsafePointer<Int8>?类型。

只有Xcode会将cString(using:)的返回类型显示为[CChar]?,其中CCharInt8的类型别名。据我所知,Swift数组也可以传递给UnsafePointer

大多数情况下,我只使用cString(using: .utf8),一切都很好但是在极少数情况下我需要因某种原因使用withUnsafeFileSystemRepresentation(_:),否则C函数不理解字符串。

那么我在这里失踪的区别是什么?

1 个答案:

答案 0 :(得分:4)

来自Apple File System Guide FAQ

  

为避免在文件名中使用不匹配的Unicode规范化(对于iOS 10.3.0,10.3.1和10.3.2)在代码中引入错误,请执行以下操作:

     
      
  • 在与文件系统交互时,使用NSFileManager和NSURL等高级Foundation API。
  •   
  • 使用POSIX open(2)等低级文件系统API创建和打开文件时,或者在文件系统外部存储文件名时,使用NSURL对象的fileSystemRepresentation属性。
  •   

如果路径需要withUnsafeFileSystemRepresentation() 传递给POSIX调用,例如open()stat()unlink()getxattr(),...并保证正确的Unicode 系统调用的规范化表单已创建。

简单示例(删除文件,如果存在,忽略错误):

url.withUnsafeFileSystemRepresentation {
    _ = unlink($0)
}

请参阅Write extend file attributes swift example了解&#34;真实&#34;例。注意

let cString2 = url.withUnsafeFileSystemRepresentation { $0 }

无效,因为C字符串在块的上下文之外无效。

这是一个证明两个API可以提供的示例 不同的C字符串:

let path = "Café".precomposedStringWithCanonicalMapping
let url = URL(fileURLWithPath: path)

path.withCString { s1 in
    url.withUnsafeFileSystemRepresentation { s2 in
        print(strcmp(s1, s2) == 0) // false
    }
}

建议使用Foundation API(FileManagerURL,...), 然后你不必关心文件系统表示。