写扩展文件属性swift示例

pra*_*bhu 13 ios swift

我正在寻找一个解决方案来为swift中的文件添加扩展文件属性.我查了这个链接写扩展文件属性,但解决方案是客观的c,我需要一个swift的解决方案.

Mar*_*n R 31

以下是Swift 3中作为扩展的可能实现URL,具有获取,设置,列出和删除文件的扩展属性的方法.(Swift 2代码可以在下面找到.)

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 { [count = data.count] in
                getxattr(fileSystemPath, name, $0.baseAddress, 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.baseAddress, 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 namebuf = Array<CChar>(repeating: 0, count: length)

            // Retrieve attribute list:
            let result = listxattr(fileSystemPath, &namebuf, namebuf.count, 0)
            guard result >= 0 else { throw URL.posixError(errno) }

            // Extract attribute names:
            let list = namebuf.split(separator: 0).compactMap {
                $0.withUnsafeBufferPointer {
                    $0.withMemoryRebound(to: UInt8.self) {
                        String(bytes: $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))])
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

let fileURL = URL(fileURLWithPath: "/path/to/file")

let attr1 = "com.myCompany.myAttribute"
let attr2 = "com.myCompany.otherAttribute"

let data1 = Data([1, 2, 3, 4])
let data2 = Data([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)
}
Run Code Online (Sandbox Code Playgroud)

(Swift 2的上一个答案:)

一个简单的例子:

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 { [count = data.count] in
                getxattr(fileSystemPath, name, $0.baseAddress, 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.baseAddress, 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 namebuf = Array<CChar>(repeating: 0, count: length)

            // Retrieve attribute list:
            let result = listxattr(fileSystemPath, &namebuf, namebuf.count, 0)
            guard result >= 0 else { throw URL.posixError(errno) }

            // Extract attribute names:
            let list = namebuf.split(separator: 0).compactMap {
                $0.withUnsafeBufferPointer {
                    $0.withMemoryRebound(to: UInt8.self) {
                        String(bytes: $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))])
    }
}
Run Code Online (Sandbox Code Playgroud)

在命令行上验证结果:

let fileURL = URL(fileURLWithPath: "/path/to/file")

let attr1 = "com.myCompany.myAttribute"
let attr2 = "com.myCompany.otherAttribute"

let data1 = Data([1, 2, 3, 4])
let data2 = Data([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)
}
Run Code Online (Sandbox Code Playgroud)

以下是如何获取和设置文件属性,实现为以下扩展方法URL:

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 { [count = data.count] in
                getxattr(fileSystemPath, name, $0.baseAddress, 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.baseAddress, 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 namebuf = Array<CChar>(repeating: 0, count: length)

            // Retrieve attribute list:
            let result = listxattr(fileSystemPath, &namebuf, namebuf.count, 0)
            guard result >= 0 else { throw URL.posixError(errno) }

            // Extract attribute names:
            let list = namebuf.split(separator: 0).compactMap {
                $0.withUnsafeBufferPointer {
                    $0.withMemoryRebound(to: UInt8.self) {
                        String(bytes: $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))])
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

let fileURL = URL(fileURLWithPath: "/path/to/file")

let attr1 = "com.myCompany.myAttribute"
let attr2 = "com.myCompany.otherAttribute"

let data1 = Data([1, 2, 3, 4])
let data2 = Data([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)
}
Run Code Online (Sandbox Code Playgroud)

  • 要修复 Swift 5 中的“`withUnsafeMutableBytes` 已弃用”警告,请将 `$0` 更改为 `$0.baseAddress`。 (2认同)