I am trying to decode some text sent from a server that is URLEncoded, and this is the best method I managed to find.
I use these standard functions for URLEncododing:
NSString* encodeToPercentEscapeString(NSString *string) {
return (__bridge NSString *)
CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef) string,
NULL,
(CFStringRef) #"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
}
NSString* decodeFromPercentEscapeString(NSString *string) {
return (__bridge NSString *)
CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL,
(__bridge CFStringRef) string,
CFSTR(""),
kCFStringEncodingUTF8);
}
If I encode special characters:
NSString* encoded = encodeToPercentEscapeString(#"ąśżźćęółń");
I get #"%C4%85%C5%9B%C5%BC%C5%BA%C4%87%C4%99%C3%B3%C5%82%C5%84"
which is ok.
But if I try to decode it:
NSString* original = decodeFromPercentEscapeString(encoded);
I get :#"ńÖŇõŇľŇļńáńô√≥ŇāŇĄ".
Why?
Is there a better method to decode URLEncoded text?
Have you tried -[NSString stringByReplacingPercentEscapesUsingEncoding:]?
Also, you are using the bridging casts incorrectly. The created strings will leak, because ARC doesn't know it owns them. Use CFBridgingRelease(). It's nice because it is a variant of CFRelease() which is normally necessary to balance a Core Foundation "Create" function, but it cooperates with ARC.
Related
I am converting NSData to NSString which I got as response of a url using the following method.
NSString *result = [[NSString alloc] initWithData:_Data encoding:NSUTF8StringEncoding];
It works fine and I am using this for a long time but today I faced an issue while loading the data (paging) at one page my result gives null string.
So I searched SO and found a method from this link NSData to NSString converstion problem!
[NSString stringWithCString:[theData bytes] length:[theData length]];
and this works fine.
My queries,
The method was deprecated in iOS 2.0. If I use this will I be facing any issue in future?
I think this is the text that made the method fail What is this and is there any way that I can encode this using NSUTF8StringEncoding?
What is the the alternative encoding that I can use for encoding all the type of characters like in the above pic?
In order to obtain the type of the content which is sent by the server, you need to inspect the Content-Type header of the response.
The content type's value specifies a "MIMI type", e.g.:
Content-Type: text/plain
A Content-Type's value may additionally specify a character encoding, e.g.:
Content-Type: text/plain; charset=utf-8
Each MIME type should define a "default" charset, which is to be used when there is no charset parameter specified.
For text/* media types the default charset is US-ASCII.
(see RFC 6657, §3).
The following code snippet demonstrates how to safely encode the body of a response:
- (NSString*) bodyString {
CFStringEncoding cfEncoding = NSASCIIStringEncoding;
NSString* textEncodingName = self.response.textEncodingName;
if (textEncodingName) {
cfEncoding = CFStringConvertIANACharSetNameToEncoding( (__bridge CFStringRef)(textEncodingName) );
}
if (cfEncoding != kCFStringEncodingInvalidId) {
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
return [[NSString alloc] initWithData:self.body encoding:encoding];
}
else {
return [self.body description];
}
}
Note:
body is a property returning a NSData object representing the response data.
response is a property returning the NSHTTPURLResponse object.
If
NSString *result = [[NSString alloc] initWithData:_Data encoding:NSUTF8StringEncoding];
returns nil then _Data does not contain a valid string in UTF-8 encoding.
You said that
[NSString stringWithCString:[theData bytes] length:[theData length]];
works fine in your case. This method
interprets the data bytes in the "default C string encoding", but it is unspecified which
encoding that is (and therefore this method is deprecated and should not be used).
I think the default C string encoding is still "Mac Roman". In that case
NSString *result = [[NSString alloc] initWithData:_Data encoding:NSMacOSRomanStringEncoding];
would be the correct solution. But in any case, you should find out which encoding
the web service uses for the response, and specify that in the initWithData:encoding:
method.
Try this
NSString *theString = [NSString stringWithFormat:#"To be continued%C", ellipsis];
NSData *asciiData = [theString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *asciiString = [[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding];
NSLog(#"Original: %# (length %d)", theString, [theString length]);
NSLog(#"Converted: %# (length %d)", asciiString, [asciiString length]);
It is due to the uncorrect string encoding.
You can try:
save the NSData to the disk with dataPath
use the NSString class method to create the string:
+ (id)stringWithContentsOfURL:(NSURL *)url usedEncoding:(NSStringEncoding *)enc error:(NSError **)error
Notice here:
enc
Upon return, if url is read successfully, contains the encoding used to interpret the data.
So if the method successes, you can get the correct string and all is done by the iOS.
I'm doing this to encode my URL in this way,
but its not working,
i got the result in NSLog but its the same url nothing is changing.
Please help me to sort this issue.
below is my code :
NSString *unencodedUrlString =
[#"http://www.demii.com/demo/dooponz/admin/index.php/chat/new_message/4/1/you/2,7"
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#" %#", unencodedUrlString);
Thanks in advance
The comma is a legal URL character, therefore stringByAddingPercentEscapesUsingEncoding leaves "2,7" as it is and does not replace it by "2%2C7".
If you want the comma to be replaced by a percent escape (as I understand from your
comment to the question), you can use CFURLCreateStringByAddingPercentEscapes
instead:
NSString *str = #"http://www.demii.com/demo/dooponz/admin/index.php/chat/new_message/4/1/you/2,7";
NSString *encoded = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(__bridge CFStringRef)(str), NULL, CFSTR(","), kCFStringEncodingUTF8));
NSLog(#"%#", encoded);
Output:
http://www.demii.com/demo/dooponz/admin/index.php/chat/new_message/4/1/you/2%2C7
The fourth parameter CFSTR(",") specifies that the comma should be replaced by
a percent escape even if it is a legal URL character.
Use this
NSString *str = [NSString stringWithFormat:#"http://www.demii.com/demo/dooponz/admin/index.php/chat/new_message/4/1/you/2,7"];
NSString *path = [str stringByReplacingOccurrencesOfString:#"," withString:#"/"];
NSLog(#"%#",path);
This will do nothing but will make , to /.
NSString* urlEncode(NSString * url)
{
string inStr = StringFromNSString(url);
CFStringRef inStringRef = CFStringCreateWithCString( kCFAllocatorDefault, inStr.c_str(), kCFStringEncodingUTF8 );
NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,(CFStringRef)inStringRef,NULL,(CFStringRef)#"!*’();:#&=+$,/?%#[]",kCFStringEncodingUTF8 );
return encodedString;
}
I am using above method to encode url... even though my app is crashing saying
<body>
<div id="content">
<h1>An Error Was Encountered</h1>
<p>The URI you submitted has disallowed characters.</p> </div>
</body>
</html>
terminate called after throwing an instance of 'std::invalid_argument'
what():
Any idea.. What is wrong with my code?
FYI: It is crashing in this method JSONNode jsonObject0 = libJSON::parse( inResponseData );
UPDATED: The server which i am sending message is UNIX server is it causing problem?
You don't need to create the inStr or inStringRef temporary variables. The types NSString* and CFStringRef are "toll free bridge" types. These types are interchangable with just a simple cast.
You can find more information about toll free bridging here: http://www.mikeash.com/pyblog/friday-qa-2010-01-22-toll-free-bridging-internals.html
That said, you can simplify your method to just the following:
-(NSString*) urlEncode
{
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes( NULL, (CFStringRef)self, NULL, (CFStringRef)#"!*'();:#&=+$,/?%#[]", kCFStringEncodingUTF8 );
return [encodedString autorelease];
}
The above is best implemented as an NSString category (note the use of self as the value to encode).
This works fine for me. I use CFSTR instead of (CFStringRef)#"!*’();:#&=+$,/?%#[]"
- (NSString *)encodedURLParameterString {
NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)self,
NULL,
CFSTR(":/=,!$& '()*+;[]##?"),
kCFStringEncodingUTF8);
return [result autorelease];
}
You can try this
NSString *sampleUrl = #"http://www.google.com/search.jsp?params=Java Developer";
NSString* encodedUrl = [sampleUrl stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
You need to make sure that you're not URL encoding more than you need. If you're going to be using this encoding string as part of an actual URL, then you should know that there are only portions of the URL that are supposed to be encoded, namely the query string (there are other bits as well, but 95% of the time, this has to do with the query).
In other words, your URL should be:
scheme://host/path?<key>=<value>&<key>=<value>
In this, ONLY the stuff inside the angle brackets (<key> and <value>) should be URL encoded.
It was the problem in UNIX server... It was giving wrong data.
NSString *encodedstring = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef)yoururlstring,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
this code works perfect
Here is the best way to encode the formatted URLString:
urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
Instead of using below as it has some memory management issues.
NSString *encodedstring = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(__bridge CFStringRef)yoururlstring,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8);
Really quick question that is driving me INSANE. I was wondering if someone could tell me why this line is leaking?
NSString *post = [NSString stringWithFormat:#"<someXML><tagWithVar=%#></tagWithVar></someXML>",var];
post = [NSString stringWithFormat:#"xmlValue=%#",(NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)post,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 )];
I am just encoding a string into a URL format. From my understanding, stringWithFormat: should return an autoreleased object. Apparently that is not the case. It works, but leaks. Any ideas??
You are using the method CFURLCreateStringByAddingPercentEscapes. If a Core Foundation function has "Create" in its name, it means that you own the returned object. In other words, you'll need to release the CFStringRef returned by CFURLCreateStringByAddingPercentEscapes.
NSString *post = [NSString stringWithFormat:#"...", var];
CFStringRef stringRef = CFURLCreateStringByAddingPercentEscapes(...);
post = [NSString stringWithFormat:#"xmlValue=%#",(NSString *)stringRef];
CFRelease(stringRef);
The following code works, but it's ugly and creates a bunch of autoreleased objects. I'm using similar code for parsing reserved HTML characters as well (for quotes, & symbols, etc). I'm just wondering... Is there a cleaner way?
NSString *result = [[NSString alloc] initWithString:userInput];
NSString *result2 = [result stringByReplacingOccurrencesOfString:#"#"
withString:#"\%23"];
NSString *result3 = [result2 stringByReplacingOccurrencesOfString:#" "
withString:#"\%20"];
formatted = [[result3 stringByReplacingOccurrencesOfString:#"&"
withString:#"\%26"] retain];
[result release];
#Yannick, you were on the right track, thank you. stringByAddingPercentEscapesUsingEncoding sort of works but ignores certain characters that can still be a problem (like slashes). Here is the best way to do URL encoding:
NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
kCFStringEncodingUTF8 );
Have you tried to use the stringByAddingPercentEscapesUsingEncoding method?
formatted = [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];