I'm trying to convert a string returned from a library to an NSString to use with a separate Objective-C API, however whenever I parse the char* to a NSString it seems to stop at the first new line.
Example:
char *tst = "POST /servers HTTP/1.0\r\nContent-Type: test/json\r\nContent-Length:10\r\n\r\n1234567890";
NSLog(#"(TEST) : TST = %#", [NSString stringWithUTF8String:tst]);
Output:
<Notice>: (TEST) : TST = POST /servers HTTP/1.0
I'm not sure if this is it ACTUALLY not parsing past the first new line, or if NSLog simply isn't displaying the rest of the string past the first newline character. And that's what I'm trying to figure out.
Edit:
I've also tried replacing the \r\n instances with only \n with no change.
Example:
char *tst = "POST /servers HTTP/1.0\r\nContent-Type: test/json\r\nContent-Length:10\r\n\r\n1234567890";
NSString *tstStr = [NSString stringWithUTF8String:tst];
NSLog(#"(TEST) : TST = %#", [tstStr stringByReplacingOccurrencesOfString:#"\r\n" withString:#"\n"]);
Output:
<Notice>: (TEST) : TST = POST /servers HTTP/1.0
Your code should work. I just tried it and it worked for me, when looking at the debug log in Xcode.
Note that you'll actually get two new lines in your NSLog output, one for \r and one for \n.
Related
I’ve developed an iOS app in which we can send emojis from iOS to web portal and vice versa. All emojis sent from iOS to web portal are displaying perfect except “© and ®”.
Here is the emoji encoding piece of code.
NSData *data = [messageBody dataUsingEncoding:NSNonLossyASCIIStringEncoding];
NSString *encodedString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// This piece of code returns \251\256 as Unicodes of copyright and registered emojis, as these two Unicodes are not according to standard code so it doesn't display on web portal.
So what should I do to convert them standard Unicodes?
Test Run :
messageBody = #"Copy right symbol : © AND Registered Mark symbol : ®";
// Encoded string i get from the above encoding is
Copy right symbol : \\251 AND Registered Mark symbol : \\256
Where as it should like this (On standard unicodes )
Copy right symbol : \\u00A9 AND Registered Mark symbol : \\u00AE
First, I will try to provide the solution. Then I will try to explain why.
Escaping non-ASCII chars
To escape unicode chars in a string, you shouldn't rely on NSNonLossyASCIIStringEncoding. Below is the code that I use to escape unicode&non-ASCII chars in a string:
// NSMutableString category
- (void)appendChar:(unichar)charToAppend {
[self appendFormat:#"%C", charToAppend];
}
// NSString category
- (NSString *)UEscapedString {
char const hexChar[] = "0123456789ABCDEF";
NSMutableString *outputString = [NSMutableString string];
for (NSInteger i = 0; i < self.length; i++) {
unichar character = [self characterAtIndex:i];
if ((character >> 7) > 0) {
[outputString appendString:#"\\u"];
[outputString appendChar:(hexChar[(character >> 12) & 0xF])]; // append the hex character for the left-most 4-bits
[outputString appendChar:(hexChar[(character >> 8) & 0xF])]; // hex for the second group of 4-bits from the left
[outputString appendChar:(hexChar[(character >> 4) & 0xF])]; // hex for the third group
[outputString appendChar:(hexChar[character & 0xF])]; // hex for the last group, e.g., the right most 4-bits
} else {
[outputString appendChar:character];
}
}
return [outputString copy];
}
(NOTE: I guess Jon Rose's method does the same but I didn't wanna share a method that I didn't test)
Now you have the following string: Copy right symbol : \u00A9 AND Registered Mark symbol : \u00AE
Escaping unicode is done. Now let's convert it back to display the emojis.
Converting back
This is gonna be confusing at first but this is what it is:
NSData *data = [escapedString dataUsingEncoding:NSUTF8StringEncoding];
NSString *converted = [[NSString alloc] data encoding:NSNonLossyASCIIStringEncoding];
Now you have your emojis (and other non-ASCIIs) back.
What is happening?
The problem
In your case, you are trying to create a common language between your server side and your app. However, NSNonLossyASCIIStringEncoding is pretty bad choice for the purpose. Because this is a black-box that is created by Apple and we don't really know what it is exactly doing inside. As we can see, it converts unicode into \uXXXX while converting non-ASCII chars into \XXX. That is why you shouldn't rely on it to build a multi-platform system. There is no equivalent of it in backend platforms and Android.
Yet it is pretty mysterious, NSNonLossyASCIIStringEncoding can still convert back ® from \u00AE while it is converting it into \256 in the first place. I'm sure there are tools on other platforms to convert \uXXXX into unicode chars, that shouldn't be a problem for you.
messageBody is a string there is no reason to convert it to data only to convert it back to a string. Replace your code with
NSString *encodedString = messageBody;
If the messageBody object is incorrect then the way to fix it is to change the way it was created. The server sends data, not strings. The data that the server sends is encoding in some agreed upon way. Generally this encoding is UTF-8. If you know the encoding you can convert the data to a string; if you don't, then the data is gibberish that cannot be read. If the messageBody is incorrect, the problem occurred when it was converted from the data that the server sent. It seems likely that you are parsing it with the incorrect encoding.
The code you posted is just plain wrong. It converts a string to data using one encoding (ASCII) and the reads that data with a different encoding (UTF8). That is like translating a book to Spanish and then having a Portuguese speaker translate it back - it might work for some words, but it is still wrong.
If you are still having trouble then you should share the code of where messageBody is created.
If you server expects a ASCII string with all unicode characters changed to \u00xx then you should first yell at your server guy because he is an idiot. But if that doesn't work you can do the following code
NSString* messageBody = #"Copy right symbol : © AND Registered Mark symbol : ®";
NSData* utf32Data = [messageBody dataUsingEncoding:NSUTF32StringEncoding];
uint32_t *bytes = (uint32_t *) [utf32Data bytes];
NSMutableString* escapedString = [[NSMutableString alloc] init];
//Start a 1 because first bytes are for endianness
for(NSUInteger index = 1; index < escapedString.length / 4 ;index++ ){
uint32_t charValue = bytes[index];
if (charValue <= 127) {
[escapedString appendFormat:#"%C", (unichar)charValue];
}else{
[escapedString appendFormat:#"\\\\u%04X", charValue];
}
}
I'm really do not understand your problem.
You can simply convert ANY character into nsdata and return it into string.
You can simply pass UTF-8 string including both emoji and other symbols using POST request.
NSString* newStr = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
NSData* data = [newStr dataUsingEncoding:NSUTF8StringEncoding];
It have to work for both server and client side.
But, of course, you have got the other problem that some fonts do not support allutf-8 chars. That's why, e.g., in terminal you might not see some of them. But this is beyong the scope of this question.
NSNonLossyASCIIStringEncoding is used only then you really wnat to convert symbol into chain of symbols. But it is not needed.
I'm trying to replace a string that holds double backslash to a string with only single backslash, for example:
\\This\\Is\\Not\\Working
To:
\This\Is\Not\Working
Using:
str = [str stringByReplacingOccurrencesOfString:#"\\\\" withString#"\\"];
But for some reason, The string remains the same (with the double backslash) every single time. What am i doing wrong here?
Sadly, I misinterpreted the console log output. the string was fine, the debugger just showed the single slash as a doubled one. (For escaping purposes i'd imagine).
The below lines of code is fine:
NSString *str=#"\\This\\Is\\Not\\Working";
str = [str stringByReplacingOccurrencesOfString:#"\\\\" withString#"\\"];
Just check value by NSLog or by printing, because in debug console slash is represented as double slash.
Check image for more clear understanding:
NSString *Str = #"\\This\\Is\\Not\\Working";
NSLog(#"%#",Str);// print:-\This\Is\Not\Working
Str = [Str stringByReplacingOccurrencesOfString:#"\\\\" withString:#"\\"];// in this no replace occurres
NSLog(#"%#",Str); // print:-\This\Is\Not\Working
NSString *Str1 = #"\\\\This\\\\Is\\\\Not\\\\Working";
NSLog(#"%#",Str1);// print:-\\This\\Is\\Not\\Working
Str1 = [Str1 stringByReplacingOccurrencesOfString:#"\\\\" withString:#"\\"];
NSLog(#"%#",Str1);// print:-\This\Is\Not\Working
Try this:
NSString *str = #"\\This\\Is\\Not\\Working";
str = [str stringByReplacingOccurrencesOfString:#"\\" withString:#"\\\\"];
NSLog(#"%#", [str stringByReplacingOccurrencesOfString:#"\\\\" withString:#"\\"]);
1st Line is your user input.
2nd Line converts the double back-slashed user input string into four back-slashed string
3rd line simply replaces four back slashes with two back slashes which results in printing single back slash
I need to have a string like this,
Content-Disposition = name="uploaded file" in my HTTP request header.
I tried using escape sequences \" like this (as mentioned here)
NSString *valueString = #"name=\"uploadedfile\" ";
it returns me an output like this : "Content-Disposition" = "name=\"uploadedfile\"";
how can i do this? Please help. Thanks.
I've got some trouble to retrieve some text message from my server, especially with the encoding. Messages can be from many languages (so they can have accents, be in japanese,... ) and can include emoji.
I'm retrieving my message with a JSON with some info. Here is some logs example :
(lldb) po dataMessages
<__NSCFArray 0x14ecc7f0>(
{
author = "User 1";
text = "Hier, c'\U00c3\U00a9tait incroyable";
},
{
...
}
)
(lldb) po [[dataMessages objectAtIndex:0] objectForKey:#"text"]
Hier, c'était incroyable
I'm able to get the correct text with :
const char *c = [[[dataMessages objectAtIndex:indexPath.row] objectForKey:#"text"] cStringUsingEncoding:NSWindowsCP1252StringEncoding];
NSString *myMessage = [NSString stringWithCString:c encoding:NSUTF8StringEncoding];
However, if the message contains emoji, cStringUsingEncoding: return a NULL value.
I don't have control on my server, so I can't change their encoding before messages are sent to me.
The problem is determining the encoding correctly. Emoji are not part of NSWindowsCP1252StringEncoding so the conversion just fails.
Moreover, you are passing through an unnecessary stage. Do not make an intermediate C string! Just call NSString's initWithData:encoding:.
In your case, calling NSWindowsCP1252StringEncoding was always a mistake; I'm surprised that this worked for any string. C3A9 is Unicode (UTF8). So just call initWithData:encoding: with the UTF8 encoding (NSUTF8StringEncoding) from the get-go and all will be well.
I have a strange problem encoding my String
For example:
NSString *str = #"\u0e09\u0e31\u0e19\u0e23\u0e31\u0e01\u0e04\u0e38\u0e13";
NSString *utf = [str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog("utf: %#", utf);
This worked perfectly in log
utf: ฉันรักคุณ
But, when I try using my string that I parsed from JSON with the same string:
//str is string parse from JSON
NSString *str = [spaces stringByReplacingOccurrencesOfString:#"U" withString:#"u"];
NSLog("str: %#, str);
NSString *utf = [str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog("utf: %#", utf);
This didn't work in log
str: \u0e09\u0e31\u0e19\u0e23\u0e31\u0e01\u0e04\u0e38\u0e13
utf: \u0e09\u0e31\u0e19\u0e23\u0e31\u0e01\u0e04\u0e38\u0e13
I have been finding the answer for hours but still have no clue
Any would be very much appreciated! Thanks!
The string returned by JSON is actually different - it contains escaped backslashes (for each "\" you see when printing out the JSON string, what it actually contains is #"\").
In contrast, your manually created string already consists of "ฉันรักคุณ" from the beginning. You do not insert backslash characters - instead, #"\u0e09" (et. al.) is a single code point.
You could replace this line
NSString *utf = [str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
with this line
NSString *utf = str;
and your example output would not change. The stringByReplacingPercentEscapesUsingEncoding: refers to a different kind of escaping. See here about percent encoding.
What you need to actually do, is parse the string for string representations of unicode code points. Here is a link to one potential solution: Using Objective C/Cocoa to unescape unicode characters. However, I would advise you to check out the JSON library you are using (if you are using one) - it's likely that they provide some way to handle this for you transparently. E.g. JSONkit does.