How to encode or decode URL in objective-c - urlencode

Is there something like
+(NSString *) URLencode: (NSString *) someString
+(NSString *) URLdecode: (NSString *) someString
If so, how to implement it?
Note to downvoters. This is NOT a simple question. I need something that can comprehensively do this. For example:
NSString * test = #"汉字马拉松是";
NSString * encoded = [test stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
PO(encoded);
PO(test);
Will yield the following:
2012-06-04 16:04:22.709 BadgerNew[2266:17003] <0xcd890 GrabClass.m:(930)> encoded (null)
2012-06-04 16:04:22.710 BadgerNew[2266:17003] <0xcd890 GrabClass.m:(931)> test 汉字马拉松是
I want my encoding to be able to URL encode EVERYTHING including japanese language, etc.
So I want encoded to contain something along %E6%B1%89%E5%AD%97%E9%A9%AC%E6%8B%89%E6%9D%BE%E6%98%AF
There are 2 different methods in http://mobiledevelopertips.com/networking/a-better-url-encoding-method.html
None are good enough.
I need to be able to encode ALL strings, including japanese/chinese characters.
Update: I followed H2CO3 answer and do this:
NSString * test = #"汉字马拉松是";
NSString * encoded = [test stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
PO(encoded);
PO(test);
PO(encoded);
Work as expected.

You probably want to take a look at the stringByAddingPercentEscapesUsingEncoding and stringByReplacingPercentEscapesUsingEncoding methods.
Encoding example (using ASCII):
NSString* encodedString =
[originalString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Decoding example (using ASCII):
NSString* originalString =
[encodedString stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
EDIT:
If this doesn't give the desired results try replacing NSASCIIStringEncoding with NSUTF8StringEncoding.
Also you might want to try the variant of above methods :
NSString * encodedString =
(NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)originalString,
NULL,
(CFStringRef)#"!*'();:#&=+$,/?%#[]",
kCFStringEncodingUTF8 );
Which will work better in some cases

It's natural that Chinese and Japanese characters don't work with ASCII string encoding. If you try to escape the string by Apple's methods, which you definitely should to avoid code duplication, store the result as a Unicode string. Use one of the following encodings:
NSUTF8StringEncoding
NSUTF16StringEncoding
NSShiftJISStringEncoding (not Unicode, Japanese-specific)

Related

NSURL: Escape Backslash using NSCharacterSet

This may be a duplicate question, but I have checked all over and can't find a working answer for iOS9. -stringByAddingPercentEscapesUsingEncoding has been deprecated. I need to use -stringByAddingPercentEncodingWithAllowedCharacters
Below is the string that needs the backslashes escaped so that the API can authenticate the session and return a response.
NSString *base = #"http://domain.com/interface/?end=imember";
NSCharacterSet *set = [NSCharacterSet URLQueryAllowedCharacterSet];
NSString *key = [#"&client_key=KOB3N6KX9JXF2MRPO5U.BRFYM7TYVE\/16KIJVXZA6R7H\/1LD1K\/JYIYG7IZP2HA7NUYOVNT3CJG==&token=SGD7E9B29TQ.8HIITZ37XW3GLK5OGLZNLCDM=" stringByAddingPercentEncodingWithAllowedCharacters:set];
The standard URL Character sets don't escape the backslashes, I have tried them all:
URLUserAllowedCharacterSet
URLPasswordAllowedCharacterSet
URLHostAllowedCharacterSet
URLPathAllowedCharacterSet
URLQueryAllowedCharacterSet
URLFragmentAllowedCharacterSet
Please if someone could assist, I am rather new to development. Is it possible to create a custom allowed set which includes the backslash?
EDIT:
This is what the url should look like:
http://domain.com/interface/?end=imember&client_key=KOB3N6KX9JXF2MRPO5U.BRFYM7TYVE\/16KIJVXZA6R7H\/1LD1K\/JYIYG7IZP2HA7NUYOVNT3CJG==&token=SGD7E9B29TQ.8HIITZ37XW3GLK5OGLZNLCDM=
The exact solution for you answer is below.I got it from Zaph's answer.That is the better answer than other answer.
NSString *unescaped = #"http://domain.com/interface/?end=imember"];
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(#"escapedString: %#", escapedString);
URL Encoding Character Sets are
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}
URLHostAllowedCharacterSet "#%/<>?#\^`{|}
URLPasswordAllowedCharacterSet "#%/:<>?#[\]^`{|}
URLPathAllowedCharacterSet "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet "#%<>[\]^`{|}
URLUserAllowedCharacterSet "#%/:<>?#[\]^`

Weird error with NSString: No known class method for selector 'stringWithBytes:length:encoding:'

I am attempting to use scanf to assign a value to an NSString, as per the answers to this question by Omar. This is the code, taken straight from progrmr's answer:
char word[40];
int nChars = scanf("%39s", word); // read up to 39 chars (leave room for NUL)
NSString* word2 = [NSString stringWithBytes:word
length:nChars
encoding:NSUTF8StringEncoding];
However, I'm getting an error on the last line that makes absolutely no sense to me:
No known class method for selector 'stringWithBytes:length:encoding:'
What in the world could be causing this error?
And yes, I do have #import <Foundation/Foundation.h> at the top of the file.
NSString does not have a stringWithBytes:length:encoding: class method, but you can use
NSString* word2 = [[NSString alloc] initWithBytes:word
length:nChars
encoding:NSUTF8StringEncoding];
Note however, that scanf() returns the number of scanned items and
not the number of scanned characters. So nChars will contain 1 and not the string length, so you should set nChars = strlen(word) instead.
A simpler alternative is (as also mentioned in one answer to the linked question)
NSString* word2 = [NSString stringWithUTF8String:word];
NSString does not respond to the selector stringWithBytes:length:encoding:. You probably wanted initWithBytes:length:encoding:.
Story in short: you might want to consider a const char C-string suitable initializer for your NSString object. Also, allocate memory before sending any initializer message to the NSString object. I would expect something like:
char word[40];
int nChars = scanf("%39s", word);
NSString *word2 = [[NSString alloc] initWithCString:word encoding:NSASCIIStringEncoding];
Note that initWithCString per design only supports properly null '\0' terminated 8-bit character arrays. For unterminated bytes arrays you have initWithBytes:length:encoding: instead.
For Unicode characters you could consider initWithCharactersNoCopy:length:freeWhenDone:.

URL string escape representation in objective-c? ("percent encoding")

I want to make a very simple task in objective-c under IOS5: convert URL string to its escaped representation.
I tried a lot of ways to do it but neither seemed to work.
I can not make stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding work. It converts letters like áíűőüöúóé but does not convert others like =.
I'd like to have a function like Uri.EscapeDataString ( http://msdn.microsoft.com/en-us/library/system.uri.escapedatastring.aspx ) in .net.
Thanks!
You could add a category to NSString that does something like
- (NSString *)ps_stringByAddingPercentEscapes;
{
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(CFStringRef)self,
NULL,
(CFStringRef)#":/?#[]#!$&’()*+,;=",
kCFStringEncodingUTF8) autorelease];
}
Replace #":/?#[]#!$&’()*+,;=" for the chars that you care about.

Objective-C: Reading contents of a file into an NSString object doesn't convert unicode

I have a file, which I'm reading into an NSString object using stringWithContentsOfFile. It contains Unicode for Japanese characters such as:
\u305b\u3044\u3075\u304f
which I believe is
せいふく
I would like my NSString object to store the string as the latter, but it is storing it as the former.
The thing I don't quite understand is that when I do this:
NSString *myString = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
It stores it as: \u305b\u3044\u3075\u304f.
But when I hardcode in the string:
NSString *myString = #"\u305b\u3044\u3075\u304f";
It correctly converts it and stores it as: せいふく
Does stringWIthContentsOfFile escape the Unicode in some way? Any help will be appreciated.
Thanks.
In the file \u305b\u3044\u3075\u304f are just normal characters. So you are getting them in string. You need to save actual Japanese characters in the file. That is, store せいふく in file and that will be loaded in the string.
You can try this, dont know how feasible it is..
NSArray *unicodeArray = [stringFromFile componentsSeparatedByString:#"\\u"];
NSMutableString *finalString = [[NSMutableString alloc] initWithString:#""];
for (NSString *unicodeString in unicodeArray) {
if (![unicodeString isEqualToString:#""]) {
unichar codeValue;
[[NSScanner scannerWithString:unicodeString] scanHexInt:&codeValue];
NSString* betaString = [NSString stringWithCharacters:&codeValue length:1];
[finalString appendString:betaString];
}
}
//finalString should have せいふく
Something like \u305b in an Objective-C string is in fact an instruction to the compiler to replace it with the actual UTF-8 byte sequence for that character. The method reading the file is not a compiler, and only reads the bytes it finds. So to get that character (officially called "code point"), your file must contain the actual UTF-8 byte sequence for that character, and not the symbolic representation \u305b.
It's a bit like \x43. This is, in your source code, four characters, but it is replaced by one byte with value 0x43. So if you write #"\x43" to a file, the file will not contain the four characters '\', 'x', '4', '3', it will contain the single character 'C' (which has ASCII value 0x43).

Using scanf with NSStrings

I want the user to input a string and then assign the input to an NSString. Right now my code looks like this:
NSString *word;
scanf("%s", &word);
The scanf function reads into a C string (actually an array of char), like this:
char word[40];
int nChars = scanf("%39s", word); // read up to 39 chars (leave room for NUL)
You can convert a char array into NSString like this:
NSString* word2 = [NSString stringWithBytes:word
length:nChars
encoding:NSUTF8StringEncoding];
However scanf only works with console (command line) programs. If you're trying to get input on a Mac or iOS device then scanf is not what you want to use to get user input.
scanf does not work with any object types. If you have a C string and want to create an NSString from it, use -[NSString initWithBytes:length:encoding:].
scanf does not work with NSString as scanf doesn’t work on objects. It works only on primitive datatypes such as:
int
float
BOOL
char
What to do?
Technically a string is made up of a sequence of individual characters. So to accept string input, you can read in the sequence of characters and convert it to a string.
use:
[NSString stringWithCString:cstring encoding:1];
Here is a working example:
NSLog(#"What is the first name?");
char cstring[40];
scanf("%s", cstring);
firstName = [NSString stringWithCString:cstring encoding:1];
Here’s an explanation of the above code, comment by comment:
You declare a variable called cstring to hold 40 characters.
You then tell scanf to expect a list of characters by using the %s format specifier.
Finally, you create an NSString object from the list of characters that were read in.
Run your project; if you enter a word and hit Enter, the program should print out the same word you typed. Just make sure the word is less than 40 characters; if you enter more, you might cause the program to crash — you are welcome to test that out yourself! :]
Taken from: RW.
This is how I'd do it:
char word [40];
scanf("%s",word);
NSString * userInput = [[NSString alloc] initWithCString: word encoding: NSUTF8StringEncoding];
yes, but sscanf does, and may be a good solution for complex NSString parsing.
Maybe this will work for you because it accepts string with spaces as well.
NSLog(#"Enter The Name Of State");
char name[20];
gets(name);
NSLog(#"%s",name);
Simple Solution is
char word[40];
scanf("%39s", word);
NSString* word2 = [NSString stringWithUTF8String:word];
The NSFileHandle class is an object-oriented wrapper for a file descriptor. For files, you can read, write, and seek within the file.
NSFileHandle *inputFile = [NSFileHandle fileHandleWithStandardInput];
NSData *inputData = [inputFile availableData];
NSString *word = [[NSString alloc]initWithData:inputData encoding:NSUTF8StringEncoding];