缓存目录、下载目录、文档目录
public static var cachesDirectory: URL? {
get {
return FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first
}
}
public static var downloadsDirectory: URL? {
get {
return FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first
}
}
public static var documentDirectory: URL? {
get {
return FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
}
}
public static func sizeOf(file: URL) -> Int? {
if !File.exists(file: file) {
return nil
}
do {
let attributes = try FileManager.default.attributesOfItem(atPath: file.path)
if let size = attributes[.size] as? Int {
return size
}
print("failde to calculate size of file \(file.path)")
return nil
} catch {
print("failed to calculate size of file \(file.path)\n\(error)")
return nil
}
}
public static func sizeOf(directory: URL) -> Int? {
var totalSize = 0
do {
let contents = try FileManager.default.contentsOfDirectory(atPath: directory.path)
for content in contents {
let contentURL = directory.appendingPathComponent(content)
let attributes = try FileManager.default.attributesOfItem(atPath: contentURL.path)
guard let type = attributes[.type] as? String else {
continue
}
if type == "NSFileTypeDirectory",
let size = sizeOf(directory: contentURL) {
totalSize += size
continue
}
if let size = attributes[.size] as? Int {
totalSize += size
continue
}
print("failde to calculate size of item \(contentURL.path)")
return nil
}
} catch {
print("failed to calculate size of folder \(directory.path)\n\(error)")
return nil
}
return totalSize
}
public static func entitiesOf(directory: URL) -> [Entity] {
if !File.exists(directory: directory) {
return []
}
var entities = [Entity]()
do {
let contents = try FileManager.default.contentsOfDirectory(atPath: directory.path)
for content in contents {
let contentURL = directory.appendingPathComponent(content)
let attributes = try FileManager.default.attributesOfItem(atPath: contentURL.path)
guard let type = attributes[.type] as? String else {
continue
}
if type == "NSFileTypeDirectory" {
entities.append(Entity(url: contentURL, type: .directory))
} else {
entities.append(Entity(url: contentURL, type: .file))
}
}
} catch {
print("failed to calculate size of folder \(directory.path)\n\(error)")
return []
}
return entities
}
public struct Entity {
let url: URL
let type: EntityType
public init(url: URL, type: EntityType) {
self.url = url
self.type = type
}
}
public enum EntityType {
case file
case directory
}
public static func exists(file: URL) -> Bool {
var isDirectory : ObjCBool = false
return FileManager.default.fileExists(atPath: file.path, isDirectory: &isDirectory) && !isDirectory.boolValue
}
public static func exists(directory: URL) -> Bool {
var isDirectory : ObjCBool = false
return FileManager.default.fileExists(atPath: directory.path, isDirectory: &isDirectory) && isDirectory.boolValue
}
如果已经存在则不会覆盖创建
@discardableResult
public static func create(file: URL, length: Int) -> Bool {
if File.exists(file: file) {
return false
}
return FileManager.default.createFile(atPath: file.path, contents: Data(count: length), attributes: nil)
}
@discardableResult
public static func create(directory: URL) -> Bool {
if File.exists(directory: directory) {
return false
}
do {
try FileManager.default.createDirectory(atPath: directory.path, withIntermediateDirectories: true, attributes: nil)
return true
} catch {
print("failed to create folder: \(directory.path)\n\(error)")
return false
}
}
@discardableResult
public static func delete(at: URL) -> Bool {
do {
try FileManager.default.removeItem(at: at)
return true
} catch {
print("failed to remove file \(at.path)\n\(error)")
return false
}
}
@discardableResult
public static func move(at: URL, to: URL) -> Bool {
do {
try FileManager.default.moveItem(at: at, to: to)
return true
} catch {
print("failed to move file from \(at.path) to \(to.path)\n\(error)")
return false
}
}
@discardableResult
public static func write(to: URL, string: String) -> Bool {
do {
try string.write(to: to, atomically: true, encoding: .utf8)
return true
} catch {
print("failed to write string to \(to.absoluteString)\n\(error)")
return false
}
}
@discardableResult
public static func write(to: URL, data: Data, offset: Int) -> Bool {
if !File.exists(file: to) && !File.create(file: to, length: 0) {
print("failde to write data to \(to.path) because file fails to create")
}
guard let fileHandle = FileHandle(forWritingAtPath: to.path) else {
print("failde to write data to \(to.path) because file handle fails to create")
return false
}
do {
try fileHandle.seek(toOffset: UInt64(offset))
fileHandle.write(data)
try fileHandle.close()
return true
} catch {
print("failde to write data to \(to.path)\n\(error)")
return false
}
}
public static func readString(from: URL) -> String? {
if !File.exists(file: from) {
print("failde to read string from \(from.path) because file does not exist")
return nil
}
do {
return try String(contentsOfFile: from.path)
} catch {
print("failde to read string from \(from.path)\n\(error)")
return nil
}
}
public static func readData(from: URL) -> Data? {
if !File.exists(file: from) {
print("failde to read data from \(from.path) because file does not exist")
return nil
}
do {
return try Data(contentsOf: from)
} catch {
print("failde to read data from \(from.path)\n\(error)")
return nil
}
}
public static func readData(from: URL, offset: Int, length: Int) -> Data? {
if !File.exists(file: from) {
print("failde to read data from \(from.path) because file does not exist")
return nil
}
guard let fileHandle = FileHandle(forReadingAtPath: from.path) else {
print("failde to read data from \(from.path) because file handle fails to create")
return nil
}
do {
try fileHandle.seek(toOffset: UInt64(offset))
let data = fileHandle.readData(ofLength: length)
try fileHandle.close()
return data
} catch {
print("failde to read data from \(from.path)\n\(error)")
return nil
}
}