I have a problem with data who are exported to a csv file.
It concerns the data with accented characters. Type Data is string.
in my file i have this :
Téléphones et internet; Abonnement iPad; 13,90 €; Débit
I would like to have :
Téléphones et internet; Abonnement iPad; 13,90€ Débit
what code should be used to do this?
Thank you.
EDIT : my code
NSMutableString *writeString = [NSMutableString string];
for (id object in [[self fetchedResultsController] fetchedObjects]) {
NSString * object1 = [[object valueForKey:#"object1Data"] description];
NSString * object2 = [[object valueForKey:#"object2Data"] description];
NSString * object3 = [[object valueForKey:#"object3Data"] description];
NSString * object4 = [[object valueForKey:#"object4Data"] description];;
[writeString appendString:[NSString stringWithFormat:#"%#; %#; %#; %#\n", object1, object2, object3, object4]];
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* savePath = [paths objectAtIndex:0];
savePath = [savePath stringByAppendingPathComponent:#"objectData.csv"];
[writeString writeToFile:savePath atomically:YES encoding:NSUTF8StringEncoding error:NULL];
EDIT2 : for viewing i use his :
QLPreviewController *previewController=[[QLPreviewController alloc]init];
previewController.delegate=self;
previewController.dataSource=self;
[self presentViewController:previewController animated:YES completion:nil];
[previewController.navigationItem setRightBarButtonItem:nil];
- (id <QLPreviewItem>)previewController:(QLPreviewController *)controller previewItemAtIndex:(NSInteger)index
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* savePath = [paths objectAtIndex:0];
savePath = [savePath stringByAppendingPathComponent:#"objectData.csv"];
return [NSURL fileURLWithPath:savePath];
}
- (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)controller
{
return 1;
}
Your output looks like it might be correct, the problem seems like it’s in how you are viewing it.
Are you importing it into Excel or something? Excel’s CSV import is very poor in my experience, and it won’t auto-detect incoming UTF-8 data.
It's likely the encoding that's causing an issue here.
As a side note it's a CSV = Comma Separated Values. You aren't putting the commas in .. ?
Change:
[writeString appendString:[NSString stringWithFormat:#"%#; %#; %#; %#\n", object1, object2, object3, object4]];
To:
[writeString appendString:[NSString stringWithFormat:#"%#;, %#;, %#;, %#\n", object1, object2, object3, object4]];
This will make the values appear in separate columns when opened in excel, unless you want it all in 1 column ... ?
Related
I want to be able to view images from a web folder inside my iPhone app. I know how to view the images with a specific url (i.e. www.mywebsite.com/image.jpg). That's easy. I just don't know how to asynchronously load an array. Basically I need to view images with a specific sequence (i.e. mywebsite.com/image_001.jpg, image_002.jpg, image_003.jpg, etc). There may be 10 or 100 images in a folder with that sequence. How do I let my app load images with a sequence?
Following code will sort images of this file format "imageName_number.jpg"
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *webDir=[documentsDirectory stringByAppendingPathComponent:#"WebFolder"];
NSFileManager *filemgr;
NSMutableArray *fileNum;
fileNum=[[NSMutableArray alloc]init];
filemgr = [NSFileManager defaultManager];
//This will give all files of your web directory you can uncomment to get dynamically
//NSArray *filelist = [filemgr contentsOfDirectoryAtPath: webDir error: nil];
// this is just example shows how unsorted will be used to sort image no you can comment this line
NSArray *filelist=[[NSArray alloc]initWithObjects:#"abc_001.jpg",#"def_005.jpg",#"abc_002.jpg",#"abc_0103.jpg",#"abc_0010.jpg",#"abc_008.jpg", nil];
int count = (int)[filelist count];
NSMutableDictionary *dictFileNumWithPath=[[NSMutableDictionary alloc]init];
NSString *imageSeprator=#"_";
for (int i = 0; i < count; i++){
NSString *imageName=[filelist objectAtIndex: i];
if (!([imageName rangeOfString:imageSeprator].location == NSNotFound)) {
NSRange startRange = [imageName rangeOfString:imageSeprator];
NSRange endRange = [imageName rangeOfString:#".jpg"];
NSRange searchRange = NSMakeRange( startRange.location+1, endRange.location-endRange.length);
NSString *strNum= [imageName substringWithRange:searchRange];
NSString *webPath=[webDir stringByAppendingPathComponent:imageName];
[dictFileNumWithPath setObject:[NSNumber numberWithInt:[strNum intValue]] forKey:webPath];
}
}
NSArray *sortedKeysFilePathArray =
[dictFileNumWithPath keysSortedByValueUsingSelector:#selector(compare:)];
NSLog(#"%#", sortedKeysFilePathArray);
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
I am quite new to iOS and Objective-c.
I am trying to auto generate a pList in my app that looks like this.
I've so far been able to create the file making it a normal Value => Key file if i replace my for loop by
for (NSString* exercisePictureName in bigPictureData) {
[data setObject:exercisePictureName forKey:exercisePictureName];
}
but my problem is that I have no idea how to structure the logic at the end of my loop to create a file structure like shown in the picture. As it has to be exact.
Could anyone point me in the right direction on how to structure my loop so that it creates the file with the right format????
- (void) createImageListFromSource {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"exercisePictures.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
path = [documentsDirectory stringByAppendingPathComponent: [NSString stringWithFormat: #"exercisePictures.plist"] ];
}
//To insert the data into the plist
NSArray* bicepPictureData = [self getAllimagesThatStartWith:#"bicep-"];
NSArray* tricepPictureData = [self getAllimagesThatStartWith:#"tricep-"];
NSArray* absPictureData = [self getAllimagesThatStartWith:#"abs-"];
NSArray* chestPictureData = [self getAllimagesThatStartWith:#"chest-"];
NSArray* backPictureData = [self getAllimagesThatStartWith:#"back-"];
NSArray* bigPictureData = [bicepPictureData arrayByAddingObjectsFromArray:tricepPictureData];
bigPictureData = [bigPictureData arrayByAddingObjectsFromArray:absPictureData];
bigPictureData = [bigPictureData arrayByAddingObjectsFromArray:chestPictureData];
bigPictureData = [bigPictureData arrayByAddingObjectsFromArray:backPictureData];
NSArray* finalData = [[NSArray alloc] init];
for (NSString* exercisePictureName in bigPictureData) {
NSDictionary* data = [[NSDictionary alloc] initWithObjectsAndKeys:exercisePictureName,#"text",exercisePictureName,#"image", nil];
[finalData arrayByAddingObject:data];
NSLog(#"%#",data);
}
NSLog(#"%#",finalData);
[finalData writeToFile: path atomically:YES];
}
What you have is an array of dictionaries. Pseudocode to show the structure:
NSMutableArray* arr = [NSMutableArray array];
for (...) {
NSDictionary* d = #{#"image": something, #"text": somethingelse};
[arr addObject:d];
}
When you are all done, just save the array directly with writeToURL....
I am using this code to get book names from a config.plist file. However my memory management is problematic. The '[dict release]' breaks the app completely and it exits.
The code works when the '[dict release]' is removed but it causes memory leaks as far as I can tell.
bnames is a global NSMutableArray
What am I doing wrong?
- (NSString *)loadBookname: (NSInteger) bookToLoad {
bookToLoad = [self bookOrder:bookToLoad];
//---get the path to the property list file---
plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
//---if the property list file can be found---
if ([[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
//---load the content of the property list file into a NSDictionary object---
dict = [[NSDictionary alloc] initWithContentsOfFile:plistFileNameConf];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
else {
//---load the property list from the Resources folder---
NSString *pListPath = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
dict = [[NSDictionary alloc] initWithContentsOfFile:pListPath];
bnames = [dict valueForKey:#"BookNames"];
[dict release];
}
plistFileNameConf = nil;
NSString *bookNameTemp;
bookNameTemp = [bnames objectAtIndex:bookToLoad - 1];
NSLog(#"bookName: %#", bookNameTemp);
return bookNameTemp;
}
You need to allocate your array properly:
bnames = [[NSArray alloc] initWithArray:[dict valueForKey:#"BookNames"]];
Double check that your dict returns the right data type.
There does not appear to be anything wrong with the way you allocate NSDictionary (although you could also use the [NSDictionary dictionaryWithContentsOfFile:] and save yourself having to worry about the release.
Either way I would suggest the issue is not with the [release] but probably the line BEFORE release:
bnames = [dict valueForKey:#"BookNames"];
a) Where is that allocated. I don't see an allocation or declaration of it anywhere?
b) What type of value do you expect back?
Put a break point on it and make sure your getting what you expect or anything.
If dict is not already a strong property, make it one. Then, use self.dict when assigning to it (and keep the release).
I've found what appears to be a better solution to the issue. This lets iOS manage the memory.
//---finds the path to the application's Documents directory---
- (NSString *) documentsPath {
NSLog(#"Start documentsPath");
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [paths objectAtIndex:0];
// NSLog(#"Found documentsPath 40");
NSLog(#"End documentsPath");
return documentsDir;
}
- (NSString *) configPath {
NSLog(#"Start configPath");
NSString *plistFileNameConf = [[self documentsPath] stringByAppendingPathComponent:#"Config.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistFileNameConf]) {
plistFileNameConf = [[NSBundle mainBundle] pathForResource:#"Config" ofType:#"plist"];
}
NSLog(#"plistFile: %#",plistFileNameConf);
NSLog(#"End configPath");
return plistFileNameConf;
}
The following calls the above code as necessary:
NSString *Choice;
NSArray *properties;
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:[self configPath]];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!temp) {
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
Choice = [temp objectForKey:#"Choice"];
properties = [temp objectForKey:Choice];
I have a NSArray in this way
myArray[0] = [string1, string2, string3, string4, mySecondArray, string5]; (at 0 position)
I write this array inside a txt file in this way
NSString *outputString = #"";
for (int i = 0; i< myArray.count; i++){
outputString = [outputString stringByAppendingString:[[[myArray objectAtIndex:i ] componentsJoinedByString:#"#"] stringByAppendingString:#";"]];
}
NSLog(#"string to write = %#", outputString);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"Text.txt"];
NSError *error;
[outputString writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
then the result of NSLog is = (position 0 of myArray) (mySecond array is empty)
one#two#three#four#(
)#five;
I want to know:
Why the array wrap?
When I'll go to read this string how can I know that it's mySecondArray?
When you message componentsJoinedByString: on an NSArray object, it calls description on each of its objects and concatenates them in order. For NSString objects, they are the strings themselves. The array wraps because of the way the description method has been implemented.
As for identifying the array while you are reading the string back, I don't think it is possible. You should consider writing the array to the file rather i.e.
[[myArray objectAtIndex:0] writeToFile:filePath atomically:YES];
or
[myArray writeToFile:filePath atomically:YES];
depending on the requirement. This way you will be able to read the elements back properly.