[英]How to access file included in app bundle in Swift?
我知道有几个问题与此有关,但它们在 Objective-C 中。
如何在实际 iPhone 上使用 Swift 访问我的应用程序中包含的.txt
文件? 我希望能够从中读取和写入。 如果您想看一下,这是我的项目文件。 如有必要,我很乐意添加详细信息。
只需在应用程序包中搜索资源
var filePath = NSBundle.mainBundle().URLForResource("file", withExtension: "txt")
但是你不能写入它,因为它在应用程序资源目录中,你必须在文档目录中创建它才能写入它
var documentsDirectory: NSURL?
var fileURL: NSURL?
documentsDirectory = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last!
fileURL = documentsDirectory!.URLByAppendingPathComponent("file.txt")
if (fileURL!.checkResourceIsReachableAndReturnError(nil)) {
print("file exist")
}else{
print("file doesnt exist")
NSData().writeToURL(fileURL!,atomically:true)
}
现在您可以从fileURL访问它
编辑 - 2018 年 8 月 28 日
这是在Swift 4.2 中的方法
var filePath = Bundle.main.url(forResource: "file", withExtension: "txt")
在文档目录中创建它
if let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
let fileURL = documentsDirectory.appendingPathComponent("file.txt")
do {
if try fileURL.checkResourceIsReachable() {
print("file exist")
} else {
print("file doesnt exist")
do {
try Data().write(to: fileURL)
} catch {
print("an error happened while creating the file")
}
}
} catch {
print("an error happened while checking for the file")
}
}
Swift 3 ,基于Karim 的回答。
读
您可以通过捆绑包的资源读取应用程序捆绑包中包含的文件:
let fileURL = Bundle.main.url(forResource:"filename", withExtension: "txt")
写作
但是,你不能在那里写。 您需要创建一个副本,最好在 Documents 目录中:
func makeWritableCopy(named destFileName: String, ofResourceFile originalFileName: String) throws -> URL {
// Get Documents directory in app bundle
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last else {
fatalError("No document directory found in application bundle.")
}
// Get URL for dest file (in Documents directory)
let writableFileURL = documentsDirectory.appendingPathComponent(destFileName)
// If dest file doesn’t exist yet
if (try? writableFileURL.checkResourceIsReachable()) == nil {
// Get original (unwritable) file’s URL
guard let originalFileURL = Bundle.main.url(forResource: originalFileName, withExtension: nil) else {
fatalError("Cannot find original file “\(originalFileName)” in application bundle’s resources.")
}
// Get original file’s contents
let originalContents = try Data(contentsOf: originalFileURL)
// Write original file’s contents to dest file
try originalContents.write(to: writableFileURL, options: .atomic)
print("Made a writable copy of file “\(originalFileName)” in “\(documentsDirectory)\\\(destFileName)”.")
} else { // Dest file already exists
// Print dest file contents
let contents = try String(contentsOf: writableFileURL, encoding: String.Encoding.utf8)
print("File “\(destFileName)” already exists in “\(documentsDirectory)”.\nContents:\n\(contents)")
}
// Return dest file URL
return writableFileURL
}
用法示例:
let stuffFileURL = try makeWritableCopy(named: "Stuff.txt", ofResourceFile: "Stuff.txt")
try "New contents".write(to: stuffFileURL, atomically: true, encoding: String.Encoding.utf8)
只是在 Swift 4 中使用此代码的快速更新:
Bundle.main.url(forResource:"YourFile", withExtension: "FileExtension")
并且以下已更新以说明写出文件:
var myData: Data!
func checkFile() {
if let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
let fileURL = documentsDirectory.appendingPathComponent("YourFile.extension")
do {
let fileExists = try fileURL.checkResourceIsReachable()
if fileExists {
print("File exists")
} else {
print("File does not exist, create it")
writeFile(fileURL: fileURL)
}
} catch {
print(error.localizedDescription)
}
}
}
func writeFile(fileURL: URL) {
do {
try myData.write(to: fileURL)
} catch {
print(error.localizedDescription)
}
}
这个特定的例子并不是最灵活的,但是通过一些工作,您可以轻松地传递您自己的文件名、扩展名和数据值。
捆绑包是只读的。 您可以使用NSBundle.mainBundle().pathForResource
以只读方式访问文件,但对于读写访问,您需要将文档复制到 Documents 文件夹或 tmp 文件夹。
在 Swift 5.1 中从包中获取文件
//For Video File
let stringPath = Bundle.main.path(forResource: "(Your video file name)", ofType: "mov")
let urlVideo = Bundle.main.url(forResource: "Your video file name", withExtension: "mov")
这个简单的包装器可以帮助您以最干净的方式从任何包中加载任何文件:
@propertyWrapper struct BundleFile<DataType> {
let name: String
let type: String
let fileManager: FileManager = .default
let bundle: Bundle = .main
let decoder: (Data) -> DataType
var wrappedValue: DataType {
guard let path = bundle.path(forResource: name, ofType: type) else { fatalError("Resource not found: \(name).\(type)") }
guard let data = fileManager.contents(atPath: path) else { fatalError("Can not load file at: \(path)") }
return decoder(data)
}
}
@BundleFile(name: "avatar", type: "jpg", decoder: { UIImage(data: $0)! } )
var avatar: UIImage
您可以定义任何解码器来满足您的需求
我必须使用另一个包中的文件。 因此,以下代码对我有用。 当你使用框架时是必需的。
let bundle = Bundle(for: ViewController.self)
let fileName = bundle.path(forResource: "fileName", ofType: "json")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.