objective-c how to encode NSArray with UTF8? - objective-c

I have scandinavian alphabets in my array like æ, ø, å. With NSLog the output showed these alphabets as scrambled codes. How to encode NSArray with UTF8? Any help is appreciated.
I tried only:
NSArray *nnoWords = [[NSArray arrayWithArray:newNoWords] retain];
NSLog (#"nnoWords: %# ", nnoWords);
newNoWords is a NSMutableArray. nnoWords containt normal objects like NSString hello, pear, apple, etc. taken from a txt file.
EDIT 29 august 2011:
nnoWords comes from this, converted to NSMutable and then back to NSArray, thus called nnoWords. And words.txt is encoded in UTF8.
NSArray *noWords = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:#"words" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL] componentsSeparatedByString:#"\n"]];
I have also tried:
NSString *norsk = #"æ ø å";
NSLog (#"%#", norsk);
And the output is correct:
2011-08-29 13:15:23.302 scanner2[29776:207] æ ø å

The problem is the Xcode console. If you view the output from Terminal.app, you will see it is as expected.
Test case:
//clang -framework Foundation -o log_utf8 log_utf8.m
#import <Foundation/Foundation.h>
int
main(void)
{
NSString *word = #"en ord på Svenska";
NSLog(#"%#", word);
}
Sample output:
StackOverflow$ clang -framework Foundation log_utf8.m -o log_utf8
StackOverflow$ ./log_utf8
2011-08-28 20:10:09.268 log_utf8[65105:707] en ord på Svenska
If you are still seeing gibberish when you view the output from something other than Xcode's questionable built-in console, then you need to examine how you're getting your string data:
How does the text with non-ASCII characters enter your application?
What encoding does NSString think that text is in?
What encoding is it actually in? If the text comes from a file, then the file command might be able to answer this for you.

Try this:
NSLog(#"%S", [[theArray description] cStringUsingEncoding:NSUTF16LittleEndianStringEncoding]);
from this question: NSLog incorrect encoding

Related

in objective-c is there any easy way to add backslash in front of special characters?

Note: Not sure why this is marked as duplicate as I clearly stated that I don't want to use stringByReplacingOccurrencesOfString over and over again.
I have a question regarding the special character filename.
I have implemented a program, so that when you open a file or multiple files, the program will read all these filenames and local path and store them into the NSMutableArray. This part works perfectly without a problem.
My program also need to use NSTask to manipulate these files. However, the problem is, sometimes filename will contain special characters, for example, /Users/josh/Desktop/Screen Shot 2013-03-19 at 2.05.06 PM.png.
I have to replace space with backslash and space
NSString *urlPath = [[self url] path];
urlPath = [urlPath stringByReplacingOccurrencesOfString:#"(" withString:#"\\("];
urlPath = [urlPath stringByReplacingOccurrencesOfString:#")" withString:#"\\)"];
urlPath = [urlPath stringByReplacingOccurrencesOfString:#" " withString:#"\\ "];
to: /Users/josh/Desktop/Screen\ Shot\ 2013-03-19\ at\ 2.05.06\ PM.png
so that I can manipulate the file properly.
Same for the ( and ). I also need to add backslash before that.
but there are too many special characters. ie.
/Users/josh/Desktop/~!##$?:<,.>%^&*()_+`-={}[]\|'';.txt
I need to change to:
/Users/josh/Desktop/\~\!#\#\$\?\:\<\,.\>\%^\&\*\(\)_+\`-\=\{\}\[\]\\\|\'\'\;.txt
and not to mention other special characters (ie. accent)
Is there any easy way to put a backslash in front of each special character, as I don't want to keep calling stringByReplacingOccurrencesOfString over and over again.
As described in NSTask's documentation for the setArguments: method, there should be no need to do special quoting:
Discussion
The NSTask object converts both path and the strings in
arguments to appropriate C-style strings (using
fileSystemRepresentation) before passing them to the task via argv[].
The strings in arguments do not undergo shell expansion, so you do not
need to do special quoting, and shell variables, such as $PWD, are not
resolved.
If you feel it is necessary, can you please provide some examples of the commands you want to run in the NSTask?
[UPDATE]: I see in the comments that you indeed are using the NSTask to execute a bash shell with -c, which I had wondered about. I've generally used NSTask to execute the command directly rather than going through the shell, like this:
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/bin/ls"];
[task setArguments:[NSArray arrayWithObjects:#"-l", self.url.path, nil]];
Can you give a more accurate example of the actual command you want to run? For example, are you piping a series of commands together? Perhaps there might be an alternate way to achieve the same results without the need for using the bash shell...
I think you may be able to use an NSRegularExpressionSearch search.
It would look something like this
+ (NSString *) addBackslashes: (NSString *) string
{
// First convert the name string to a pure ASCII string
NSData *asciiData = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *asciiString = [[[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding] lowercaseString];
// Define the characters that we will replace
NSString *searchCharacters = #"PUT IN ALL OF YOUR SPECIAL CHARACTERS HERE";
// example NSString *searchCharacters = #"!##$%&*()";
// replace them
NSString *regExPattern = [NSString stringWithFormat:#"[%#]", searchCharacters];
string = [asciiString stringByReplacingOccurrencesOfString:regExPattern withString: [NSString stringWithFormat:#"\\%#", regExPattern] options:NSRegularExpressionSearch range:NSMakeRange(0, asciiString.length)];
return string;
}
you could maintain a set of strings that need to be escaped and use NSScanner to build the new string by iterating the the source string and each time a problematic character is found u first add \\ to a destination string and continue coping the next chars.
NSString *sourceString = #"/Users/josh/Desktop/\"Screen Shot\" 2013-03-19 at 2\\05\\06 PM.png";
NSMutableString *destString = [#"" mutableCopy];
NSCharacterSet *escapeCharsSet = [NSCharacterSet characterSetWithCharactersInString:#" ()\\"];
NSScanner *scanner = [NSScanner scannerWithString:sourceString];
while (![scanner isAtEnd]) {
NSString *tempString;
[scanner scanUpToCharactersFromSet:escapeCharsSet intoString:&tempString];
if([scanner isAtEnd]){
[destString appendString:tempString];
}
else {
[destString appendFormat:#"%#\\%#", tempString, [sourceString substringWithRange:NSMakeRange([scanner scanLocation], 1)]];
[scanner setScanLocation:[scanner scanLocation]+1];
}
}
NSLog(#"\n%#\n%#", sourceString, destString);
result:
/Users/josh/Desktop/Screen Shot 2013-03-19 at 2.05.06 PM.png
/Users/josh/Desktop/Screen\ Shot\ 2013-03-19\ at\ 2.05.06\ PM.png

Not showing smily ( Emoji ) in in UITextView in iOS?

I have stored all uni-codes(emoji characters) in plist supported by iphone. When i write directly as
- (IBAction)sendButtonSelected:(id)sender {
NSMutableArray *emoticonsArray = [[NSMutableArray alloc]initWithObjects:#"\ue415",nil];
NSString *imageNameToPass = [NSString stringWithFormat:#"%#",[emoticonsArray objectAtIndex:0]];
NSLog(#"imageNameToPass1...%#",imageNameToPass);
messageTextView.text =imageNameToPass;
}
it show emoji in textview but as soon as i fetch from plist
NSString *plistPath1 = [[NSBundle mainBundle] pathForResource:#"unicodes" ofType:#"plist"];
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath1];
activeArray= [dictionary objectForKey:categoryString];
NSLog(#"activeArray...%#",activeArray);
emoticonsArrayForHomeEmoji = [[NSMutableArray alloc]initWithCapacity:[activeArray count]];
for(int i=0; i<[activeArray count]; i++)
{
id objects = (id)[activeArray objectAtIndex:i];
[emoticonsArrayForHomeEmoji insertObject:objects atIndex:i];
}
NSString *imageNameToPass = [NSString stringWithFormat:#"%#",[emoticonsArrayForHomeEmoji
objectAtIndex:0]];
NSLog(#"imageNameToPass1...%#",imageNameToPass);
messageTextView.text =imageNameToPass;
then it shows unicode as text \ue415 in text view instead of emoji.
What i am doing wrong?. Please help me out!
Wel said by #AliSoftware, the Plist data will be read as-it is, so you can add the emojis to your plist by following this steps:
1) Go to your top bar, and click on Edit.
2) Now select Special Characters
3) Now drag and drop emoji to plist.
For more details I am adding snap shots. take a look at it.
The \uxxxx notation is only interpreted by the compiler (as the source code is usually in ASCII or MacRoman or whatever but not often UTF8)
Plist files uses the characters directly, and are encoded in UTF8.
So you should insert the emoji character itself into the plist directly, instead of using the \uxxxx notation, as the Plist data will be read as-is.
Lion and Mountain Lion Keyboard palettes contains emoji characters directly, so that should not be difficult to insert the characters when editing the PLIST anyway.

Output Spanish Character

I need to print Ñ to screen. I'm using this code and it works fine for everything but the capital Ñ. It displays this: √ë.
CGContextShowText(textContext, [text UTF8String], strlen([text UTF8String]));
And, all these encodings give the same thing:
const char *cn = "Ñ";
NSLog(#"%#", [NSString stringWithUTF8String: cn]);
NSLog(#"%C", 0x00d1);
NSLog(#"%#", #"Ñ");
2012-06-20 16:27:09.388 app[406:707] Ñ
2012-06-20 16:27:09.392 app[406:707] Ñ
2012-06-20 16:27:09.394 app[406:707] Ñ
So, how do I display Ñ and not √ë, using NSLog or CGContextShowText?
The following works properly on my Mac:
NSLog(#"%#", [NSString stringWithUTF8String:"Ñ"]);
Make sure the text encoding has been set correctly in Xcode:

How to prevent the OS X text layout engine from automatically "flipping" lines with right-to-left text?

How do I make Apple's Cocoa GUI controls not automatically "flip" lines that contain right-to-left text (such as arabic)?
Behold my test case, wherein I plan to keep the asterisks (**) in the beginning of the lines when they are printed on screen:
#import <Foundation/Foundation.h>
int main(int argc, char *argv[])
{
NSAutoreleasePool *autoReleasePool = [[NSAutoreleasePool alloc] init];
NSString *str1 = #"** english first then arabic تجر\n";
NSString *str2 = #"** تجر arabic first then english\n";
[str1 writeToFile:#"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:NULL];
[str2 writeToFile:#"/dev/stdout" atomically:NO encoding:NSUTF8StringEncoding error:NULL];
[autoReleasePool release];
return 0;
}
When I run this in Terminal.app I get:
$ gcc -framework Foundation test.m
$ ./a.out
** english first then arabic تجر
arabic first then english تجر **
In iTerm, though, the lines don't get "flipped":
$ gcc -framework Foundation test.m
$ ./a.out
** english first then arabic تجر
** تجر arabic first then english
Based on some cursory examination of iTerm's code, it looks like this is due to iTerm's "manual" character-by-character handling of output and Terminal.app's (assumed) use of OS-native string layout APIs. Is there any way to prevent this "flippage" from occurring when using, for example, NSTextView to display these kinds of strings? I couldn't find any answers in Apple's documentation.
I'm running an english Mac OS 10.5.6 with english as the #1 language in the list under System Preferences > International > Language.
Have you tried:
[nstextviewobj setBaseWritingDirection:NSWritingDirectionLeftToRight];
This method is in the NSText parent class.

NSLog incorrect encoding

I've got a problem with the following code:
NSString *strValue=#"你好";
char temp[200];
strcpy(temp, [strValue UTF8String]);
printf("%s", temp);
NSLog(#"%s", temp);
in the first line of the codes, two Chinese characters are double quoted. The problem is printf function can display the Chinese characters properly, but NSLog can't.
Thanks to all. I figured out a solution for this problem. Foundation uses UTF-16 by default, so in order to use NSLog to output the c string in the example, I have to use cStringUsingEncoding to get UTF-16 c string and use %S to replace %s.
NSString *strValue=#"你好";
char temp[200];
strcpy(temp, [strValue UTF8String]);
printf("%s", temp);
strcpy(temp, [strValue cStringUsingEncoding:NSUTF16LittleEndianStringEncoding]);
NSLog(#"%S", temp);
NSLog's %s format specifier is in the system encoding, which seems to always be MacRoman and not unicode, so it can only display characters in MacRoman encoding. Your best option with NSLog is just to use the native object format specifier %# and pass the NSString directly instead of converting it to a C String. If you only have a C string and you want to use NSLog to display a message instead of printf or asl, you will have to do something like Don suggests in order to convert the string to an NSString object first.
So, all of these should display the expected string:
NSString *str = #"你好";
const char *cstr = [str UTF8String];
NSLog(#"%#", str);
printf("%s\n", cstr);
NSLog(#"%#", [NSString stringWithUTF8String:cstr]);
If you do decide to use asl, note that while it accepts strings in UTF8 format and passes the correct encoding to the syslog daemon (so it will show up properly in the console), it encodes the string for visual encoding when displaying to the terminal or logging to a file handle, so non-ASCII values will be displayed as escaped character sequences.
My guess is that NSLog assumes a different encoding for 8-bit C-strings than UTF-8, and it may be one that doesn't support Chinese characters. Awkward as it is, you might try this:
NSLog(#"%#", [NSString stringWithCString: temp encoding: NSUTF8StringEncoding]);
I know you are probably looking for an answer that will help you understand what's going on.
But this is what you could do to solve your problem right now:
NSLog(#"%#", strValue);
# define NSLogUTF8(a,b) NSLog(a,[NSString stringWithCString:[[NSString stringWithFormat:#"%#",b] cStringUsingEncoding:NSUTF8StringEncoding] encoding:NSNonLossyASCIIStringEncoding])
#define NSLogUTF8Ex(a,b) NSLog(a,[MLTool utf8toNString:[NSString stringWithFormat:#"%#",b]])
+(NSString*)utf8toNString:(NSString*)str{
NSString* strT= [str stringByReplacingOccurrencesOfString:#"\\U" withString:#"\\u"];
//NSString *strT = [strTemp mutableCopy];
CFStringRef transform = CFSTR("Any-Hex/Java");
CFStringTransform((__bridge CFMutableStringRef)strT, NULL, transform, YES);
return strT;
}