I have a directory in my app that contains a bunch of files (also in subdirectories) for upload. After I upload the file I delete it but the empty directories remain. I try to deal with them periodically by traversing the content of "root" directory and marking all empty directories for deletion.
Due to the nature of the app I assume that the average number of empty directories is around 50 but it can grow in worst cases to around 1000.
I remove all marked directories with FileManager.removeItem(atPath:) in a loop in main thread:
for itemToDeletePath in markedItems {
try? filemanager.removeItem(atPath: itemToDeletePath)
}
Should I be worried about performance of this looped deletion? In general is it "fast" to delete empty directory?
I unfortunately couldn't find any info on performance of deletion operations on iOS (or at least I didn't know how to search this).
Related
I'm trying to save a downloaded file so I can open it in another session. I'm saving the mp3 data to the documents directory, and I'm saving the url to the file in a local datastore. When I check using
if ([[NSFileManager defaultManager] fileExistsAtPath:musicObject[#"localFile"]]){
NSLog(#"applicationDocumentsDir exists");
}
else {
NSLog(#"File doesn't exist");
}
it returns "File doesn't exist", but I know it does because I've printed out the documents directory which gives me
"file:///private/var/mobile/Containers/Data/Application/94552DFC-022B-4962-9CB7-CCD87CB43E57/Documents/xDDsCbXAFhwEqGIzJfJRByEr1.mp3",
and I'm trying to access it with the same path but the first is private. How do I make the file not private (I have saved it earlier in the app)
file:///var/mobile/Containers/Data/Application/AE27BD8F-5EEB-48FC-A8D4-E228F99CECE3/Documents/xDDsCbXAFhwEqGIzJfJRByEr1.mp3
I suggest the following steps:
Take the last path component (that's just your mp3 filename)
Get the current Documents directory
Build a new path with the current Documents directory and the extracted mp3 filename
If I remember correctly, /var is a symlink to /private/var. So depending on how the path is built, one may end up with one or the other.
I inherited a project which was struck by the same problem, only with an extra randomly named directory in between. Eventually I removed the leading /private component, constructed an array of path components and checked, whether replacing non-existent elements with the current value leads to an existing file. You case should be easier to handle.
I don't remember when, but at some point the application directory (the hex numbers path component) began to change with almost each run in the simulator. Beginning with this behaviour such problems became much more visible. Although one should not save full paths, I suspect a lot of projects didn't care in the past. On one hand because things just worked, and on the other hand because a lot of people just don't know it.
In my extension, I need to write a huge file (say around 20 gigs) to the disk. Currently I am doing it in the main thread, but file creation is very expensive operation. I was about to move the whole file creation process to a ChromeWorker, but based on https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers I cannot have access to the nsiFile from a ChromeWorker.
So my questions are:
1. Is it possible to access Cc, Ci, and Cu from within a ChromeWorker?
2. If not what would be the most efficient way to create and fill large files in Firefox. Note that I need to write the file based on segments and offsets (Ci.nsISeekableStream).
It's not possible to access nsIFile from ChromeWorker. But nsIFile is horrible synchronus option.
Go with OS.File: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/OSFile.jsm
On that page go to the link for usage on workers: https://developer.mozilla.org/docs/Mozilla/JavaScript_code_modules/OSFile.jsm/OS.File_for_workers
On the mainthread os.file returns promises.
In worker they are synchronus. Wrap your os.file functions in worker with a try-catch, as when an error occurs, (like os.file.remove with option of ignoreAbsent set to false) then the catch will hold the OS.File.Error object.
Great move to ChromeWorker btw! I'm a huge fan of ChromeWorkers. I wrote a simple example of jsm using chromeworker here: https://github.com/Noitidart/jpm-chromeworker
For segments, you'll have to OS.File.open and then on the return value do a .setPosition() then you can read certain number of bytes from that position, or write, or whatever. Its awesome stuff. OS.File is the new way and the recommended way to do file operations. Its been around awhile now though since like Firefox 29 or before that.
I have images in uitableview, they each have a string for they're path in documents directory.
Now my trouble is if somebody adds the same image they will have the same path.
I was thinking of making an if-statement that will run on all of my fetchedResultsController objects or better yet my entire documents directory and append a number or something to the pathString.
lets say user adds title.jpg to doc directory, then he adds the same image then I want a check to see if it already exists, if it already exists in doc directory then append title(1).jpg so it can save properly and so on.
any efficient way of doing that ?
Depending on the OS you're targeting you can set the image name using NSUUID. If you're targeting < iOS 6 you'll have to use CFUUIDRef. This will always ensure you have a unique filename for an image.
I have some compression components (like KAZip, JVCL, zLib) and exactly know how to use them to compress files, but i want to compress multiple folders into one single archive and keep folders structure after extract, how can i do it?
in all those components i just can give a list of files to compress, i can not give struct of folders to extract, there is no way (or i couldn't find) to tell every file must be extracted where:
i have a file named myText.txt in folder FOLDER_A and have a file with same name myText.txt in folder FOLDER_B:
|
|__________ FOLDER_A
| |________ myText.txt
|
|__________ FOLDER_B
| |________ myText.txt
|
i can give a list of files to compress: myList(myText.txt, myText.txt) but i cant give the structure for uncompress files, what is best way to found which file belongs to which folder?
The zip format just does not have folders. Well, it kinda does, but they are kind of empty placeholders, only inserted if you need metadata storage like user access rights. But other than those rather rare advanced things - there is no need for folders at all. What is really done - and what you can observe opening zip file in the notepad and scrolling to the end - is that each file has its path in it, starting with "archive root". In your exanple the zip file should have two entries (two files):
FOLDER_A/myText.txt
FOLDER_B/myText.txt
Note, that the separators used are true slashes, common to UNIX world, not back-slashes used in DOS/Windows world. Some libraries would fix back-slashes it for you, some would not - just do your tests.
Now, let's assume that that tree is contained in D:\TEMP\Project - just for example.
D:\TEMP\Project\FOLDER_A\myText.txt
D:\TEMP\Project\FOLDER_B\myText.txt
There are two more questions (other than path separators): are there more folders within D:\TEMP\Project\ that should be ignored, rather than zipped (like maybe D:\TEMP\Project\FOLDER_C\*.* ? and does your zip-library have direct API to pack the folders wit hall its internal subfolder and files or should you do it file by file ?
Those three questions you should ask yourself and check while choosing the library. The code drafts would be somewhat different.
Now let's start drafting for the libraries themselves:
The default variant is just using Delphi itself.
Enumerate the files in the folder: http://docwiki.embarcadero.com/CodeExamples/XE3/en/DirectoriesAndFilesEnumeraion_(Delphi)
If that enumeration results in absolute paths then strip the common D:\TEMP\Project from the beginning: something like If AnsiStartsText('D:\TEMP\Project\', filename) then Delete(filename, 1, Length('D:\TEMP\Project\'));. You should get paths relative to chosen containing place. Especially if you do not compress the whole path and live some FOLDER_C out of archive.
Maybe you should also call StringReplace to change '\' into '/' on filenames
then you can zip them using http://docwiki.embarcadero.com/Libraries/XE2/en/System.Zip.TZipFile.Add - take care to specify correct relative ArchiveFileName like aforementioned FOLDER_A/myText.txt
You can use ZipMaster library. It is very VCL-bound and may cause troubles using threads or DLLs. But for simple applications it just works. http://www.delphizip.org/
Last version page have links to "setup" package which had both sources, help and demos. Among demos there is an full-featured archive browser, capable of storing folders. So, you just can read the code directly from it. http://www.delphizip.org/191/v191.html
You talked about JVCL, that means you already have Jedi CodeLib installed. And JCL comes with a proper class and function, that judging by name can directly do what you want it too: function TJclSevenzipCompressArchive.AddDirectory(const PackedName: WideString; const DirName: string = ''; RecurseIntoDir: Boolean = False; AddFilesInDir: Boolean = False): Integer;
Actually all those libraries are rather similar on basic level, when i made XLSX export i just made a uniform zipping API, that is used with no difference what an actual zipping engine is installed. But it works with in-memory TStream rather than on-disk files, so would not help you directly. But i just learned than apart of few quirks (like instant vs postponed zipping) on ground level all those libs works the same.
I have a couple of files in mnesia directory, like
fs_my#node_14585_1263_545605_962084.273
fs_my#node_14702_1263_545842_879762.273
fs_my#node_14585_1263_545605_962084.290
...
Can I remove them (because it is big files) without risk to lose data?
Why does these files apear?
What are these files for?
Is it safe to remove them?
See http://www.erlang.org/doc/man/file_sorter.html
So without looking into the files, I would say that
1.+4. Yes, you can remove them, but first give it a try, as Zed said.
2.+3. They are temporary files used for sorting and should have been removed. """[...] Temporary files are deleted unless some uncaught EXIT signal occurs."""