I used to use the following to rename aplist file with various user inputted values (BOOL,Strings mostly):
[manager moveItemAtPath:oldPath toPath:newPath error:&error];
And for some reason in iOS4+ this glitches out, so I Attempt the following:
[1] [manager copyItemAtPath:oldPath toPath:newPath error:&error];
[2] [manager removeItemAtPath:oldPath error:&error];
Now, [1] copies the plist and ALL of the data correctly. (I've verified when commenting out [2]. But for some reason, when I attempt [1] & [2], the file /appears/ renamed, however, there are only certain fields missing, for example I FName and LName stay intact, whereas Phone1,Phone2,Email1,Email2 and Website are removed from the new file.
For the life of me, I just cannot figure out why only some of the data remains when I attempt a removeFileAtPath for the OLD file AFTER the NEW FILE is created?
Any help would be MUCH APPRECIATED!
I just simply want to rename a plist file, while keeping ALL of the data in tact.
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil];
Related
I'm new to the site and probably even newer to app development, however i'm learning slowly.. lol
So i hit my first big snag, I've researched all over on the web and can't find what I'm looking for, so here we go.
I'm creating an app that calls upon some user inputted files that can and do change on occasion. I've added the UIFileSharing option for this so users can upload files via iTunes.
There are 3 different types of files that will need to be used, a .opt, a .pkg, and a .txt.
Is there some way i can take the files from the directory, read them, and based off the file extension pull them and use them in a UIPickerView wheel? I'm really new at this so please forgive me when i ask you to be specific.
My assumption is to do this in a few steps, first read the files and sort them and place them in an array based on the extension, then use said array to populate the picker, and also to get the count for number of rows etc..
I guess the second two parts are pretty simple to figure out, just setting up a picker to use an array, i just need to know if its possible to build that array based on the user loaded files.
thanks in advance,
Chuck
You'll need to use the UIDocumentInteractionController class.
Simple Example
UIDocumentInteractionController * controller;
NSURL *fileURL=[NSURL fileURLWithPath:[self getFilePath]]
controller = [ UIDocumentInteractionController interactionControllerWithURL: fileURL ];
// How to get File From the Document Directory
-(NSString *)getFilePath{
NSString *documentPath= [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
return [documentPath stringByAppendingPathComponent:#"Your file name"]
}
I solved it guys, thanks for all the help.. Code is below, for anyone interested. Don't forget to define your arrays!
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *bundleDirectory = [fileManager contentsOfDirectoryAtPath:documentsPath error:nil];
NSPredicate *Option = [NSPredicate predicateWithFormat:#"self ENDSWITH '.opt'"];
_OptionArray = [bundleDirectory filteredArrayUsingPredicate:Option];
_OptionPickerData = [_OptionArray copy];
I am creating an image file from a json object and the file creation is successful and the image is indeed created and can be displayed. I want a process that will check if the file is still in cache or a tmp directory before downloading the image. If the image is indeed there then I want to check the creation date and modification date attributes of the file to see if I need to download a new version of the image to keep it up to date. This is where the problem comes in.
The creation and modification date attributes are null. I've even attempted to manually set the attributes and it didn't change anything.
Here's the code I use to create the file:
NSString *fileName = [NSHomeDirectory() stringByAppendingPathComponent: [NSString stringWithFormat:#"tmp/%#",theFileName]];
BOOL filecreationSuccess =[fileManager createFileAtPath:fileName contents:myData attributes:nil];
if(filecreationSuccess == NO){
NSLog(#"Failed to create the file");
}
I have even tried adding the Code and the attributes on the file are still null:
NSDate *now = [NSDate date];
NSDictionary *createDateAttr = [NSDictionary dictionaryWithObjectsAndKeys: now, NSFileCreationDate,nil];
NSDictionary *modDateAttr = [NSDictionary dictionaryWithObjectsAndKeys: now, NSFileModificationDate, nil];
[fileManager setAttributes:modDateAttr ofItemAtPath:fileName error:&err];
[fileManager setAttributes:createDateAttr ofItemAtPath:fileName error:&err];
I am unsure of what to do next. Any help would be greatly appreciated, Thank you.
I have found my problem. It wasn't that the modification and creation dates weren't being set, but that I was not getting the correct set of properties for the file. It ended up being that the code I was using was getting the properties for the path that the file was in, not the file itself.
I am trying to update an existing plist on iOS5 simulator but it fails miserably.
It finds the plist and retrieves existing information and updates the array but it does not write to file.
Any one would have any ideas?
NSString *path = [[NSBundle mainBundle] pathForResource:#"content_iPhone" ofType:#"plist"];
NSMutableArray *plist = [[NSMutableArray arrayWithContentsOfFile:path] mutableCopy];
// For testing purpose, get an object from the Array and add the object to array
newObject = [plist objectAtIndex:1];
[plist addObject:newObject];
[plist writeToFile:path atomically:YES];
You can't write to a file inside your app bundle, you can only read from it.
You could write the file to the user's Documents directory instead: look at
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
This returns an array, the first object of which will be the path to the user's Documents directory for your app. You could copy the file there the first time your app is run, and update it at that location in the future.
I'm currently trying to attach image files to a model directly from a zip file (i.e. without first saving them on a disk). It seems like there should be a clearer way of converting a ZipEntry to a Tempfile or File that can be stored in memory to be passed to another method or object that knows what to do with it.
Here's my code:
def extract (file = nil)
Zip::ZipFile.open(file) { |zip_file|
zip_file.each { |image|
photo = self.photos.build
# photo.image = image # this doesn't work
# photo.image = File.open image # also doesn't work
# photo.image = File.new image.filename
photo.save
}
}
end
But the problem is that photo.image is an attachment (via paperclip) to the model, and assigning something as an attachment requires that something to be a File object. However, I cannot for the life of me figure out how to convert a ZipEntry to a File. The only way I've seen of opening or creating a File is to use a string to its path - meaning I have to extract the file to a location. Really, that just seems silly. Why can't I just extract the ZipEntry file to the output stream and convert it to a File there?
So the ultimate question: Can I extract a ZipEntry from a Zip file and turn it directly into a File object (or attach it directly as a Paperclip object)? Or am I stuck actually storing it on the hard drive before I can attach it, even though that version will be deleted in the end?
UPDATE
Thanks to blueberry fields, I think I'm a little closer to my solution. Here's the line of code that I added, and it gives me the Tempfile/File that I need:
photo.image = zip_file.get_output_stream image
However, my Photo object won't accept the file that's getting passed, since it's not an image/jpeg. In fact, checking the content_type of the file shows application/x-empty. I think this may be because getting the output stream seems to append a timestamp to the end of the file, so that it ends up looking like imagename.jpg20110203-20203-hukq0n. Edit: Also, the tempfile that it creates doesn't contain any data and is of size 0. So it's looking like this might not be the answer.
So, next question: does anyone know how to get this to give me an image/jpeg file?
UPDATE:
I've been playing around with this some more. It seems output stream is not the way to go, but rather an input stream (which is which has always kind of confused me). Using get_input_stream on the ZipEntry, I get the binary data in the file. I think now I just need to figure out how to get this into a Paperclip attachment (as a File object). I've tried pushing the ZipInputStream directly to the attachment, but of course, that doesn't work. I really find it hard to believe that no one has tried to cast an extracted ZipEntry as a File. Is there some reason that this would be considered bad programming practice? It seems to me like skipping the disk write for a temp file would be perfectly acceptable and supported in something like Zip archive management.
Anyway, the question still stands:
Is there a way of converting an Input Stream to a File object (or Tempfile)? Preferably without having to write to a disk.
Try this
Zip::ZipFile.open(params[:avatar].path) do |zipfile|
zipfile.each do |entry|
filename = entry.name
basename = File.basename(filename)
tempfile = Tempfile.new(basename)
tempfile.binmode
tempfile.write entry.get_input_stream.read
user = User.new
user.avatar = {
:tempfile => tempfile,
:filename => filename
}
user.save
end
end
Check out the get_input_stream and get_output_stream messages on ZipFile.
As the title suggests, I'm looking for a way to get attributes of a large number of files in a directory, but without adding the cost of an additional disk access for each file.
For example, if I get the Name attribute of FileInfo objects in a collection, then there is no additional disk access. However if I get the LastWriteTimeUtc, then an additional disk access is made.
My code:
DirectoryInfo di = new DirectoryInfo(myDir);
FileInfo[] allFiles = di.GetFiles("*.*", SearchOption.TopDirectoryOnly);
foreach (FileInfo fInfo in allFiles)
{
name = fInfo.Name //no additional disk access made
lastMod = fInfo.LastWriteTimeUtc //further disk access made!!!
}
Does anyone know of a way I can get this information in one round trip? I would have hoped that DirectoryInfo.GetFiles() does this but no luck.
Thanks in advance.
If you really care about this, you should probably write this in C using FindFirstFile/GetFileTime, etc.
So, this happens by design. The LastWriteTimeUtc is lazy loaded. So nothing to do other write my own component.