Proper Encoding for chines character from NSData - iphone

Please help me i'm using below code to get file name.
Here i'm getting NSString from NSData where multipartData is NSMutableArray which contain NSData.
NSString* postInfo = [[NSString alloc] initWithBytes:[[multipartData objectAtIndex:1] bytes] length:[[multipartData objectAtIndex:1] length] encoding:NSUTF8StringEncoding];
I'm getting string like:
Printing description of postInfo:
Content-Disposition: form-data; name="file"; filename="??:??.PNG"
But It should be like:
Printing description of postInfo:
Content-Disposition: form-data; name="file"; filename="华语/華語.PNG"
Thanks in advance.

Obviously the server doesn't encode the response using UTF-8, but probably another Chinese-only encoding. You need to use the Content-Type header to detect which encoding it is, and then find the appropriate NSStringEncoding using the following code;
// set charset to the MIME charset you get from the server
CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)(charset)));
Here is a detailed answer:
// getting the Content-Type header (e.g. "application/json; charset=utf-8")
NSString* header = [[response allHeaderFields] objectForKey:#"Content-Type"];
// getting the MIME type
NSString* charset = nil;
NSArray* contentTypeParts = [header componentsSeparatedByString:#";"];
NSInteger i = 0;
for (NSString* part in contentTypeParts) {
// ignoring first loop (e.g. "application/json")
if (i > 0) {
NSArray* partComponents = [part componentsSeparatedByString:#"="];
if ([partComponents count] == 2 && [#"charset" isEqualToString:[[partComponents objectAtIndex:0] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]]) {
charset = [[partComponents objectAtIndex:1] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
break;
}
}
i++;
}
// converting the MIME type to NSStringEncoding
NSStringEncoding stringEncoding = NSUTF8StringEncoding; // default to UTF8
if (charset) {
stringEncoding = CFStringConvertEncodingToNSStringEncoding(CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)(charset)));
}
// finally you can convert your string properly!
NSString* postInfo = [[NSString alloc] initWithBytes:[[multipartData objectAtIndex:1] bytes] length:[[multipartData objectAtIndex:1] length] encoding:stringEncoding];

Related

ios - How to parse HTML file?

I'm getting HTML content in below format.
wsse:BinarySecurityToken wsu:Id="uuid:07747f2a-4be4-48fa-9654-5e12235f6040" ValueType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
aHR0cCUzYSUyZiUyZnNjaGVtYXMubWNk</wsse:BinarySecurityToken><
In the below code I'm getting
wsu:Id="uuid:07747f2a-4be4-48fa-9654-5e12235f6040" ValueType="http://schemas.xmlsoap.org/ws/2009/11/swt-token-profile-1.0" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
aHR0cCUzYSUyZiUyZnNjaGVtYXMubWNk
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if(_data)
{
NSString* content = [[NSString alloc] initWithData:_data
encoding:NSUTF8StringEncoding];
NSLog(#"Content :%#",content);
NSRange divRange = [content rangeOfString:#"wsse:BinarySecurityToken" options:NSCaseInsensitiveSearch];
if (divRange.location != NSNotFound)
{
NSRange endDivRange;
endDivRange.location = divRange.length + divRange.location;
endDivRange.length = [content length] - endDivRange.location;
endDivRange = [content rangeOfString:#"=<" options:NSCaseInsensitiveSearch range:endDivRange];
if (endDivRange.location != NSNotFound)
{
divRange.location += divRange.length;
divRange.length = endDivRange.location - divRange.location;
NSLog(#"BinarySecurityToken : %#",[content substringWithRange:divRange]);
}
}
[webView loadHTMLString:content baseURL:_url];
}
}
I want the Output as aHR0cCUzYSUyZiUyZnNjaGVtYXMubWNk.
Any ideas? Thanks in advance.
As you discussing you have NSString *token = #"<wsse:BinarySecurityToken>aHR0cCUzYSUyZiUyZnNjaGVtYWd0Sjk0JTNk</wsse:BinarySecurityToken>";
and what the token between tags then you can replace the unwanted character like .
NSString *str = [token stringByReplacingOccurrencesOfString:#"<wsse:BinarySecurityToken>"
withString:#""];;
and then
NSString *correctToken = [str stringByReplacingOccurrencesOfString:#"</wsse:BinarySecurityToken>"
withString:#""];;

ios - How to parse HTML content in ios?

How do I parse HTML file?
I'm getting an HTML file in the below code,I just want to get data in between BinarySecurityToken XML node.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if(_data)
{
//Here am getting the below HTML content
NSString* content = [[NSString alloc] initWithData:_data
encoding:NSUTF8StringEncoding];
}
}
<input type="hidden" name="wa" value="wsignin1.0" />
<input type="hidden" name="wresult"
value="<t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:Lifetime>
<wsu:Created >2013-04-29T11:50:29.895Z</wsu:Created>
<wsu:Expires>2013-04-29T12:00:29.895Z</wsu:Expires>
</t:Lifetime>
<wsp:AppliesTo>
<EndpointReference>
<Address>urn:orin.converse</Address>
</EndpointReference></wsp:AppliesTo>
<t:RequestedSecurityToken>
<wsse:BinarySecurityToken>
aHR0cCUzYSUyZiUyZnNjaGVtYWd0Sjk0JTNk
</wsse:BinarySecurityToken>
Any ideas? Thanks in advance.
You can get using this code
NSRange divRange = [content rangeOfString:#"<wsse:BinarySecurityToken>" options:NSCaseInsensitiveSearch];
if (divRange.location != NSNotFound)
{
NSRange endDivRange;
endDivRange.location = divRange.length + divRange.location;
endDivRange.length = [content length] - endDivRange.location;
endDivRange = [content rangeOfString:#"</wsse:BinarySecurityToken>" options:NSCaseInsensitiveSearch range:endDivRange];
if (endDivRange.location != NSNotFound)
{
divRange.location += divRange.length;
divRange.length = endDivRange.location - divRange.location;
NSLog(#"BinarySecurityToken : %#",[content substringWithRange:divRange]);
}
}
Output :
aHR0cCUzYSUyZiUyZnNjaGVtYWd0Sjk0JTNk
You need and XML parser for that.
There's a tutorial here
For this particular case you can get the ranges of <wsse:BinarySecurityToken> and </wsse:BinarySecurityToken>, construct new range that will provide you location of the token, and get substring in that range.
Sample code:
NSRange openingTagRange = [htmlString rangeOfString:#"<wsse:BinarySecurityToken>"];
NSRange closingTagRange = [htmlString rangeOfString:#"</wsse:BinarySecurityToken>"];
NSRange tokenRange = NSMakeRange(openingTagRange.location + openingTagRange.length, closingTagRange.location - (openingTagRange.location + openingTagRange.length));
NSString *token = [htmlString substringWithRange:tokenRange];
Since your input comes from outside, you should probably check if the ranges' locations are not equal to NSNotFound.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"];
NSData * data = [NSData dataWithContentsOfFile:filePath];
TFHpple * tutorialsParser = [[TFHpple alloc] initWithHTMLData:data];
NSString *query = #"//div[#id='BinarySecurityToken']";
NSArray *nodes = [tutorialsParser searchWithXPathQuery:query];
for (TFHppleElement * element in nodes) {
NSLog(#"%#", element);
NSLog(#"%#", [element tagName]);
NSLog(#"%#", [element attributes]);
NSLog(#"%#", [element children]);
for (TFHppleElement *childElement in [element children]) {
NSLog(#"%#", childElement);
}
}
hope this will help you For more try this blog and Git Project Resource may help you and
Good blog by RAYWENDERLICH
or another option if you have all the HTML data in NSString you can get data between specific NSString with this function.
-(NSString*)stringBetweenString:(NSString*)start andString:(NSString)end {
NSRange startRange = [self rangeOfString:start];
if (startRange.location != NSNotFound) {
NSRange targetRange;
targetRange.location = startRange.location + startRange.length;
targetRange.length = [self length] - targetRange.location;
NSRange endRange = [self rangeOfString:end options:0 range:targetRange];
if (endRange.location != NSNotFound) {
targetRange.length = endRange.location - targetRange.location;
return [self substringWithRange:targetRange];
}
}
return nil;
}

How to convert properly from NSData to NSString?

I'm getting weird NSString value after performing a conversion. For example, I have one byte with value 2 (00000010) that is stored in response. I tried both NSString initWithData and initWithBytes but both return weird symbol (upside down question mark). Here's my code:
NSString *command1 = [[NSString alloc] initWithData:response encoding:NSASCIIStringEncoding];
NSString *command2 = [[NSString alloc] initWithBytes:[response bytes] length:[response length] encoding:NSASCIIStringEncoding];
NSLog(#"command1: %#", command1);
NSLog(#"command2: %#", command2);
Also tried NSUTF8StringEncoding but NSASCIIStringEncoding is correct one because data comes encoded one byte per symbol.
From what I am reading, this is what you want:
NSString *stringWithContentsOfBinaryData(NSData *data)
{
NSMutableString *output;
int len = [data length];
uint8_t *bytes = [data bytes];
for (int i = 0; i < len; i++)
{
[output appendFormat:#"%i", bytes[i]];
}
return output;
}
It just simply converts each byte to it's integer representation and concatenates that into a string.
ASCII is not necessarily the right encoding. ASCII only defines characters between 0x00 and 0x7F. If response is an HTTP response, and the encoding is not specified in the HTTP Content-Type header, the default is ISO-8859-1 for which you should use NSISOLatin1StringEncoding
And it doesn't matter what encoding you use: control characters (0x00 - 0x1F) aren't necessarily printable.

NSXML parsing error when used with NSData

I have a simple XML file containing a subset list of products. When I load the file from the iOS App bundle and send it through the parser with: initWithNSURL, with an NSURL pointing to the local file it parses correctly.
However if I download the same file via an NSURLConnection and pass it to the parser with initWithData, the parsing fails. I can confirm the data is being downloaded correctly because if I perform NSString *temp = [NSString stringWithUTF8String:[downloadedData bytes]]; the outputted string is correct.
I have a guy feeling it's sometime to do with encoding somewhere along the line, any thoughts?
My friend do the parser job,
NSString* xmlData = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
xmlData should look like
abc
and my friend just analyze the string,and it's work
and I used libxml2 to parse xml with
xmlTextReaderPtr reader = xmlReaderForMemory([data bytes], [data length], NULL, NULL, (XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING));
if (reader != NULL) {
ret = xmlTextReaderRead(reader);
while (ret == 1) {
const xmlChar *name, *value;
name = xmlTextReaderConstName(reader);
if (name == NULL)
name = BAD_CAST "--";
NSString *Name = [NSString stringWithCString:(const char*)name encoding:NSUTF8StringEncoding];
value = xmlTextReaderConstValue(reader);
if (value == NULL)
value = BAD_CAST "\n";
NSString *Value = [NSString stringWithCString:(const char*)value encoding:NSUTF8StringEncoding];
NSLog("%d %d %# %d %#",
xmlTextReaderDepth(reader),
xmlTextReaderNodeType(reader),
Name,
xmlTextReaderIsEmptyElement(reader),
Value);
ret = xmlTextReaderRead(reader);
}
xmlFreeTextReader(reader);
}
and result is correct too

NSString to NSData conversion Problem

I have some Bytes of image in my string and i want to draw it to UIImageView ...Here is my code
NSString* str= #"<89504e47 0d0a1a0a 0000000d 49484452 ........... 454e44ae 426082>";
NSData* data=[str dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"My NSDATA %#",data);
imageView.image=[UIImage imageWithData:data];
Now when i saw that printed data on console it is not in same format what i gave to that string..The output is something like.....
<3c383935 30346534 37203064 30613161..........
So my imageview show nothing..... please help
if question was: How to convert string data to image then this is answer.
NSData *imgData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"icon" ofType:#"png"]];
// set your string data into inputString var
NSString *inputString = [imgData description];
NSLog(#"input string %#",inputString);
// clearing string from trashes
NSString *dataStr = [inputString stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"<>"]];
// separate by words of 4 bytes
NSArray *words = [dataStr componentsSeparatedByString:#" "];
// calculate number of bytes
NSArray *sizes = [words valueForKey:#"length"];
int sizeOfBytes = 0;
for (NSNumber *size in sizes) {
sizeOfBytes += [size intValue]/2;
}
int bytes[sizeOfBytes];
int counts = 0;
for (NSString *word in words) {
// convert each word from string to int
NSMutableString *ostr = [NSMutableString stringWithCapacity:[word length]];
while ([word length] > 0) {
[ostr appendFormat:#"%#", [word substringFromIndex:[word length] - 2]];
word = [word substringToIndex:[word length] - 2];
}
NSScanner *scaner = [NSScanner scannerWithString:ostr];
unsigned int val;
[scaner scanHexInt:&val];
bytes[counts] = val;
counts++;
}
// get NSData form c array
NSData* data = [NSData dataWithBytes:bytes length:sizeOfBytes];
NSLog(#"My NSDATA %#",data);
// your image is ready
UIImage *image = [UIImage imageWithData:data];
NSLog(#"image: %#",image);
what you are seeing in NSLog output are the ASCII codes of the string characters.
for example:
NSString* str = #"A";
NSData* data=[str dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#",data);
you will see something like:
<41....
that's because 0x41 is the code for letter A.
Same is happening with your string.
The data is exactly what you're feeding it: a simple string (printed as raw byte values). But I guess your input string is a hexdump and you manually need to turn into bytes.