编写扩展文件属性的swift例子
我正在寻找一个解决scheme,以迅速添加文件的扩展文件属性。 我检查了这个链接写扩展的文件属性 ,但解决scheme是在客观的C,我需要一个解决scheme,迅速。
这里有一个可能的实现在Swift 3中作为URL
的扩展,使用方法来获取,设置,列出和删除文件的扩展属性。 (Swift 2的代码可以在下面find。)
extension URL { /// Get extended attribute. func extendedAttribute(forName name: String) throws -> Data { let data = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> Data in // Determine attribute size: let length = getxattr(fileSystemPath, name, nil, 0, 0, 0) guard length >= 0 else { throw URL.posixError(errno) } // Create buffer with required size: var data = Data(count: length) // Retrieve attribute: let result = data.withUnsafeMutableBytes { getxattr(fileSystemPath, name, $0, data.count, 0, 0) } guard result >= 0 else { throw URL.posixError(errno) } return data } return data } /// Set extended attribute. func setExtendedAttribute(data: Data, forName name: String) throws { try self.withUnsafeFileSystemRepresentation { fileSystemPath in let result = data.withUnsafeBytes { setxattr(fileSystemPath, name, $0, data.count, 0, 0) } guard result >= 0 else { throw URL.posixError(errno) } } } /// Remove extended attribute. func removeExtendedAttribute(forName name: String) throws { try self.withUnsafeFileSystemRepresentation { fileSystemPath in let result = removexattr(fileSystemPath, name, 0) guard result >= 0 else { throw URL.posixError(errno) } } } /// Get list of all extended attributes. func listExtendedAttributes() throws -> [String] { let list = try self.withUnsafeFileSystemRepresentation { fileSystemPath -> [String] in let length = listxattr(fileSystemPath, nil, 0, 0) guard length >= 0 else { throw URL.posixError(errno) } // Create buffer with required size: var data = Data(count: length) // Retrieve attribute list: let result = data.withUnsafeMutableBytes { listxattr(fileSystemPath, $0, data.count, 0) } guard result >= 0 else { throw URL.posixError(errno) } // Extract attribute names: let list = data.split(separator: 0).flatMap { String(data: Data($0), encoding: .utf8) } return list } return list } /// Helper function to create an NSError from a Unix errno. private static func posixError(_ err: Int32) -> NSError { return NSError(domain: NSPOSIXErrorDomain, code: Int(err), userInfo: [NSLocalizedDescriptionKey: String(cString: strerror(err))]) } }
用法示例:
let fileURL = URL(fileURLWithPath: "/path/to/file") let attr1 = "com.myCompany.myAttribute" let attr2 = "com.myCompany.otherAttribute" let data1 = Data(bytes: [1, 2, 3, 4]) let data2 = Data(bytes: [5, 6, 7, 8, 9]) do { // Set attributes: try fileURL.setExtendedAttribute(data: data1, forName: attr1) try fileURL.setExtendedAttribute(data: data2, forName: attr2) // List attributes: let list = try fileURL.listExtendedAttributes() print(list) // ["com.myCompany.myAttribute", "com.myCompany.otherAttribute", "other"] let data1a = try fileURL.extendedAttribute(forName: attr1) print(data1a as NSData) // <01020304> // Remove attributes for attr in list { try fileURL.removeExtendedAttribute(forName: attr) } } catch let error { print(error.localizedDescription) }
(之前回答Swift 2 🙂
一个简单的例子:
let fileURL = NSURL(fileURLWithPath: "/path/to/file") let attrName = "com.myCompany.myAttribute" var attrData: [UInt8] = [1, 2, 3, 4, 5] // Get local file system path: var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) guard fileURL.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { fatalError("Invalid file URL") } // Set extended attribute (returns 0 on success): guard setxattr(&fileSystemPath, attrName, &attrData, attrData.count, 0, 0) == 0 else { perror("setxattr") // prints error message of last system call fatalError() }
在命令行上validation结果:
$ xattr -px com.myCompany.myAttribute / path / to / file 01 02 03 04 05
下面是如何获取和设置文件属性,实现为NSURL
扩展方法:
extension NSURL { // Get extended attribute. Returns `nil` on failure. func extendedAttribute(forName name: String) -> [UInt8]? { // Get local file system path: var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) guard self.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { return nil } // Determine attribute size: let length = getxattr(fileSystemPath, name, nil, 0, 0, 0) guard length >= 0 else { return nil } // Create buffer with required size: var data = [UInt8](count: length, repeatedValue: 0) // Retrieve attribute: let result = getxattr(fileSystemPath, name, &data, data.count, 0, 0) guard result >= 0 else { return nil } return data } // Set extended attribute. Returns `true` on success and `false` on failure. func setExtendedAttribute(data: [UInt8], forName name: String) -> Bool { // Get local file system path: var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) guard self.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { return false } // Set attribute: let result = data.withUnsafeBufferPointer { setxattr(fileSystemPath, name, $0.baseAddress, data.count, 0, 0) } return result == 0 } // Remove extended attribute. Returns `true` on success and `false` on failure. func removeExtendedAttribute(forName name: String) -> Bool { // Get local file system path: var fileSystemPath = [Int8](count: Int(MAXPATHLEN), repeatedValue: 0) guard self.getFileSystemRepresentation(&fileSystemPath, maxLength: fileSystemPath.count) else { return false } // Remove attribute: let result = removexattr(fileSystemPath, name, 0) return result == 0 } }
用法示例:
let fileURL = NSURL(fileURLWithPath: "/path/to/file") let attrName = "com.myCompany.myAttribute" // Set attribute: let data1: [UInt8] = [1, 2, 3, 4] fileURL.setExtendedAttribute(data1, forName: attrName) // Get attribute: if let data2 = fileURL.extendedAttribute(forName: attrName) { print(data2) } // Remove attribute: fileURL.removeExtendedAttribute(forName: attrName)