Rename file in Cocoa? - objective-c

How would I rename a file, keeping the file in the same directory?
I have a string containing a full path to a file, and a string containing a the new filename (and no path), for example:
NSString *old_filepath = #"/Volumes/blah/myfilewithrubbishname.avi";
NSString *new_filename = #"My Correctly Named File.avi";
I know about NSFileManager's movePath:toPath:handler: method, but I cannot workout how to construct the new file's path..
Basically I'm looking for the equivalent to the following Python code:
>>> import os
>>> old_filepath = "/Volumes/blah/myfilewithrubbishname.avi"
>>> new_filename = "My Correctly Named File.avi"
>>> dirname = os.path.split(old_filepath)[0]
>>> new_filepath = os.path.join(dirname, new_filename)
>>> print new_filepath
/Volumes/blah/My Correctly Named File.avi
>>> os.rename(old_filepath, new_filepath)

NSFileManager and NSWorkspace both have file manipulation methods, but NSFileManager's - (BOOL)movePath:(NSString *)source toPath:(NSString *)destination handler:(id)handler is probably your best bet. Use NSString's path manipulation methods to get the file and folder names right. For example,
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil];
Both classes are explained pretty well in the docs, but leave a comment if there's anything you don't understand.

It's worth noting that moving a file to itself will fail. I had a method that replaced spaces with underscores and made the file name lowercase and renamed the file to the new name. Files with only one word in the name would fail the rename as the new name would be identical on a case-insensitive file system.
The way I resolved this was to do a two step rename, first renaming the file to a temporary name and then renaming it to the intended name.
Some pseudocode explaining this:
NSString *source = #"/FILE.txt";
NSString *newName = [[source lastPathComponent] lowercaseString];
NSString *target = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName];
[[NSFileManager defaultManager] movePath:source toPath:target error:nil]; // <-- FAILS
The solution:
NSString *source = #"/FILE.txt";
NSString *newName = [[source lastPathComponent] lowercaseString];
NSString *temp = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:[NSString stringWithFormat:#"%#-temp", newName]];
NSString *target = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName];
[[NSFileManager defaultManager] movePath:source toPath:temp error:nil];
[[NSFileManager defaultManager] movePath:temp toPath:target error:nil];

I just wanted to make this easier to understand for a newbie. Here's all the code:
NSString *oldPath = #"/Users/brock/Desktop/OriginalFile.png";
NSString *newFilename = #"NewFileName.png";
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] movePath:oldPath toPath:newPath handler:nil];
NSLog( #"File renamed to %#", newFilename );

here's a more recent example for iOS, the NSFileManager method is a little different:
NSString *newFilename = [NSString stringWithFormat:#"%#.m4a", newRecording.title];
NSString *newPath = [[newRecording.localPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFilename];
[[NSFileManager defaultManager] moveItemAtPath:newRecording.localPath toPath:newPath error:nil];

For the icing on top, a category on NSFileManager:
#implementation NSFileManager (FileManipulations)
- (void)changeFileNamesInDirectory:(NSString *)directory changeBlock:(NSString * (^) (NSString *fileName))block
{
NSString *inputDirectory = directory;
NSFileManager *fileManager = [NSFileManager new];
NSArray *fileNames = [fileManager contentsOfDirectoryAtPath:inputDirectory error:nil];
for (NSString *fileName in fileNames) {
NSString *newFileName = block(fileName);
NSString *oldPath = [NSString stringWithFormat:#"%#/%#", inputDirectory, oldFileName];
// move to temp path so case changes can happen
NSString *tempPath = [NSString stringWithFormat:#"%#-tempName", oldPath];
NSString *newPath = [[oldPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:newFileName];
NSError *error = nil;
[fileManager moveItemAtPath:oldPath toPath:tempPath error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
return;
}
[fileManager moveItemAtPath:tempPath toPath:newPath error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
}
}
}
#end

Related

.m file to string

I am trying to convert a .m file to string. I will search for files in a folder and then want to use each of its contents as a string. This is the code I am using:
- (IBAction)searchAction:(id)sender {
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *dirContents = [fm contentsOfDirectoryAtPath:folderLabel.stringValue error:nil];
NSPredicate *fltr = [NSPredicate predicateWithFormat:#"self ENDSWITH '.m'"];
NSArray *onlyMs = [dirContents filteredArrayUsingPredicate:fltr];
for (int i=0; i<[onlyMs count]; i++) {
NSString* text = [[NSString alloc] initWithContentsOfFile:[onlyMs objectAtIndex:i]
encoding:NSUTF8StringEncoding
error:nil];
NSLog(#"string: %#", text);
}
}
2013-02-13 02:38:05.700 LocalizedStringSearch[19001:303] string: (null)
Except here, all the log is returning is null even though it will find all the .m file correctly.
Anyone know what I'm doing wrong?
Thanks a lot!
I think contentsOfDirectoryAtPath: gives you an array of filenames only, not full path names, so you need to prepend the path before you open files. EDIT: I think I might be confusing that with enumeratorAtPath:... if so continue using the filenames you have rather than appending them to the original folder name.
Here's an example (untested):
NSString *fullPath = [folderLabel.stringValue stringByAppendingPathComponent:[onlyMs objectAtIndex:i];
NSError *error = nil;
NSString *text = [[NSString alloc] initWithContentsofFile:fullPath
encoding:NSUTF8StringEncoding
error:&error];
if (text == nil)
NSLog(#"%#", error);
else
NSLog(#"%#", text);
The above will only work if the files actually are encoded using UTF-8. If you are unsure of the encoding, you can let the framework try and figure it out for you with:
NSString *fullPath = [folderLabel.stringValue stringByAppendingPathComponent:[onlyMs objectAtIndex:i];
NSError *error = nil;
NSStringEncoding enc;
NSString *text = [[NSString alloc] initWithContentsofFile:fullPath
usedEncoding:&enc
error:&error];
if (text == nil)
NSLog(#"%#", error);
else
NSLog(#"%#", text);

Renaming an existing file with Obj-C

I've seen this question asked a few times but I have been unable thus far to achieve success using any of the post solutions. What I am trying to do is rename a file in the local storage of an app (also kind of new to Obj-c). I am able to retrieve the old path and create the new path, but what would I have to write in order to actually change the files name?
What I have thus far is:
- (void) setPDFName:(NSString*)name{
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* initPath = [NSString stringWithFormat:#"%#/%#",[dirPaths objectAtIndex:0], #"newPDF.pdf"];
NSString *newPath = [[NSString stringWithFormat:#"%#/%#",
[initPath stringByDeletingLastPathComponent], name]
stringByAppendingPathExtension:[initPath pathExtension]];
}
NSError *error = nil;
[[NSFileManager defaultManager] moveItemAtPath:initPath toPath:newPath error:&error];
The code is very messy; try this:
- (BOOL)renameFileFrom:(NSString*)oldName to:(NSString *)newName
{
NSString *documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
NSString *oldPath = [documentDir stringByAppendingPathComponent:oldName];
NSString *newPath = [documentDir stringByAppendingPathComponent:newName];
NSFileManager *fileMan = [NSFileManager defaultManager];
NSError *error = nil;
if (![fileMan moveItemAtPath:oldPath toPath:newPath error:&error])
{
NSLog(#"Failed to move '%#' to '%#': %#", oldPath, newPath, [error localizedDescription]);
return NO;
}
return YES;
}
and call this using:
if (![self renameFileFrom:#"oldName.pdf" to:#"newName.pdf])
{
// Something went wrong
}
Better still, put the renameFileFrom:to: method into a utility class and make it a class method so it can be called from anywhere in your project.

NSMutableString returns null

I'm trying to construct a string from the file names in my app's document folder.
So far I have:
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [directoryPaths objectAtIndex:0];
NSError *error = nil;
NSArray *directoryContent = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory error:&error];
NSLog(#"contents of document folder = %#", directoryContent);
This prints:
contents of app's document folder = (
".DS_Store",
File1.doc,
"File2.pdf",
....
)
I'd like to construct a string of file names, separated in some way, perhaps by semi-colon and attempted it (initially without any separation) via this code:
NSMutableString *fileList;
for (NSString *folder in directoryContent)
{
[fileList appendString:[NSString stringWithFormat:#"%#", folder]];
}
NSLog(#"file list = %#", fileList);
This prints file list = (null), and I can't figure out where I'm going wrong. Any ideas?
You shold initialize the MutableString before adding strings. NSMutableString* fileList = [[NSMutableString alloc] init ];

Saving images to a directory

Hi I want to save an image to a directory, I pass the NSData and do what I think will save the file in a directory I create but the problem is that it doesn't save. This is what I have so far. Why doesn't the initWithContentsOfURL:encoding:error: work, it returns null but the other method I used works? The main problem is WRITETOURL which returns a 0 which i think means that the information wasn't stored properly, any tips?
NSFileManager *fm = [[NSFileManager alloc] init];
NSArray * directoryPaths = [fm URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask];
NSLog(#"%#", directoryPaths);
NSURL* dirPath = nil;
dirPath = [[directoryPaths objectAtIndex:0] URLByAppendingPathComponent:[NSString stringWithFormat:#"photos.jpeg"]];
NSError* theError = nil;
[fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES attributes:nil error:&theError];
UIImage* photoToStore = [UIImage imageWithData:photoToSave];
NSString *pathContainingPhoto = [[NSString alloc] initWithFormat:#"%#.jpeg", UIImageJPEGRepresentation(photoToStore, 1.0)];
NSError *error = nil;
BOOL OK = [pathContainingPhoto writeToURL:dirPath atomically:YES encoding:NSUTF8StringEncoding error:&error];
NSLog(#"OK = %d", OK); //Returns 0
NSLog(#"%#", dirPath);
//WHY DOESNT THIS VERSION WORK?
// NSString *pathToFile = [[NSString alloc] initWithContentsOfURL:dirPath encoding:NSUTF8StringEncoding error:&error];
NSLog(#"%#", pathToFile);
NSString* pathToFile = [NSString stringWithContentsOfURL:dirPath encoding:nil error:nil];
NSArray *dirContents = [fm contentsOfDirectoryAtPath:pathToFile error:nil];
NSLog(#"%#", dirContents);
Do like this and int count in .h file and set its intial value count = 0; in viewDidLoad:
NSString *stringPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0]stringByAppendingPathComponent:[NSString stringWithFormat:#"Image_%d.png",count];
error = nil;
if (![[NSFileManager defaultManager] fileExistsAtPath:stringPath]) // removing item it already exuts
{
[[NSFileManager defaultManager] removeItemAtPath:stringPath error:&error];
}
if(photoToSave) // nsdata of image that u have
{
[photoToSave writeToFile:stringPath atomically:YES];
}
count++; // maintaining count of images

How can I create a zip file by using Objective C?

I am developing an iOS application, and trying to zip the file I have created in the application, is there any built in function able to do this?
I definitely recommend Objective-Zip. It just recently moved to https://github.com/flyingdolphinstudio/Objective-Zip:
Some examples from their documentation:
Creating a Zip File:
ZipFile *zipFile= [[ZipFile alloc] initWithFileName:#"test.zip" mode:ZipFileModeCreate];
Adding a file to a zip file:
ZipWriteStream *stream= [zipFile writeFileInZipWithName:#"abc.txt" compressionLevel:ZipCompressionLevelBest];
[stream writeData:abcData];
[stream finishedWriting];
Reading a file from a zip file:
ZipFile *unzipFile= [[ZipFile alloc] initWithFileName:#"test.zip" mode:ZipFileModeUnzip];
[unzipFile goToFirstFileInZip];
ZipReadStream *read= [unzipFile readCurrentFileInZip];
NSMutableData *data= [[NSMutableData alloc] initWithLength:256];
int bytesRead= [read readDataWithBuffer:data];
[read finishedReading];
As Alex pointed out, I responded to this question by pointing out the NSData category contributed by users of the Cocoadev wiki. That category includes methods for dealing with zipped and gzipped data in an NSData instance (that could be read from a Zip file or written to one). This should be all you need to implement the file zipping you describe, as long as you can feed your file data into an NSData instance.
For an example of this category in action, please see the source code for my iPhone application, Molecules. I only use the method to extract data from a gzipped file (in SLSMolecule+PDB.m), but you should be able to get the basic concepts from that.
first you download Objective-zip example from http://code.google.com/p/objective-zip/downloads/list
in this example Find and copy three folder Objective-Zip, MiniZip and ZLib drag in to your project
import two class in you .m class
"ZipFile.h" and
"ZipWriteStream.h"
create method of zip my code is :-
-(IBAction)Zip{
self.fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory , NSUserDomainMask, YES);
NSString *ZipLibrary = [paths objectAtIndex:0];
NSString *fullPathToFile = [ZipLibrary stringByAppendingPathComponent:#"backUp.zip"];
//[self.fileManager createDirectoryAtPath:fullPathToFile attributes:nil];
//self.documentsDir = [paths objectAtIndex:0];
ZipFile *zipFile = [[ZipFile alloc]initWithFileName:fullPathToFile mode:ZipFileModeCreate];
NSError *error = nil;
self.fileManager = [NSFileManager defaultManager];
NSArray *paths1 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
self.documentsDir = [paths1 objectAtIndex:0];
NSArray *files = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:self.documentsDir error:&error];
//for(NSString *filename in files){
for(int i = 0;i<files.count;i++){
id myArrayElement = [files objectAtIndex:i];
if([myArrayElement rangeOfString:#".png" ].location !=NSNotFound){
NSLog(#"add %#", myArrayElement);
NSString *path = [self.documentsDir stringByAppendingPathComponent:myArrayElement];
NSDictionary *attributes = [[NSFileManager defaultManager]attributesOfItemAtPath:path error:&error];
NSDate *Date = [attributes objectForKey:NSFileCreationDate];
ZipWriteStream *streem = [zipFile writeFileInZipWithName:myArrayElement fileDate:Date compressionLevel:ZipCompressionLevelBest];
NSData *data = [NSData dataWithContentsOfFile:path];
// NSLog(#"%d",data);
[streem writeData:data];
[streem finishedWriting];
}else if([myArrayElement rangeOfString:#".txt" ].location !=NSNotFound)
{
NSString *path = [self.documentsDir stringByAppendingPathComponent:myArrayElement];
NSDictionary *attributes = [[NSFileManager defaultManager]attributesOfItemAtPath:path error:&error];
NSDate *Date = [attributes objectForKey:NSFileCreationDate];
ZipWriteStream *streem = [zipFile writeFileInZipWithName:myArrayElement fileDate:Date compressionLevel:ZipCompressionLevelBest];
NSData *data = [NSData dataWithContentsOfFile:path];
// NSLog(#"%d",data);
[streem writeData:data];
[streem finishedWriting];
}
}
[self testcsv];
[zipFile close];
}
your documents directory saved item .png and .txt files zipping in Library folder with backup.zip
i hope this is helps