In my program, I'm allowing the user to input some words into a textfield. Then my program will use these words to form a html string. The string will then be used in NSURL so I can connect to the website.
This method works great for english words. But when I input some chinese (or korean) in there, I does not work. Thus I believe that I need to convert the inputed data before passing it to NSURL. However I could not find a way to do this.
Here's an example of how my code looks like.
NSString *searchedString = theSearchBar.text;
NSString *urlToBeSearched = [[NSString alloc]
initWithFormat:#"http://www.awebsite.com/search/%#",
searchedString];
NSURLRequest *urlRequest = [[NSURLRequest alloc]
initWithURL:[NSURL URLWithString:urlToBeSearched]
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:50];
NSURLConnection *tempCon =[[NSURLConnection alloc] initWithRequest:urlRequest
delegate:self];
Then of course releasing them later.
For example, when searchedString = 你好, the urlLink will be http://www.awebsite.com/search/你好. NSURLConnection doesn't like that and will give me "Bad Url" error.
However, if the urlLink is "%E4%BD%A0%E5%A5%BD" it will give me the correct link.
The set of characters allowed in a URI is pretty much limited to a subset of US-ASCII (see RFC2396). That means your Chinese characters must be percent escaped in the URI. The documentation for NSURL +URLWithString: says the string must conform to the RFC so you need to percent escape the string before calling that method.
Fortunately, NSString has a method that will allow you to do that called -stringByAddingPercentEscapesUsingEncoding:. You still need to choose a suitable encoding and which one you choose depends on how the server decodes the URL string. The easiest option is probably to use UTF-8 at both ends. You need to do something like:
NSString* searchedString = [theSearchBar.text stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
NSString* urlToBeSearched = [NSString stringWithFormat:#"http://www.awebsite.com/search/%#", searchedString];
// everything else the same, except you don't need to release urlToBeSearched
Did you try encoding your search-string?
[NSString stringByAddingPercentEscapesUsingEncoding:/encoding-of-choice/];
Not sure what encoding you would use for chinese characters though.
Related
I have a strange text encoding problem that I can't figure out. The strange this is that if you check out the text online from the API feed in a browser the text doesn't need any formatting.
Here's my code:
-(void) viewDidLoad {
[super viewDidLoad];
NSString *jsonDealString = [NSString stringWithFormat:#"http://api.*****"];
NSLog(#"deal id is %#",dealId);
// Download the JSON
NSString *jsonString = [NSString
stringWithContentsOfURL:[NSURL URLWithString:jsonDealString]
encoding:NSStringEncodingConversionAllowLossy|NSUTF8StringEncoding
error:nil];
// Create parser for the api
SBJSON *parser = [[SBJSON alloc] init];
NSDictionary *results = [parser objectWithString:jsonString error:nil];
[self setDisplayItems:[results objectForKey:#"results"]];
NSDictionary *item = (NSDictionary *)[displayItems objectAtIndex:0];
self.titleDeal.text = [item objectForKey:#"title"];
}
I was able to correct the text encoding problem using:
// merchant name with encoding fix
NSString *correctStringTitleDeal = [NSString stringWithCString:[[[item objectForKey:#"merchant"] objectForKey:#"name"] cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding];
self.titleDeal.text = correctStringTitleDeal;
But that caused a crash when a Null object was encountered.
my crash log output states:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* +[NSString stringWithCString:encoding:]: NULL cString'
Here's a screenshot of the problem occurring in a table view (it's occurring elsewhere in the app too):
thanks for any help
The crash is because you are sending a message to a c-string, not to an object. cstringUsingEncoding: gives a c-string and you cannot do things like encode:
For the encoding problem, if you can read well the text from the API using a browser, then it is encoded for HTML instead of unicodes in UTF8 form.
Short answer: Find out the string encoding of the API and use it.
Longer answer:
The most likely cause of encoding problems is that the JSON isn't in UTF-8. JSON is required by spec to be in some form of Unicode (see RFC4627 Section 3). The speicifc encoding is determined by the first four octets. Again, see the spec.
Your passing of NSStringEncodingConversionAllowLossy is extremely suspicious. You should not be allowing lossy conversion. You should know the specific encoding of the API and you should use it. Similarly, you switch encoding in your other example code to NSISOLatin1StringEncoding. While this is similar to some Unicode, it is not a Unicode encoding as so never should be used for JSON.
It's of course possible that this particular API is in violation of spec and is sending badly encoded JSON. You can either work with the API provider to fix their JSON, or you can use whatever encoding they are providing. But you shouldn't guess, and you definitely shouldn't accept lossy conversions.
I am working on loading images into a gallery on the iPhone and running into an issue. It is apparent that something in the script isn't happy with spaces being in filename's when trying to download the images off of the internet.
This is the connection line.
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:str]] delegate:self];
And I pass an NSString in the NSURL. It works on all photos that don't have spaces.
Example of evil photos:
thumbs_WJ (16).jpg
thumbs_WJ (25).jpg
Now I know I could go back and update all the photos, update the database, and change the script so it doesn't add spaces anymore...but we are talking about thousands of photos.
And suggestions?
you need to do string:
str =[str stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
Use NSString's stringByAddingPercentEscapesUsingEncoding: method on the text you want to include as an argument.
From Apple docs:
stringByAddingPercentEscapesUsingEncoding:
Returns a representation of the receiver using a given encoding to determine the percent escapes necessary to convert the receiver into a legal URL string.
If your string is a "normal" string, you can use NSUTF8StringEncoding as encoding. Otherwise, specify the encoding your string is in.
Just replace spaces with "%20" in your urlstring.
I am trying to use an http request to google maps to obtain the driving distance between two locations using JSON. However, it seems these are treated different in a browser than in the (iphone) app.
I create an NSString which holds the URL, using coordinates and %20 (a space). I NSLog() the URL to make sure, and it seems ok (ie it works fine in browser and looks fine)...but when NSLogging the string initialised with the contents of that URL, I get (null).
Here is the code:
NSString *urlString=[[NSString alloc] initWithFormat:#"http://maps.google.com/maps/nav?q=from:%.7f%#%.7f%#to:%.7f%#%.7f", testLocation.coordinate.latitude, #"%%20", testLocation.coordinate.longitude, #"%%20", thePark.coordinate.latitude, #"%%20", thePark.coordinate.longitude];
which I then NSLog() and get http://maps.google.com/maps/nav?q=from:51.4986110%20-0.1236110%20to:51.4960938%20-0.2200041 ...to no avail.
NSString *json=[[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:urlString]];
When I NSLog() this, it prints null. Does anyone have any suggestions as to why this might be happening or an easier way to do it? I plan to then parse the JSON and get the drving distance
You should escape the urlString using "stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding" instead of escaping manually with %20.
Edit:
I tested with these 3 lines of codes and I got the json string.
NSString *urlString=[[[[NSString alloc] initWithFormat:#"http://maps.google.com/maps/nav?q=from:%.7f %.7f to:%.7f %.7f", 51.4986110, -0.1236110, 51.4960938, -0.2200041] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] autorelease];
NSString *json=[[[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:urlString]] autorelease];
NSLog(#"json = %#", json);
How do I use comma-separated-values received from a URL query in Objective-c?
when I query the URL I get csv such as ("OMRUAH=X",20.741,"3/16/2010","1:52pm",20.7226,20.7594).
How do I capture and use this for my application?
You have two options:
Use a CSV parser: http://freshmeat.net/projects/ccsvparse
Or parse the data yourself into an array:
// myString is an NSString object containing your data
NSArray *array = [myString componentsSeparatedByString: #","];
I recently dealt with CSV parsing for Yahoo! Finance as well. I used Ragel to write a parser in C that was good enough for the CSV I was getting. It handled everything but escaped quotes, which are not going to show up much in stock quotes. It was pretty painless and a good learning experience. I'd post the code, but it was work-for-hire, so I don't own it.
Turning a C string into an NSString is easy. If you have it as an NSData, as you likely do at the end of a URL download, just do [[NSString alloc] initWithData:csvData encoding:NSUTF8StringEncoding]. If you have a pointer to a character buffer instead, use [[NSString alloc] initWithBytes:buffer length:buflen encoding:NSUTF8StringEncoding]. buflen could be strlen(buffer) if buffer is a normal, NUL-terminated C string.
So I'm fetching a JSON string from a php script in my iPhone app using:
NSURL *baseURL = [NSURL URLWithString:#"test.php"];
NSError *encodeError = [[NSError alloc] init];
NSString *jsonString = [NSString stringWithContentsOfURL:baseURL encoding:NSUTF8StringEncoding error:&encodeError];
NSLog(#"Error: %#", [encodeError localizedDescription]);
NSLog(#"STRING: %#", jsonString);
The JSON string validates when I test the output. Now I'm having an encoding issue. When I fetch a single echo'd line such as:
{ "testKey":"é" }
The JSON parser works fine and I am able to create a valid JSON object. However, when I fetch my 2MB JSON string, I get presented with:
Error: Operation could not be completed. (Cocoa error 261.)
and a Null string. My PHP file is UTF8 itself and I am not using utf8_encode() because that seems to double encode the data since I'm already pulling the data as NSUTF8StringEncoding. Either way, in my single-echo test, it's the approach that allowed me to successfully log \ASDAS style UTF8 escapes when building the JSON object.
What could be causing the error in the case of the larger string?
Also, I'm not sure if it makes a difference, but I'm using the php function addslashes() on my parsed php data to account for quotes and such when building the JSON string.
I'm surprised no one has mentioned using a different encoding value instead of NSUTF8StringEncoding when calling [NSString stringWithContentsOfFile:encoding:error:].
I also got Cocoa error 261 when parsing a JSON file. I just went through the list of NSString encodings until one worked. Fortunately the first one worked for me: NSASCIIStringEncoding!
You can also use NSString stringWithContentsOfFile:usedEncoding:error: to try to find the correct encoding (as described here: How to use stringWithContentsOfURL:encoding:error:?).
Don't know if this is your problem, but I just had a similar thing (stringWithContentsOfFile, no JSON), and the problem was that the file had CRLF (windows) line-endings and Western-whatever-it's-called encoding. I used SubEthaEdit to convert to LF (Mac/Unix line-endings) and UTF-8 encoding, and now everything works fine.
Encoding issue: Cocoa Error 261? I solved this issue by trying different encoding. First I was using NSUTF8 then I switched to NSASCIIStringEncoding and it worked.
NSString* path = [[NSBundle mainBundle] pathForResource: #"fileName" ofType: #"type"];
NSData* data = [NSData dataWithContentsOfFile:path];
NSString *string = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"%#",string);
For future reference, if you need to override the encoding, and you're working with streams without embedded NULs, something like this might be good (I've just written a rough sketch outline here, check this code is and does want you want before using it):
NSHTTPURLResponse* resp=nil;
NSData* jsonAsImmutableData = [NSURLConnection sendSynchronousRequest:
[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://<whatever>"]]
returningResponse:&resp error:NULL];
NSMutableData*modifiedData = [NSMutableData dataWithData:jsonAsImmutableData];
char extraNulls[7] =
{0,0,0,0,0,0,0}; // is this defensive enough for your encoding?
[modifiedData appendBytes:extraNulls length:7];
NSString* jsonAsString = [NSString stringWithCString:[modifiedData bytes]
encoding:<whatever your encoding is>];
But I expect your best course of action is to check that your server is both using and claiming to use UTF-8 encoding or some other Apple iPhone supported encoding.
EDIT
altered code comment.
What helped me was just to change the physical file encoding to UTF-8. My editor had set it to the default, MacRoman, and didn't like letters with accents.