Swift 檔案路徑與讀寫檔
Contents
iOS的路徑
專案資料夾內的路徑
利用Bundle.main獲取 可以指定檔案名稱以及副檔名。
// 得到url
let url = Bundle.main.url(forResource: "myjson", withExtension: "json")
// 得到path
let path = Bundle.main.path(forResource: "myjson", ofType: "json")
一般App路徑
Document範例
// 透過路徑尋找URL
let path = NSHomeDirectory() + "/Document"
let urlfrompath = URL(fileURLWithPath: path)
// 直接拿取URL,陣列第0個是資料夾本身(雖然也只有一個url)
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
Caches 範例
// 透過路徑尋找URL
let path = NSHomeDirectory() + "/Library/Caches"
let urlfrompath = URL(fileURLWithPath: path)
// 直接拿取URL
let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
Temp 範例
// 兩種路徑取得的方法
let pathFromNSHome = NSHomeDirectory() + "/tmp"
let pathFromLibrary = NSTemporaryDirectory()
// URL
let urlfrompath = URL(fileURLWithPath: pathFromNSHome)
新增路徑
- 將想要新增的路徑名稱寫出來
- 利用FileManager.default.createDirectory新增路徑
- 此方法的withIntermediateDirctories參數若設成true,可以幫你遞迴建立不存在的資料夾
let directoryPath = NSTemporaryDirectory() + "/images"
do{
try FileManager.default.createDirectory(atPath: directoryPath, withIntermediateDirectories: true, attributes: nil)
}catch{
print("Cannot create directory")
}
列出某個路徑下的所有檔案
- 先找到想列出檔案的路徑
- 利用 FileManager.default.contentsOfDirectory來列出此資料夾底下的檔案
let tempPath = NSTemporaryDirectory()
do{
let fileList = try FileManager.default.contentsOfDirectory(atPath: tempPath)
for file in fileList{
print(file)
}
}
catch{
print("Cannot list directory")
}
查看路徑資訊
FileManager.default.fileExists 可以幫你查看這個檔案是否存在,以及該檔案是否為一個Directory。
需要特別注意的是OBJCBool的使用
let path = NSTemporaryDirectory() + "/images"
var isDirectory:ObjCBool = false
let isExist = FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory)
if isExist == true && isDirectory.boolValue == true{
print("File exist and it is a direcotry")
}
else if isExist == true && isDirectory.boolValue == false{
print("File exist but it is not a direcotry")
}
else{
print("File isn't exist")
}
複製貼上刪除檔案
使用下方函式,記得加上do try catch。
FileManager.default.copyItem(atPath: path, toPath: cpPath)
FileManager.default.moveItem(atPath: path, toPath: mvPath)
FileManager.default.removeItem(atPath: path)
一般型別寫檔讀檔
讀寫String
寫檔要呼叫String的方法
let text = "Hello World"
let filePath = NSTemporaryDirectory() + "Text.txt"
do{
try text.write(toFile: filePath, atomically: true, encoding: .utf8)
}catch{
print("Not save correctly")
}
讀檔要使用NSString
let filePath = NSTemporaryDirectory() + "Text.txt"
do{
let loading = try NSString(contentsOfFile: filePath, encoding: String.Encoding.utf8.rawValue)
print(loading)
}catch{
print("No save file")
}
讀寫Array
利用NSArray做寫入
let originalArray = ["Apple", "Banana", "MAngo"]
let arrayToSave = NSArray(array: originalArray)
let filePath = NSTemporaryDirectory() + "saveArray.txt"
arrayToSave.write(toFile: filePath, atomically: true)
利用NSArray做讀出
let filePath = NSTemporaryDirectory() + "saveArray.txt"
if let loadArray = NSArray(contentsOfFile: filePath) as? [String]{
print(loadArray)
}
讀寫Dict
寫入靠NSDictionary
let originalDict = ["1":"apple", "2":"banana", "3":"orange"]
let dictToSave = NSDictionary(dictionary: originalDict)
let filePath = NSTemporaryDirectory() + "saveDict.txt"
dictToSave.write(toFile: filePath, atomically: true)
讀取靠NSDictionary
let filePath = NSTemporaryDirectory() + "saveDict.txt"
if let loadDict = NSDictionary(contentsOfFile: filePath) as? [String:String]{
print(loadDict)
}
多媒體寫檔讀檔
圖檔
存檔
多媒體的寫檔只能依靠URL而不能靠檔案路徑。
- 先拿到要儲存的UIImage (可靠照相機或手機已有的圖片)
- 以指定格式載入圖片 (UIImagePNGRepresentation或UIImageJPGRepresentation)
- 產生路徑及URL
- 在指定URL下存檔
// 拿到UIImage
guard let image = UIImage(named: "Tails") else {
print ("Cannot find image")
return
}
if let dataToSave = UIImagePNGRepresentation(image){
// 產生路徑
let filePath = NSTemporaryDirectory() + "savedImage.png"
let fileURL = URL(fileURLWithPath: filePath)
// 寫入
do{
try dataToSave.write(to: fileURL)
}catch{
print("Can not save Image")
}
}
讀檔
- 先用UIImage載入
- 把載入圖片放在UIImageView上面
let filePath = NSTemporaryDirectory() + "savedImage.png"
let image = UIImage(contentsOfFile: filePath)
myImageView.image = image
自定義class讀寫檔
要寫檔的class必須繼承
- NSObject
- NSCoding
並複寫相關function
class Item : NSObject, NSCoding{
var name:String?
var detail:String?
init(name:String, detail:String) {
self.name = name
self.detail = detail
}
required init?(coder aDecoder: NSCoder) {
name = aDecoder.decodeObject(forKey: "name") as! String
detail = aDecoder.decodeObject(forKey: "detail") as! String
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
aCoder.encode(detail, forKey: "detail")
}
}
可以來試著測試了
寫檔
- 產生物件
- 利用NSKeyedArchiver.archivedData包裹物件,產生data
- 找到寫檔路徑
- 將data寫入指定路徑
let item = Item(name: "危城", detail: "動作")
let data = NSKeyedArchiver.archivedData(withRootObject: item)
let docUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let url = docUrl.appendingPathComponent("myfile.txt")
try! data.write(to: url)
讀檔
- 找到讀檔路徑
- 獲取Data
- 利用NSKeyedUnarchiver.unarchiveObject,將data轉換成指定物件
let docUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let url = docUrl.appendingPathComponent("myfile.txt")
let data = try? Data(contentsOf: url)
if let data = data {
let item = NSKeyedUnarchiver.unarchiveObject(with: data) as! Item
print("=== Read ===")
print(item.name)
print(item.detail)
}