NSTask not working for file path with special characters - ios

I am using NStask to get the folder size.Its working fine for normal file paths like home/ABC/Users/testUser/Documents. But it is not showing any output for file path like home/ABC/Users/testUser/Ω≈ç∂√√√∂ƒ∂.However I am getting proper output for the same file path on terminal. Any suggestion?
NSString* userName = #"test123_test123";
NSString* password = #"test";
NSString* serverIP = #"200.144.172.210";
NSString* sizeFolderPath = [[NSBundle mainBundle] pathForResource:#"demoUtilities" ofType:nil];
NSString* xml= #"--test";
NSString* passwordArg = [NSString stringWithFormat:#"--pwd-=%#",password];
NSString *filePath = #"UsersMac/Users/test/Ω≈ç∂√√√∂ƒ∂";
NSString* address = [NSString stringWithFormat:#"%##%#::home/%#", userName, serverIP,filePath];
NSArray* arguments = [NSMutableArray arrayWithObjects:xml,passwordArg,address,nil];
TestCommandExcecuter *cmExec = [[TestCommandExcecuter alloc]init];
[cmExec setCommandString:sizeFolderPath];
[cmExec setCommandArguments:arguments];

I am using this code:
Depricated from 2.0
NSDictionary *fileDictionary = [[NSFileManager defaultManager]
fileAttributesAtPath:filePath traverseLink:YES];
long long size = [fileDictionary fileSize];
NSLog(#"size :: %lld",size);
Latest :
NSDictionary *fileDictionary = [[NSFileManager defaultManager]
attributesOfItemAtPath:filePath error:nil];
long long size = [fileDictionary fileSize];
NSLog(#"size :: %lld",size);
Here is the reference link :
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFileManager_Class/Reference/Reference.html#//apple_ref/occ/instm/NSFileManager/attributesOfItemAtPath%3aerror%3a

Related

iOS11.2 NSFileManager API behivour is different than previous iOS versions

I am using below piece of code to calculate a checksum for files I added in a "temp" folder for app bundle. I am getting different checksum values in iOS11.2 compared to all lower iOS version. I was wondering what has changed among these versions? Is some changes in File system in iOS 11.2 is reason for the difference? Can somebody please throw light on the issue or faced similar issues? Below is the piece of code I used.
NSString* bundleRootDir;
bundleRootDir = [[NSBundle mainBundle] bundlePath];
NSLog(#"bundleRootDir %# ",bundleRootDir );
NSString *tmpDir = [bundleRootDir stringByAppendingPathComponent:#"temp"];
NSLog(#"tmpDir %# ",tmpDir);
NSFileManager *fileManager1=[[NSFileManager alloc] init];
NSDirectoryEnumerator *dirEnum = [fileManager1 enumeratorAtPath:tmpDir];
// NSFileManager *fileManager1 = [NSFileManager defaultManager];
//NSArray *filePathsArray1 = [fileManager1 subpathsOfDirectoryAtPath:tmpDir error:nil];
NSMutableData *allFilesData1 = [NSMutableData new];
uLong crc1 = crc32(0L, Z_NULL, 0);
NSInteger filecount1=0;
//for (NSString *file1 in filePathsArray1) {
NSString *file1;
while ((file1 = [dirEnum nextObject])) {
NSString *fullPathToFile1 = [tmpDir stringByAppendingPathComponent:file1];
BOOL isDirectory1;
if ([fileManager1 fileExistsAtPath:fullPathToFile1 isDirectory:&isDirectory1] && isDirectory1 ) {
// ignore directories...
continue;
}
else {
NSData *myData1 = [NSData dataWithContentsOfFile:fullPathToFile1];
[allFilesData1 appendData:myData1];
NSLog(#"Checksum files included %# , %d",fullPathToFile1,filecount1);
}
filecount1++;
}
NSLog(#"Checksum cal : length of data %lu",[allFilesData1 length]);
NSString *strData = [[NSString alloc]initWithData:allFilesData1 encoding:NSUTF8StringEncoding];
NSLog(#"All Data for checksum %#",strData);
crc1 = crc32(crc, [allFilesData1 bytes], [allFilesData1 length]);
NSLog(#"WL_INIT_PACKAGE - testWebResourcesChecksum crc32 output %lu",crc1);
NSString *checksum1 = [NSString stringWithFormat:#"%lu", crc1];
NSLog(#"WL_INIT_PACKAGE - testWebResourcesChecksum crc32 output %#",checksum1);

Cant write data to plist file in - objective c

I'm trying to read and write data to my plist file, While the reading part goes well, the writing part does nothing.
I might be mistaken for the writing part - i can't see any changes in my file under my bundle - it is still empty after my changes, and when i close the app and open it again - i still see empty email address line.
The code for writing (and placing the plist in the document folder for future writings)
NSFileManager *fileManger=[NSFileManager defaultManager];
NSError *error;
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doumentDirectoryPath=[pathsArray objectAtIndex:0];
NSString *destinationPath= [doumentDirectoryPath stringByAppendingPathComponent:#"userData.plist"];
NSLog(#"plist path %#",destinationPath);
if ([fileManger fileExistsAtPath:destinationPath]){
NSLog(#"database localtion %#",destinationPath);
//return;
}
NSString *sourcePath = [[[NSBundle mainBundle] resourcePath]stringByAppendingPathComponent:#"userData.plist"];
[fileManger copyItemAtPath:sourcePath toPath:destinationPath error:&error];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: sourcePath];
NSString *emailAddress = (NSString *)[dict objectForKey: #"emailAddress"];
if([emailAddress isEqualToString:#""])
{
// Do stuff
}
And for writing
NSArray *pathsArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *doumentDirectoryPath =[pathsArray objectAtIndex:0];
NSString *destinationPath = [doumentDirectoryPath stringByAppendingPathComponent:#"userData.plist"];
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile: destinationPath];
[plistDict setValue:#"myEmail#gmail.com" forKey:#"emailAddress"];
[plistDict writeToFile:destinationPath atomically: YES];
But as i said, nothing is changed in the file itself, and not even when i save, close the app and open it again (the string is always empty on my reading part)
Any help will be more than welcomed.

How to read a text file ,turn it into a string, then using arguments on it

Say If I had a string = "There were %# apples,I ate %#. Now I have %# apples" in text file "Apples.txt". This is how I will extract the text from it.
NSString *path = [[NSBundle mainBundle] pathForResource:#"Apples" ofType:#"txt"];
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
Now how do I pass the arguments to it so it looks like this:
"There were %# apples,I ate %#. Now I have %# apples", x, y, x-y
I am sure there is a way around this using NString with arguments? using
NSString with local argument functions? otherwise I will have to type all of my text in the file.m
This very crucial for my app.
You are probably looking for [NSString stringWithFormat:...].
Your complete code goes like this :
NSString *path = [[NSBundle mainBundle] pathForResource:#"Apples" ofType:#"txt"];
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSNumber *total = #100;
NSNumber *ate = #34;
NSString *fullString = [NSString stringWithFormat:content,total,ate, #([total integerValue] - [ate integerValue])];
NSLog(#"%#", fullString);
Output:
"There were 100 apples,I ate 34. Now I have 66 apples".
Use + stringWithFormat:
Here's the Apple reference

iOS use ID3Lib to edit ID3 tags from mp3 files in the NSDocsDir

I am using ID3Lib example project to edit Title, Album and Artist ID3 tags on mp3 files and all is good until I come to adding an image (cover Art) if any one has any ideas how to finish off the below code that would be great:
- (void)demo {
nImage = [UIImage imageNamed:#"amazing-grace.jpg"];//unused
NSString *imagePath = [[NSBundle mainBundle] pathForResource:#"amazing-grace" ofType:#"jpg"];
NSString *path = [[NSBundle mainBundle] pathForResource:#"amazing-grace-10s" ofType:#"mp3"];
NSArray *docPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [[docPaths objectAtIndex:0] stringByAppendingPathComponent:#"amazing-grace-10s.mp3"];
[[NSFileManager defaultManager] copyItemAtPath:path toPath:docPath error:nil];
// Read title tag
ID3_Tag tag;
tag.Link([path UTF8String]);
ID3_Frame *titleFrame = tag.Find(ID3FID_TITLE);
unicode_t const *value = titleFrame->GetField(ID3FN_TEXT)->GetRawUnicodeText();
NSString *title = [NSString stringWithCString:(char const *) value encoding:NSUnicodeStringEncoding];
NSLog(#"The title before is %#", title);
// Write title tag
tag.Link([docPath UTF8String]);
tag.Strip(ID3FID_TITLE);
tag.Strip(ID3FID_ALBUM);
tag.Strip(ID3FID_LEADARTIST);
tag.Clear();
ID3_Frame frame;
frame.SetID(ID3FID_TITLE);
frame.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);
NSString *newTitle = nTitle;
frame.GetField(ID3FN_TEXT)->Set((unicode_t *) [newTitle cStringUsingEncoding:NSUTF16StringEncoding]);
ID3_Frame frame2;
frame2.SetID(ID3FID_ALBUM);
frame2.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);
NSString *newAlbum = nAlbmum;
frame2.GetField(ID3FN_TEXT)->Set((unicode_t *) [newAlbum cStringUsingEncoding:NSUTF16StringEncoding]);
ID3_Frame frame3;
frame3.SetID(ID3FID_LEADARTIST);
frame3.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);
NSString *newArtist = nArtist;
frame3.GetField(ID3FN_TEXT)->Set((unicode_t *) [newArtist cStringUsingEncoding:NSUTF16StringEncoding]);
//this is the image code
ID3_Frame frame4;
frame4.SetID(ID3FID_PICTURE);
frame4.GetField(ID3FN_TEXTENC)->Set(ID3TE_UNICODE);// dont think this should be TEXTENC
NSString *newImage = imagePath;
frame4.GetField(ID3FN_DATA)->FromFile((const char *)[newImage cStringUsingEncoding:NSUTF16StringEncoding]);//this line is also probably wrong
tag.AddFrame(frame);
tag.AddFrame(frame2);
tag.AddFrame(frame3);
tag.AddFrame(frame4);
tag.SetPadding(false);
tag.SetUnsync(false);
tag.Update(ID3TT_ID3V2);
NSLog(#"The title after is %# The album after is %# The artist after is %# The artist after is %#", newTitle,newAlbum,newArtist,newImage);
}
Use file path with UTF-8 encoding and will work fine:
frame.GetField(ID3FN_DATA)->FromFile((const char *)[newImage cStringUsingEncoding:NSUTF8StringEncoding]);
I get this code, From this source: https://android.googlesource.com/platform/external/id3lib/+/8a58cac9f8db5ed55b02b3ac24156d628af923d1/examples/test_pic.cpp
frame.SetID(ID3FID_PICTURE);
frame.GetField(ID3FN_MIMETYPE)->Set("image/jpeg");
frame.GetField(ID3FN_PICTURETYPE)->Set(11);
frame.GetField(ID3FN_DESCRIPTION)->Set("B/W picture of Saint-Saëns");
//frame.GetField(ID3FN_DATA)->FromFile("composer.jpg");
frame.GetField(ID3FN_DATA)->FromFile((const char *)[newImage cStringUsingEncoding:NSUTF8StringEncoding]);
tag.AddFrame(frame);
And! this work nice. :D

Getting a list of files in a directory with a glob

For some crazy reason I can't find a way to get a list of files with a glob for a given directory.
I'm currently stuck with something along the lines of:
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager]
directoryContentsAtPath:bundleRoot];
..and then stripping out the stuff I don't want, which sucks. But what I'd really like is to be able to search for something like "foo*.jpg" instead of asking for the entire directory, but I've not been able to find anything like that.
So how the heck do you do it?
You can achieve this pretty easily with the help of NSPredicate, like so:
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSFileManager *fm = [NSFileManager defaultManager];
NSArray *dirContents = [fm contentsOfDirectoryAtPath:bundleRoot error:nil];
NSPredicate *fltr = [NSPredicate predicateWithFormat:#"self ENDSWITH '.jpg'"];
NSArray *onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr];
If you need to do it with NSURL instead it looks like this:
NSURL *bundleRoot = [[NSBundle mainBundle] bundleURL];
NSArray * dirContents =
[fm contentsOfDirectoryAtURL:bundleRoot
includingPropertiesForKeys:#[]
options:NSDirectoryEnumerationSkipsHiddenFiles
error:nil];
NSPredicate * fltr = [NSPredicate predicateWithFormat:#"pathExtension='jpg'"];
NSArray * onlyJPGs = [dirContents filteredArrayUsingPredicate:fltr];
This works quite nicely for IOS, but should also work for cocoa.
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSFileManager *manager = [NSFileManager defaultManager];
NSDirectoryEnumerator *direnum = [manager enumeratorAtPath:bundleRoot];
NSString *filename;
while ((filename = [direnum nextObject] )) {
//change the suffix to what you are looking for
if ([filename hasSuffix:#".data"]) {
// Do work here
NSLog(#"Files in resource folder: %#", filename);
}
}
What about using NSString's hasSuffix and hasPrefix methods? Something like (if you're searching for "foo*.jpg"):
NSString *bundleRoot = [[NSBundle mainBundle] bundlePath];
NSArray *dirContents = [[NSFileManager defaultManager] directoryContentsAtPath:bundleRoot];
for (NSString *tString in dirContents) {
if ([tString hasPrefix:#"foo"] && [tString hasSuffix:#".jpg"]) {
// do stuff
}
}
For simple, straightforward matches like that it would be simpler than using a regex library.
Very Simplest Method:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSFileManager *manager = [NSFileManager defaultManager];
NSArray *fileList = [manager contentsOfDirectoryAtPath:documentsDirectory
error:nil];
//--- Listing file by name sort
NSLog(#"\n File list %#",fileList);
//---- Sorting files by extension
NSArray *filePathsArray =
[[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory
error:nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF EndsWith '.png'"];
filePathsArray = [filePathsArray filteredArrayUsingPredicate:predicate];
NSLog(#"\n\n Sorted files by extension %#",filePathsArray);
Unix has a library that can perform file globbing operations for you. The functions and types are declared in a header called glob.h, so you'll need to #include it. If open up a terminal an open the man page for glob by typing man 3 glob you'll get all of the information you need to know to use the functions.
Below is an example of how you could populate an array the files that match a globbing pattern. When using the glob function there are a few things you need to keep in mind.
By default, the glob function looks for files in the current working directory. In order to search another directory you'll need to prepend the directory name to the globbing pattern as I've done in my example to get all of the files in /bin.
You are responsible for cleaning up the memory allocated by glob by calling globfree when you're done with the structure.
In my example I use the default options and no error callback. The man page covers all of the options in case there's something in there you want to use. If you're going to use the above code, I'd suggest adding it as a category to NSArray or something like that.
NSMutableArray* files = [NSMutableArray array];
glob_t gt;
char* pattern = "/bin/*";
if (glob(pattern, 0, NULL, &gt) == 0) {
int i;
for (i=0; i<gt.gl_matchc; i++) {
[files addObject: [NSString stringWithCString: gt.gl_pathv[i]]];
}
}
globfree(&gt);
return [NSArray arrayWithArray: files];
Edit: I've created a gist on github that contains the above code in a category called NSArray+Globbing.
You need to roll your own method to eliminate the files you don't want.
This isn't easy with the built in tools, but you could use RegExKit Lite to assist with finding the elements in the returned array you are interested in. According to the release notes this should work in both Cocoa and Cocoa-Touch applications.
Here's the demo code I wrote up in about 10 minutes. I changed the < and > to " because they weren't showing up inside the pre block, but it still works with the quotes. Maybe somebody who knows more about formatting code here on StackOverflow will correct this (Chris?).
This is a "Foundation Tool" Command Line Utility template project. If I get my git daemon up and running on my home server I'll edit this post to add the URL for the project.
#import "Foundation/Foundation.h"
#import "RegexKit/RegexKit.h"
#interface MTFileMatcher : NSObject
{
}
- (void)getFilesMatchingRegEx:(NSString*)inRegex forPath:(NSString*)inPath;
#end
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
MTFileMatcher* matcher = [[[MTFileMatcher alloc] init] autorelease];
[matcher getFilesMatchingRegEx:#"^.+\\.[Jj][Pp][Ee]?[Gg]$" forPath:[#"~/Pictures" stringByExpandingTildeInPath]];
[pool drain];
return 0;
}
#implementation MTFileMatcher
- (void)getFilesMatchingRegEx:(NSString*)inRegex forPath:(NSString*)inPath;
{
NSArray* filesAtPath = [[[NSFileManager defaultManager] directoryContentsAtPath:inPath] arrayByMatchingObjectsWithRegex:inRegex];
NSEnumerator* itr = [filesAtPath objectEnumerator];
NSString* obj;
while (obj = [itr nextObject])
{
NSLog(obj);
}
}
#end
I won't pretend to be an expert on the topic, but you should have access to both the glob and wordexp function from objective-c, no?
stringWithFileSystemRepresentation doesn't appear to be available in iOS.
Swift 5
This works for cocoa
let bundleRoot = Bundle.main.bundlePath
let manager = FileManager.default
let dirEnum = manager.enumerator(atPath: bundleRoot)
while let filename = dirEnum?.nextObject() as? String {
if filename.hasSuffix(".data"){
print("Files in resource folder: \(filename)")
}
}
Swift 5 for cocoa
// Getting the Contents of a Directory in a Single Batch Operation
let bundleRoot = Bundle.main.bundlePath
let url = URL(string: bundleRoot)
let properties: [URLResourceKey] = [ URLResourceKey.localizedNameKey, URLResourceKey.creationDateKey, URLResourceKey.localizedTypeDescriptionKey]
if let src = url{
do {
let paths = try FileManager.default.contentsOfDirectory(at: src, includingPropertiesForKeys: properties, options: [])
for p in paths {
if p.hasSuffix(".data"){
print("File Path is: \(p)")
}
}
} catch { }
}

Resources