In swift how can I get the file path for a test audio File that i have copied into the resources folder in Xcode
The code I have gives file not found. Am I looking in the right Directories with NSSearchPathForDirectoriesInDomains? Any help much appreciated!
let name = "test.wav"
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
let filePath = paths.stringByAppendingPathComponent(name)
let checkValidation = NSFileManager.defaultManager()
if (checkValidation.fileExistsAtPath(filePath)) {
print("found .wav")
} else {
print("file not found")
}
i just found this that works.
let name = "test.wav"
let soundPath = (NSBundle.mainBundle().resourcePath! as NSString).stringByAppendingPathComponent(name)
let soundURL = NSURL.fileURLWithPath(soundPath)
Related
download and save file
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
// var fileURL = self.createFolder(folderName: downloadFolderName)
var fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileName = URL(string : currentFile.link )
fileURL = fileURL.appendingPathComponent((fileName?.lastPathComponent)!)
return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(currentDownloadedFile.link , to: destination).response(completionHandler: { (DefaultDownloadResponse) in
print("res ",DefaultDownloadResponse.destinationURL!);
completion(true)
})
but when i wont to check file in this dirrectory i get nil
let filemanager:FileManager = FileManager()
let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let files = filemanager.enumerator(atPath: fileURL.absoluteString) // = nil
while let file = files?.nextObject() {
print(file)
}
if i save local path to file and after reload app wont to share it -> "share" app cant send file (mb cant found it)
can u pls help me. how it works ? why when i print all files he didnt find it? how to save file who after reboot app it will be saved in same link
You are using the wrong API
For file system URLs use always path, absoluteString returns the full string including the scheme (e. g. file:// or http://)
let files = filemanager.enumerator(atPath: fileURL.path)
I store an .jpg image i the iOS documents directory. I can write files and read files but when it comes to deleting them it says that there is no such file but that cannot be because I can read it with the same url.
Reading:
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let path = NSURL(fileURLWithPath: paths[0] as String)
let fullPath = path.appendingPathComponent(info["pi"] as! String)
let data = NSData(contentsOf: fullPath!)
Deleting:
let fileManager = FileManager.default
fileManager.delegate = self
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let path = NSURL(fileURLWithPath: paths[0] as String)
let fullPath = path.appendingPathComponent(info["pi"] as! String)
do {
try fileManager.removeItem(atPath: "\(fullPath!)")
} catch {
print("\(error)")
}
It throws:
Error Domain=NSCocoaErrorDomain Code=4 "“image_496251232.806566.jpg” couldn’t be removed." UserInfo={NSUnderlyingError=0x1758eb40 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}, NSFilePath=file:///var/mobile/Containers/Data/Application/269ADA58-6B09-4844-9FAA-AC2407C1D991/Documents/image_496251232.806566.jpg, NSUserStringVariant=(
Remove
)}
Your fullPath variable is a (optional) URL. To convert that to a file path string, use the .path property, not string interpolation:
fileManager.removeItem(atPath: fullPath!.path)
Or better, use the URL directly without converting it to a path:
fileManager.removeItem(at: fullPath!)
(And get rid of the forced unwrapping in favor of option binding ... :-)
a. How should I get all the txt files in directory?
i got a path of directory and now i should find all the txt files and change every one a little.
i try to run over all the files:
let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)
while let element = enumerator?.nextObject() as? String {
}
}
but I stuck there. How can I check if the filetype is text?
b. When i get to a directory (in the directory I run), I want get in and search there too, and in the end get out to the place I was and continue.
a is much more important to me but if I get an answer to b too it will be nice.
a. Easy and simple solution for Swift 3:
let enumerator = FileManager.default.enumerator(atPath: folderPath)
let filePaths = enumerator?.allObjects as! [String]
let txtFilePaths = filePaths.filter{$0.contains(".txt")}
for txtFilePath in txtFilePaths{
//Here you get each text file path present in folder
//Perform any operation you want by using its path
}
Your task a is completed by above code.
When talking about b, well you don't have to code for it because we are here using a enumerator which gives you the files which are inside of any directory from your given root directory.
So the enumerator does the work for you of getting inside a directory and getting you their paths.
You can use for .. in syntax of swift to enumerate through NSEnumerator.
Here is a simple function I wrote to extract all file of some extension inside a folder.
func extractAllFile(atPath path: String, withExtension fileExtension:String) -> [String] {
let pathURL = NSURL(fileURLWithPath: path, isDirectory: true)
var allFiles: [String] = []
let fileManager = NSFileManager.defaultManager()
if let enumerator = fileManager.enumeratorAtPath(path) {
for file in enumerator {
if let path = NSURL(fileURLWithPath: file as! String, relativeToURL: pathURL).path
where path.hasSuffix(".\(fileExtension)"){
allFiles.append(path)
}
}
}
return allFiles
}
let folderPath = NSBundle.mainBundle().pathForResource("Files", ofType: nil)
let allTextFiles = extractAllFile(atPath: folder!, withExtension: "txt") // returns file path of all the text files inside the folder
I needed to combine multiple answers in order to fetch the images from a directory and I'm posting my solution in Swift 3
func searchImages(pathURL: URL) -> [String] {
var imageURLs = [String]()
let fileManager = FileManager.default
let keys = [URLResourceKey.isDirectoryKey, URLResourceKey.localizedNameKey]
let options: FileManager.DirectoryEnumerationOptions = [.skipsPackageDescendants, .skipsSubdirectoryDescendants, .skipsHiddenFiles]
let enumerator = fileManager.enumerator(
at: pathURL,
includingPropertiesForKeys: keys,
options: options,
errorHandler: {(url, error) -> Bool in
return true
})
if enumerator != nil {
while let file = enumerator!.nextObject() {
let path = URL(fileURLWithPath: (file as! URL).absoluteString, relativeTo: pathURL).path
if path.hasSuffix(".png"){
imageURLs.append(path)
}
}
}
return imageURLs
}
and here is a sample call
let documentsDirectory = FileManager.default.urls(for:.documentDirectory, in: .userDomainMask)[0]
let destinationPath = documentsDirectory.appendingPathComponent("\(filename)/")
searchImages(pathURL: projectPath)
Swift 4
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let url = URL(fileURLWithPath: documentsPath)
let fileManager = FileManager.default
let enumerator: FileManager.DirectoryEnumerator = fileManager.enumerator(atPath: url.path)!
while let element = enumerator.nextObject() as? String, element.hasSuffix(".txt") {
// do something
}
let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)
while let element = enumerator?.nextObject() as? String where element.pathExtension == "txt" {
// element is txt file
}
let fileManager = NSFileManager.defaultManager()
let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath!)!
while let element = enumerator.nextObject() as? String {
if (element.hasSuffix(".txt")) { // element is a txt file }
}
All of my attempts to read from a plist have resulted in a nil value returned, I've tried this in several ways on both Xcode 6 & Xcode beta 7. Also, there are quite a few similar questions on stack, I've tried many of them, but none of them resolve this issue.
I've added my words.plist by clicking on:
{my project} > targets > build phases > copy Bundle Resources
Then I tried several variations of the following code in my ViewController:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths[0] as! String
let path = documentsDirectory.stringByAppendingPathComponent("words.plist")
let fileManager = NSFileManager.defaultManager()
//check if file exists
if(!fileManager.fileExistsAtPath(path)) {
// If it doesn't, copy it from the default file in the Bundle
if let bundlePath = NSBundle.mainBundle().pathForResource("words", ofType: "plist") {
let resultDictionary = NSMutableDictionary(contentsOfFile: bundlePath)
println("Bundle words file is --> \(resultDictionary?.description)") // this is nil!!!
fileManager.copyItemAtPath(bundlePath, toPath: path, error: nil)
} else {
println("words not found. Please, make sure it is part of the bundle.")
}
} else {
println("words already exits at path.")
// use this to delete file from documents directory
//fileManager.removeItemAtPath(path, error: nil)
}
print("entering if-let")
if let pfr = NSBundle.mainBundle().pathForResource("words", ofType: "plist") {
print("\nin let\n")
print(pfr)
print("\nentering dict if-let\n")
if let dict = NSDictionary(contentsOfFile: path) as? Dictionary<String, AnyObject> {
// use swift dictionary as normal
print("\nin let\n")
print(dict)
}
}
}
Question
Why am I getting a nil value and whats the proper way to add a plist file and read from it?
update:
inside my if statement the following is nil:
let resultDictionary = NSMutableDictionary(contentsOfFile: bundlePath)
println("Bundle words file is --> \(resultDictionary?.description)") // this is nil!!!
To me, this would indicate that either Xcode doesn't know about my words.plist file, or that I'm pointing my bundlePath to the wrong location.
the issue:
As #Steven Fisher stated, in the comments. My .plist file was an Array and not an NSDictionary. So I just had to switch two lines from my code:
let resultDictionary = NSMutableDictionary(contentsOfFile: bundlePath)
to
let resultDictionary = NSMutableArray(contentsOfFile: bundlePath)
and also
if let dict = NSDictionary(contentsOfFile: path) { //...
to
if let dict = NSArray(contentsOfFile: path) { //..
final working code:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) as NSArray
let documentsDirectory = paths[0] as! String
let path = documentsDirectory.stringByAppendingPathComponent("words.plist")
let fileManager = NSFileManager.defaultManager()
//check if file exists
if(!fileManager.fileExistsAtPath(path)) {
// If it doesn't, copy it from the default file in the Bundle
if let bundlePath = NSBundle.mainBundle().pathForResource("words", ofType: "plist") {
let resultDictionary = NSMutableArray(contentsOfFile: bundlePath)
println("Bundle words file is --> \(resultDictionary?.description)")
fileManager.copyItemAtPath(bundlePath, toPath: path, error: nil)
} else {
println("words not found. Please, make sure it is part of the bundle.")
}
} else {
println("words already exits at path.")
// use this to delete file from documents directory
//fileManager.removeItemAtPath(path, error: nil)
}
print("entering if-let")
if let pfr = NSBundle.mainBundle().pathForResource("words", ofType: "plist") {
print("\nin let\n")
print(pfr)
print("\nentering dict if-let\n")
if let dict = NSArray(contentsOfFile: pfr) {
// use swift dictionary as normal
print("\nin let\n")
print(dict)
}
}
}
I'm trying to count the number of directories in the iOS Documents Directory of my app using the following swift code:
let manager = NSFileManager.defaultManager()
let path: NSString = NSBundle.mainBundle().resourcePath!.stringByAppendingPathComponent("Documents")
var array = manager.contentsOfDirectoryAtPath(path, error: nil)
let count = array?.count
My Documents directory currently contains one directory but when I run this code, 'count' returns nil every time. Why is this?
Your method to find the Documents directory is wrong, NSBundle.mainBundle().resourcePath gives the path to the application bundle.
There is a dedicated function for this purpose:
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
And then you should use the error parameter and check the return value when
retrieving the directory contents:
let fileManager = NSFileManager.defaultManager()
var error : NSError?
if let files = fileManager.contentsOfDirectoryAtPath(documentsPath, error: &error) {
let count = files.count
// ...
} else {
println("Could not get contents of directory: \(error?.localizedDescription)")
}
Credit to Martin R. for the original answer! Here is a Swift 3 version incase anyone needs it...
Swift 3
func countFilesInDocumentsDirectory() {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) [0] as String
do {
let files = try FileManager.default.contentsOfDirectory(atPath: documentsPath)
print("File count = \(files.count)")
for i in 0...files.count-1 {
print("FILE: \n\(files[i])")
}
} catch {
//...
}
}