OSX directory with spaces - objective-c

I'm having an issue with opening directories that have spaces in them. My code looks like this:
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setCanChooseDirectories:YES];
if ( [openDlg runModal] == NSOKButton )
{
NSArray* files = [openDlg URLs];
NSString* directoryName = [[files objectAtIndex:0] absoluteString];
directoryURL = [files objectAtIndex:0];
NSLog(#"Directory Name: %#", directoryName);
NSArray *directoryArray = [directoryName componentsSeparatedByString:#"/"];
NSString* currentDirectory = [directoryArray objectAtIndex:(directoryArray.count- 2)];
[directoryBox setTitle:currentDirectory];
}
When I select a directory name with spaces the files are not displayed in a table and the output in the NSLog looks like this:
Directory Name:
file://localhost/Users/Rich/Software%20Bisque/
Any ideas?

The -URLs method of of NSOpenPanel returns instances of NSURL, not file system paths. While NSURLs have become the preferred way to refer to files, you can easily change to a file system path by using NSURL's -path method.
Note that there are many methods specific to working with file system paths that are added to NSString in NSPathUtilities.h. You could probably rewrite your code to incorporate those (double-check that I've got your targeted directory okay):
NSArray* files = [openDlg URLs];
NSString* directoryName = [[files objectAtIndex:0] path];
directoryURL = [files objectAtIndex:0];
NSLog(#"Directory Name: %#", directoryName);
// NSArray *directoryArray = [directoryName pathComponents];
// NSString* currentDirectory = [directoryArray objectAtIndex:(directoryArray.count- 2)];
NSString *currentDirectory = [[directoryName stringByDeletingLastPathComponent]
lastPathComponent];
[directoryBox setTitle:currentDirectory];

You could try removing the percent escapes in the directoryName string - I don't think the system needs them there. Something like:
directoryName = [directoryName stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

Related

Objective C writetoFile not work when get file path from textfied (file browser)

Im trying to save the file into the path, which I manual input into text field or select from FileBrowser. However it doesn't work.
If I drop path to textfield then it working fine. Could you help me.
- (IBAction)btnRawDataPath:(id)sender {
_txtLog.stringValue = #"";
// Create the File Open Dialog class.
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
// Enable the selection of files in the dialog.
[openDlg setCanChooseFiles:NO];
// Multiple files not allowed
[openDlg setAllowsMultipleSelection:NO];
// Can't select a directory
[openDlg setCanChooseDirectories:YES];
// Display the dialog. If the OK button was pressed,
// process the files.
if ( [openDlg runModal] == NSModalResponseOK )
{
// Get an array containing the full filenames of all
// files and directories selected.
NSArray* urls = [openDlg filenames];
// Loop through all the files and process them.
for(int i = 0; i < [urls count]; i++ )
{
//fileList.push_back(std::string([[[urls objectAtIndex:i] path] UTF8String]));
NSString* url = [urls objectAtIndex:i] ;
NSLog(#"Url: %#", url);
_txtRawDataPath.stringValue = url;
}
}
}
// EXCUTE
NSString *filePath = [_txtRawDataPath.stringValue stringByAppendingPathComponent:#"outputFIle.csv"];
NSData* settingsData;
settingsData = [mainString dataUsingEncoding: NSASCIIStringEncoding];
if ([settingsData writeToFile:filePath atomically:YES ])
NSLog(#"%#", filePath);

Save files avoiding duplicate filenames and overwriting

So, here's my situation :
I've got an application prompting the user to select a folder to save his files
Now let's say his files are : a.png, b.png, c.png
What I want is :
if file - let's say - a.png already exists in the selected folder, DON'T overwrite it. Instead create a file with name a (1).png. If a file a (1).png already exists, then name it like a (2).png, and so on - pretty much like OS X does when copy-pasting files with the same name.
This is how I'm currently doing it - but it still doesn't strike me ok :
NSString* target = [self getTargetPathForFile:filename path:folder];
NSString* fname = [target lastPathComponent];
while ([[NSFileManager defaultManager] fileExistsAtPath: [folder stringByAppendingPathComponent:fname]])
{
//NSLog(#"FNAME : %#",fname);
if ([self str:fname containsString:#")." options:nil])
{
NSArray* a = [fname componentsSeparatedByString:#"("];
NSArray* b = [[a objectAtIndex:1] componentsSeparatedByString:#")"];
fname = [NSString stringWithFormat:#"%#(%d)%#",[a objectAtIndex:0],[[b objectAtIndex:0] intValue]+1,[b objectAtIndex:1]];
}
else
{
fname = [NSString stringWithFormat:#"%# (1).%#",[fname stringByDeletingPathExtension],[fname pathExtension]];
}
//NSLog(#"Setting filename to :: %#",fname);
}
target = [folder stringByAppendingPathComponent:fname];
Any ideas how to go about this? Is there any Cocoa-friendly (or built-in) method for this?
Why not try this one :
NSString* fname = [target lastPathComponent];
NSString* fnameNoExt = [fname stringByDeletingPathExtension];
NSString* extension = [fname pathExtension];
int fileIndex = 1;
while ([[NSFileManager defaultManager] fileExistsAtPath: [folder stringByAppendingPathComponent:fname]])
{
//NSLog(#"FNAME : %#",fname);
fname = [NSString stringWithFormat:#"%# (%d).%#", fnameNoExt, fileIndex, extension];
//NSLog(#"Setting filename to :: %#",fname);
fileIndex++;
}
target = [folder stringByAppendingPathComponent:fname];
If you don't really care about the file names as you explained in one of your comment, and can consider using automatically-generated file names instead, use either CFUUID, NSProcessInfo, or mkstemp.
Using CFUUID to generate a unique identifier str:
CFUUIDRef uuidref = CFUUIDCreate(NULL);
CFStringRef cfstr = CFUUIDCreateString(NULL, uuidref);
// If using ARC:
NSString* filename = (__bridge_transfer NSString*)cfstr;
// If not using ARC
NSString* filename = [(NSString*)cfstr autorelease];
// Then release the CFUUIDRef
CFRelease(uuidref);
Using NSProcessInfo
NSString* filename = [[NSProcessInfo processInfo] globallyUniqueString];
Using mkstemp: see CocoaWithLove

NSOpenPanel not correctly accessing NSUrl from filename with Whitespace

Did a search, didn't find any issues on this.
My application takes .csv files, switches the data around and spits it out in a way my company finds useful. The issue is that the program seems to require filenames without whitespace. For instance "My data.csv" will not work, but "My_data.csv" will work. Here is what I believe to be the relevant code
NSArray *allowedTypes = [NSArray arrayWithObjects:#"CSV",#"csv",nil];
openDLG = [NSOpenPanel openPanel];
[openDLG setDelegate:self];
[openDLG setCanChooseFiles:YES];
[openDLG setAllowedFileTypes:allowedTypes];
NSInteger openReturn = [openDLG runModal];
if (openReturn == NSFileHandlingPanelOKButton) {
NSArray *rawCSVs = [openDLG URLs];
NSEnumerator *enumerator = [rawCSVs objectEnumerator];
id object;
while ((object = [enumerator nextObject])) {
NSString *tempDump = [NSString stringWithContentsOfURL:object encoding:NSUTF8StringEncoding error:NULL];
NSArray *bigArray = [tempDump csvRows];
int total = [bigArray count];
....do other things
In debug mode, the "object" comes up as nil for filenames with whitespace and "tempdump" string comes up as #"nil" for filenames with whitespace, but comes up wonderfully for names_with_underscores
An URL does not permit every character, so you will need to do some conversion.
NSString *rawString = [NSString stringWithString:#"/Users/myusername/test 1.txt"];
NSString *escapedString = [rawString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:escapedString];
NSLog(#"url: %#", url);

Objective C Exception during file reading?

I am trying to read a text file line by line, and the text file will be a really small file so I just used:
NSString *fileContents = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
However, an exception is raised on that line, saying:
[NSURL getFileSystemRepresentation:maxLength:]: unrecognized selector sent to instance 0x7f92c40e1890
I'm really new to Objective-C and I don't get why this is happening...
Thanks in advance.
NSString *filePath;
NSOpenPanel *fileBrowser = [NSOpenPanel openPanel];
[fileBrowser setCanChooseFiles:YES];
[fileBrowser setCanChooseDirectories:YES];
if ([fileBrowser runModal] == NSOKButton) {
NSArray *files = [fileBrowser URLs];
for ( int i = 0; i < [files count]; i++ ) {
filePath = [files objectAtIndex:i];
}
}
Is this because of the [fileBrowser URLs] part?
Thank you.
It looks like filePath is an NSURL, but stringWithContentsOfFile:encoding:error: expects the path as an NSString.
Try this:
NSString *fileContents = [NSString stringWithContentsOfURL:filePath encoding:NSUTF8StringEncoding error:nil];
You are getting this error because NSURL does not have a method getFileSystemRespresentation, this is in NSString.
You can either use this method on your fileContents string, or pass your fileContents string to NSURL's URLWithString method.

Calling methods after comparing string objects from NSArray Cocoa

I am selecting files through this code:
- (IBAction)selectFile:(id)sender {
// Create the File Open Dialog class.
NSOpenPanel* openDlg = [NSOpenPanel openPanel];
[openDlg setPrompt:#"Select"];
fileTypes = [NSArray arrayWithObjects:#"wmv", #"3gp", #"mp4", #"avi", #"mp3", #"mma", #"wav", #"jpeg", #"png", #"jpg", #"tiff", nil];
// NSArray *JpegfileTypes = [NSArray arrayWithObjects:#"jpeg", #"png", #"jpg", #"tiff", #"mp3" nil];
// Enable the selection of files in the dialog.
[openDlg setCanChooseFiles:YES];
//Enable multiple selection of files
[openDlg setAllowsMultipleSelection:YES];
// Enable the selection of directories in the dialog.
[openDlg setCanChooseDirectories:YES];
// Display the dialog. If the OK button was pressed,
// process the files.
if ( [openDlg runModalForDirectory:nil file:nil types:fileTypes] == NSOKButton )
{
// Get an array containing the full filenames of all
// files and directories selected.
files = [[openDlg filenames] retain];
int i; // Loop counter.
// Loop through all the files and process them.
for( i = 0; i < [files count]; i++ )
{
NSString *tempFilePath = [files objectAtIndex:i];
NSLog(#"tempFilePath::: %#",tempFilePath);
inputFilePath = [[files objectAtIndex:i] retain];
NSLog(#"filename::: %#", inputFilePath);
// Do something with the filename.
[selectedFile setStringValue:inputFilePath];
NSLog(#"selectedFile:::: %#", selectedFile);
}
}
}
Then after selection I have used this code to process the selected file.
- (IBAction)setMessage:(id)sender {
[fileGenProgress startAnimation:self];
NSString *message = [[NSString alloc] initWithFormat:#"Started"];
[lblMessage setStringValue:message];
[message release];
[self startProcessingVideoFile];
[self startProcessingAudioFile];
[self startProcessingJpg];
}
The issue I am facing is that, I am not getting that how would I compare the different strings like if the selected file was 3gp/mp4 or jpg or mp3. As if user has selected some video file then the method [self startProcessingVideoFile]; will run and if he has selected some JPG or PNG etc file then [self startProcessingAudioFile]; method will run.
As selected will be having a path not only the extension of the file. So in this scenario how can I force the - (IBAction)setMessage:(id)sender method to run the appropriate method.
You can get string's extension (format) like this:
NSString *extension = [stringPath pathExtension];
And for comparing now it's very easy when You know what extension Your file is. For example:
NSLog(extension);
if ([extension isEqualToString:#"3gp"] || [ext isEqualToString:#"mp4"]) {
[self startProcessingVideoFile];
}
and etc.
Update:
Your IBAction:SetMessage should look like this:
- (IBAction)setMessage:(id)sender {
[fileGenProgress startAnimation:self];
NSString *message = [[NSString alloc] initWithFormat:#"Started"];
[lblMessage setStringValue:message];
[message release];
NSString *extension = [inputFilePath pathExtension];
NSLog(extension);
if ([extension isEqualToString:#"3gp"] || [ext isEqualToString:#"mp4"]) {
[self startProcessingVideoFile];
}
// And etc for others formats.
//[self startProcessingAudioFile];
//[self startProcessingJpg];
}